Notifications
Clear all

[Closed] enumeratefiles slow for selection, fast for all scene

(  
 	local mapfiles=#()
 	fn addmap mapfile =
 	(
 		local mapfileN=mapfile-- as name
 		local index=finditem mapfiles mapfileN
 		if index == 0 do append mapfiles mapfileN
 	)   
 	mapfiles=#()
 	
 	--for all scene
 	start = timestamp()
 	enumeratefiles addmap
 	end = timestamp()
 	  format "Enumerate for all scene took % seconds
" ((end-start)/1000.0)
 	
 	
 	--for selection
 	start = timestamp()
 	for node in selection do
 			enumeratefiles node addmap
 	end = timestamp()
 	  format "Enumerate for selection took % seconds
" ((end-start)/1000.0)
 	
 	start = timestamp()
 	fn Completed sender arg =
 	(
 		sender.Dispose();
 		end = timestamp()
 		format "Enumerate for selection with BGWorker took % seconds
" ((end-start)/1000.0)
 		--print mapfiles
 	 )	
 	  
 	fn EnumF sender arg =
 	(
 		for node in selection do
 		(	
 			enumeratefiles node addmap --#missing
 		)	
 	)
 	  
 	fn ScanFiles = 
 	(	
 		local thread = dotnetobject "System.ComponentModel.BackGroundWorker";
 		dotnet.addeventhandler thread "DoWork" EnumF ;
 		dotNet.addeventhandler thread "RunWorkerCompleted" Completed;
 		thread.RunWorkerAsync "selection";
 		thread.IsBusy;
 	)
 	ScanFiles() 
 	
 	--print mapfiles
 	
 )	

For a scene with 2491 objects selected and 68 texture maps I get such such results:

Enumerate for all scene took 0.081 seconds
Enumerate for selection took 14.262 seconds
Enumerate for selection with BGWorker took 14.54 seconds

It seams that it should work faster for selection, but it soesn’t. If I don’t use BGWorker for selection then UI is become busy for a while. Tell me please, do you have a better solution then me may be…?

Thx in advance!

4 Replies
1 Reply
(@polytools3d)
Joined: 1 year ago

Posts: 0

Yes, it might take longer for selections. Can’t you use usedMaps() instead?
Check out the following tests:

(
	local mapfiles, calls
	
	fn addmap mapfile =
	(
		calls += 1
		appendifunique mapfiles mapfile
	)
	
	fn RunTests =
	(
		--ALL NODES
		mapfiles=#(); calls=0
		st = timestamp(); sh = heapfree
		enumeratefiles addmap
		format "all:%ms ram:%	files:%	calls:%
" (timestamp()-st) (sh-heapfree) mapfiles.count calls
		
		--sleep 1; gc()
		
		--SELECTION
		mapfiles=#(); calls=0
		st = timestamp(); sh = heapfree
		for node in selection do enumeratefiles node addmap
		format "sel:%ms ram:%	files:%	calls:%
" (timestamp()-st) (sh-heapfree) mapfiles.count calls
		
		--sleep 1; gc()
		
		mapfiles=#()
		st = timestamp(); sh = heapfree
		for node in selection do join mapfiles (usedmaps node)
		mapfiles = makeuniquearray mapfiles
		format "sel:%ms ram:%	files:%
" (timestamp()-st) (sh-heapfree) mapfiles.count
	)

	max create mode
	
	/* TEST 1 */
	format "TEST 1
"
	delete objects; gc()
	map = bitmaptexture filename:"NO_BITMAP"
	mat = standard diffusemap:map specularmap:map bumpmap:map opacitymap:map
	for j = 1 to 1000 do box lengthsegs:1 widthsegs:1 heightsegs:1 material:mat
	max select all
	RunTests()
	
	/* TEST 2 */
	format "
TEST 2
"
	delete objects; gc()
	map = bitmaptexture filename:"C:\\MISSING_BITMAP.PNG"
	mat = standard diffusemap:map specularmap:map bumpmap:map opacitymap:map
	for j = 1 to 1000 do box lengthsegs:1 widthsegs:1 heightsegs:1 material:mat
	max select all
	RunTests()
	
	/* TEST 3 */
	format "
TEST 3
"
	delete objects; gc()
	tx = bitmap 128 128 color:red filename:"C:\\TEST_BITMAP.PNG"
	save tx; close tx
	map = bitmaptexture filename:tx.filename
	mat = standard diffusemap:map specularmap:map bumpmap:map opacitymap:map
	for j = 1 to 1000 do box lengthsegs:1 widthsegs:1 heightsegs:1 material:mat
	max select all
	RunTests()
	
	deletefile tx.filename
)

I get this results:
TEST 1
– all: 2ms ram:64L files:0 calls:0
– sel:18ms ram:64L files:0 calls:0
– sel:12ms ram:72136L files:0

– TEST 2
– all: 3ms ram:64L files:0 calls:0
– sel:1113ms ram:64L files:0 calls:0
– sel: 22ms ram:72136L files:0

– TEST 3
– all: 2ms ram:184L files:1 calls:1
– sel:206ms ram:960080L files:1 calls:8000
– sel: 51ms ram:136136L files:1

I tested your script on a scene I have with a few thousands objects and a few thousands file assets…enumerating all the assets took ~1.5 seconds, and enumerating random selections of hundreds of objects took ~0.5seconds each time.

Maybe there’s some other issue at play in your scene?

Hey, Jorge! Thank you very much for your post.

Here is an example

all:11ms ram:384L files:4 calls:5
sel:14550ms ram:6567576L files:4 calls:54976
sel:4349ms ram:674384L files:4

for selection it takes really long, but anyway with used maps it’s faster.
Does usedmaps function scan all maps in modifiers, Ies in lights as well? does it work with missed maps?

UsedMaps() should work with modifiers, lights, etc. but AFAIK, they won’t return missing images.

Also, as it works "per instance", in the scene you uploaded it should be a lot faster to scan for materials instead of nodes, as there are 2 materials in the scene but and 1700 nodes. Something like:
for mat in scenematerials do join mapfiles (usedmaps mat)

But then you would need to know if there are no modifiers, and such things.

I don’t remember any mayor problem using it, but I would search on the forum to make sure it will work as you need.