8
$\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$
6
  • $\begingroup$ Is it necessary to update the mesh before returning the newly created object? $\endgroup$
    – satishgoda
    Jun 19, 2013 at 17:46
  • $\begingroup$ everything that I have read says that it should be updated, so I have. $\endgroup$ Jun 19, 2013 at 19:20
  • $\begingroup$ I was thinking it should be obj.update() and not mesh.update().. $\endgroup$
    – satishgoda
    Jun 20, 2013 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$ Jun 20, 2013 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, 2013 at 7:30

4 Answers 4

8
$\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$
5
  • 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$ Jun 20, 2013 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$ Jun 20, 2013 at 9:49
  • $\begingroup$ Excellent :) Looking forward to your script. $\endgroup$
    – satishgoda
    Jun 20, 2013 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, 2013 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, 2013 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$
5
  • $\begingroup$ Will the garbage collector not reclaim the memory since it was orphaned? $\endgroup$
    – satishgoda
    Jun 19, 2013 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, 2013 at 19:23
  • $\begingroup$ Ahh.. I see what you mean. Looks like Adhi updated his answer as well. Cool. Thanks. $\endgroup$
    – satishgoda
    Jun 20, 2013 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$ Jun 20, 2013 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$ Jun 20, 2013 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$
2
  • $\begingroup$ Thats interesting. It doesn't make a huge difference but it does help and you can tell it works $\endgroup$ Jun 21, 2013 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, 2013 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$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .