7
$\begingroup$

In my script I am importing a large amount of objects (+2500) but sharing the mesh data from one single primitive. While this has taken care of importing speed, it completely slows blender down. However when I import as individual primitives blender is very responsive even with + 2500 objects.

Why does blender slow down (frame rate, buttons, etc) when sharing mesh data blocks and is there anyway to aliviate this?

Code:

def create_mesh(name, radius, locat):
    #print (fList)

    # Create mesh and object
    mesh = bpy.data.meshes.new('Sphere')
    mesh = bpy.data.meshes['Primary']
    obj = bpy.data.objects.new('Shpere', mesh)
    #obj.show_name = True
    obj.scale = (radius, radius, radius)
    obj.location = locat 

    # Link object to scene and make active
    scn = bpy.context.scene
    scn.objects.link(obj)
    #scn.objects.active = obj
    #obj.select = True


    # Update mesh with new data
    mesh.update() 

    return obj
$\endgroup$
  • $\begingroup$ Is it necessary to update the mesh before returning the newly created object? $\endgroup$ – satishgoda Jun 19 '13 at 17:46
  • $\begingroup$ everything that I have read says that it should be updated, so I have. $\endgroup$ – Defor Mations Jun 19 '13 at 19:20
  • $\begingroup$ I was thinking it should be obj.update() and not mesh.update().. $\endgroup$ – satishgoda Jun 20 '13 at 4:08
  • $\begingroup$ I'm not sure what you would update in the obj. AFAIK mesh.update() is to update the mesh to display correctly after working with it. $\endgroup$ – Defor Mations Jun 20 '13 at 5:25
  • $\begingroup$ Actually.. there is no method called update() on objects.. I stand corrected.. I am taking your code and doing some tests.. will post my observations in sometime.. Cheers. $\endgroup$ – satishgoda Jun 20 '13 at 7:30
7
$\begingroup$

I would like to share some stats that I gathered after doing some tests. I think what you are facing could be viewport performance issues and nothing really about Python. Those issues can be improved by following some optimizations (which are demonstrated below)

One Suzanne mesh linked to 7497 Objects

In the viewport, with all the objects selected, I invoked the Redraw Timer operator (CTRL+ALT+T) and chose Draw Region + Swap option for the following cases

With Outline Selected checked on (under Display Panel of Properties Panel N)

Warning: 10 x Draw Region and Swap: 9437.80 ms,  average: 943.7801

With Outline Selected checked off

Warning: 10 x Draw Region and Swap: 7264.04 ms,  average: 726.4040

With Outline Selected checked off and VBOs Checked On (Sunder System Tab of User Preferences Editor CTRL+ALT+U)

Warning: 10 x Draw Region and Swap: 1672.37 ms,  average: 167.2374

All 7497 Objects having their own copies of Suzanne Mesh

and following similar test cases as above, I got the following results

Warning: 10 x Draw Region and Swap: 7910.51 ms,  average: 791.0507

Warning: 10 x Draw Region and Swap: 5558.50 ms,  average: 555.8497

Warning: 10 x Draw Region and Swap: 1815.82 ms,  average: 181.5816

I hope this helps in what you are doing.

Lots of Linked Meshes Test

Note: The VBOs checkbox below the Backface Culling was customized by me (by editing the python user interface files). VBOs setting is actually present in the User Preferences Editor.

