-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FBXLoader: replace for loops with array builtins and tidy code #12739
Conversation
Similarly to a previous PR. I remember adding these for loops to avoid instantiation of new functions. For loops tend to perform much faster than forEach. The main goal at the time was to speed up parsing and avoid garbage collection. Have you had a look at Chrome Dev Tools' performance tab to see how these changes affect? |
Have you read Code style? https://github.com/mrdoob/three.js/wiki/Mr.doob%27s-Code-Style%E2%84%A2#cycles |
Yes, I did quite a bit of performance testing as I was making this PR - at first I was making sure to just replace small loops (max 10 - 100 loops), but even testing against large loops (the geometry creation function and the text parser) I didn't see any evidence of slowing down, at least in Chrome. If you prefer, I can undo the changes to large loops. For smaller loops (let's say, likely to be less than 100 loops), the performance difference is negligible and forEach is much more readable. I'll do some more testing with and without this PR and report on performance differences. |
I prefer keeping the current |
That seems redundant to me. I'd rather it be the other way - In any case, I'll test when I have time later today - it's possible that the performance differences between |
I think you should've first made an issue to discuss if we should make |
Sounds good! Curious to see the results 👌 |
OK, here's the results of some initial testing on my laptop. ModelsTested with three models:
Methodology:Testing parsing time wrapping the the console.time( 'Parsing took: ' );
var scene = self.parse( buffer, resourceDirectory );
console.timeEnd( 'Parsing took:' ); Tested memory use in Chrome using the dev tool performance tab and reloading the page. Browsers:All files loaded from local file system on Windows 10, caching disabled.
Firefox updated to the "quantum" version half way through testing so I had to redo those 😕 Results:For reach pair of numbers below, the first is running the wafp.bin.fbx (binary, compressed)Chrome, FireFox , Edge , wafp.fbx (ASCII)Chrome, FireFox , Edge , xsi_man_skinning.fbx (binary, uncompressed)Chrome, FireFox , Edge , Thoughts:There seems to be very little difference between Deviation in results on FireFox and Chrome was very small (except for a couple of outliers, most of the runs I used to get the average were within 100ms of each other) - and it seems like using Deviation in Edge was large (up a second difference between tuns on the ASCII file) so the results there are not so conclusive. Except that they show how slow Edge is compared to the other two. |
Update: Brave Browser( Chromium based ) on AndroidDid some testing on my old Moto G3 Android phone using the Brave browser which is based on Chromium v62.03. Again, the results show very little difference. I would say these are a bit less accurate though as I kept getting "context lost" errors and deviation was up to a couple of seconds between runs. wafp.bin.fbx (binary, compressed)Brave, wafp.fbx (ASCII)Brave, xsi_man_skinning.fbx (binary, uncompressed)Brave, |
This result is very surprising and interesting to me... I tried "Male Dynamic Pose.fbx" from mixamo on my Windows10 + Chrome, I realized the parsing time becomes 100ms faster (from 600ms to 500ms) by just changing few lines in Replacing three.js/examples/js/loaders/FBXLoader.js Lines 844 to 846 in b0e95eb
with
and replacing three.js/examples/js/loaders/FBXLoader.js Line 1114 in b0e95eb
with
Seems like this part is the major (or almost all) performance gain from this PR. If this result is true, we may should recommend to use |
Yeah, so much that I don't totally trust the results 😆 I guess the takeaway here is that recent JIT compilers are basically black boxes and assuming things like "for loops are faster than forEach loops" is premature optimisation these days, even though it was once a sound assumption. |
Alright! Lets give it a try! 😊 |
Thanks! |
Sweet! If it ends up being an issue I'll change it back later 😊 |
I tried further Even with
In But I couldn't reproduce any cases where So I think it's a bit too early to switch the default loop from Let me know if you folks find the key factors which make |
I tend to agree with @takahirox on this. Regardless, we should have a well-defined policy. What is it? |
Personally I'm in favour of These test have at least shown that performance difference is likely to be just a few milliseconds on modern browsers, even with very large arrays (the |
I vote for ordinary So i clearly promote |
Indeed, that would be interesting to know. |
I vote for whatever is more performant. With a good balance on readability. |
That is a policy, but it is not well-defined. :-) |
I've done a quick search through the codebase for
Also for good measure My suggestion would be that we keep the strict policy for the /src folder, but relax it for other parts of the repo (so these methods can be used for files in the /test and /examples folder). |
Sounds good to me. Also, right now is more important the awesome work you're doing on making the loader have excellent support. We can optimise things later. |
Well, testing against the loader from r87, the wafp.bin.fbx file (compressed, binary) model I've been testing took 1158ms, now loads in 514ms in dev. ASCII and uncompressed binary are about the same (maybe 100-200ms faster on larger models I'm testing), but since most people are using compressed binary FBX files, we can say that we have reduced loading times for FBX models by >50% in most cases. ...just in case you need to write some advertising blurb somewhere 😅 |
🎉🎉🎉 |
Replace for loops with array builtins - forEach, map or reduce, and some other tidying.
Also made the
parseConnections
method a little easier to read.