$\endgroup$
  • 2
    $\begingroup$ These have all helped. Also, instead of using uv_spheres I have switched to nurbs spheres and that has helped a lot. And I didn't know about the Redraw Timer. Thanks for that, this will be extremely useful optimizing the importer. When I get this working well, I'll post what I did. $\endgroup$ – Defor Mations Jun 20 '13 at 9:45
  • 1
    $\begingroup$ 2500 nurbs spheres with a material slot but no material: Draw Region + Swap - Warning: 10 x Draw Region and Swap: 2282.79 ms, average: 228.2791 and this is working far better than it was before. I starting to think that this might be my system although I have 16gb ram on a Imac27 I5 and ATI 512mb. $\endgroup$ – Defor Mations Jun 20 '13 at 9:49
  • $\begingroup$ Excellent :) Looking forward to your script. $\endgroup$ – satishgoda Jun 20 '13 at 9:49
  • 1
    $\begingroup$ @satishgoda why did you make this wiki? It doesn't need to be. I changed it back. $\endgroup$ – iKlsR Jun 20 '13 at 21:13
  • $\begingroup$ @iKlsR Was not sure if this was an answer that directly answers the question.. That is why. Thank you for taking the appropriate action. Cheers. $\endgroup$ – satishgoda Jun 21 '13 at 3:36
9
$\begingroup$

You're sharing one object data (Primary) among +2500 objects, but with this line:

bpy.data.meshes.new('Sphere')

... you're also creating +2500 orphan mesh data. It's easy to add several MBs to Blender's memory usage (verifiable through System Monitor), just running that bit of code:

import bpy

for i in range(1, 2500):
    bpy.data.meshes.new('Sphere')

The orphaned obdatas won't be reclaimed until loading new scene or quitting (to see them, select a mesh object, click the dropdown button to the left of the obdata's name in Properties area's Object Data tab). For scenes large enough, in systems with low RAM, this could slow down the whole system.

$\endgroup$
  • $\begingroup$ Will the garbage collector not reclaim the memory since it was orphaned? $\endgroup$ – satishgoda Jun 19 '13 at 17:48
  • 3
    $\begingroup$ probably not until the file is saved/reopened? Since I believe we are talking about BPY objects, not plain python objects. $\endgroup$ – Mike Pan Jun 19 '13 at 19:23
  • $\begingroup$ Ahh.. I see what you mean. Looks like Adhi updated his answer as well. Cool. Thanks. $\endgroup$ – satishgoda Jun 20 '13 at 4:09
  • $\begingroup$ However, that doesn't explain why when I import and create a separate "primitive" for each line, blender doesn't have those memory issues. BTW, I tried saving and reopening the file and that doesn't help at all. $\endgroup$ – Defor Mations Jun 20 '13 at 5:16
  • $\begingroup$ I have updated the code to: mesh = bpy.data.meshes('Primary') however this doesn't do anything to help the issue $\endgroup$ – Defor Mations Jun 20 '13 at 5:30
2
$\begingroup$

The answer provided by @satishgoda also reminded me of a suggestion by PsyFi or Sabiantian_k.

Closing the outliner can speed up the viewport performance as the data view is is constantly being polled for updates. As the number of objects being checked for updates increase, it impacts performance.

$\endgroup$
  • $\begingroup$ Thats interesting. It doesn't make a huge difference but it does help and you can tell it works $\endgroup$ – Defor Mations Jun 21 '13 at 5:54
  • $\begingroup$ Yeah it was just a random funny point they brought up about their time during the TOS project. They were thinking about making it more dynamic in what it actually polled but not sure if it was actually submitted as a feature improvement. It might already be that way. $\endgroup$ – neomonkeus Jun 21 '13 at 13:31
1
$\begingroup$

You absolutely need to factor scn.objects.link(obj) out of your function and place it in a separate loop, so that creation and linkage of objects to the scene are separated between different loops. When you use scn.objects.link(obj) whithin the same iteration where you create object, blender updates all the scene every iteration. See answer https://blender.stackexchange.com/a/7360/3153 with comments to it. Your code may transform to something like this:

def create_mesh(name, radius, locat):
    mesh = bpy.data.meshes['Primary']
    obj = bpy.data.objects.new(name, mesh)
    obj.scale(radius, radius, radius)
    obj.location = locat 
    return obj

obs = []
for name, radius, locat in params2500:
    o = create_mesh(name, radius, locat)
    obs.append(o)

sc = bpy.context.scene
for o in obs:
    sc.objects.link(o)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.