#3708 closed enhancement (fixed)
[PATCH] SpiderMonkey 38 Upgrade
Reported by: | leper | Owned by: | Itms |
---|---|---|---|
Priority: | Should Have | Milestone: | Alpha 21 |
Component: | Core engine | Keywords: | patch |
Cc: | Yves | Patch: |
Description (last modified by )
SpiderMonkey 38 was released some time ago, and it brings some improvements like eg better ES6 support.
I've started working on the upgrade and it compiles without problems right now, but there is still 1 test failures (which is to be expected and cannot easily be fixed since the function we relied on was removed). Some review, testing and suggestions would be nice.
There is a commit for each upstream change that required a change in our code, or did not fit in any of those. The last commit contains some TODOs.
The debug api was removed and JS_SetFunctionCallback
which could have been used for our needs was also removed in SM37 (hinting at both the JS Debugger and the tracelogger).
Given the high number of changes needed and for easier testing/reviewing the code is in the sm38 branch of my github repo.
https://github.com/na-Itms/0ad/tree/sm38 (Note that this will be rebased (both on top of 0ad/0ad and interactively).)
Attachments (6)
Change History (36)
comment:1 by , 9 years ago
Description: | modified (diff) |
---|
comment:2 by , 9 years ago
comment:7 by , 9 years ago
Description: | modified (diff) |
---|
Is any more review needed here? And do we want that in before A20?
comment:8 by , 9 years ago
Milestone: | Alpha 20 → Alpha 21 |
---|
comment:9 by , 8 years ago
Description: | modified (diff) |
---|---|
Keywords: | rfc added; wip review removed |
I fixed some little things (the debug build now runs without issues), the current state of the work is here: https://github.com/na-Itms/0ad/tree/sm38
I'm taking a look at the TODOs from the latest commit. After that I'll squash my work into SVN patches. In the meantime the work is ready for some reviewing!
comment:10 by , 8 years ago
Owner: | changed from | to
---|
Ready for reviewing: you can use https://github.com/na-Itms/0ad/tree/sm38 for eased reviewing, and you should test the squash branch which contains what should be committed:
- Two cleanup patches beforehand
- The new SpiderMonkey files
- All the code changes for the new API
- Two commits making use of new SpiderMonkey features
- An incomplete commit removing one of our workarounds. I still need to figure out how to remove it in the component manager without breaking anything
Except for that last bullet point, I would like to commit that immediately when I come back from holidays, in two weeks, so please review, test and give comments!
comment:11 by , 8 years ago
- In build.sh there are some more occurences of the SpiderMonkey version number that could probably be replaced by a variable (but it's that way since more than one version, so not really an issue of the update).
- The wiki page about the Tracelogger (EngineProfiling#SpiderMonkeyTracelogger) needs an update. It has to be enabled using some environment variables now instead of the build options and viewing the graph requires you to start a webserver from a python script (see https://github.com/h4writer/tracelogger).
- We should call JS_Shutdown. Apparently that wasn't really required so far, but the tracelogger requires it (tl-data.json misses a "]" at the end otherwise).
- It seems like performance didn't improve or even got a bit worse with the upgrade. My hypothesis was that it should improve because we have used more new features that broke JIT compiling of SM31 over time and SM38 should support more of these cases. This should not prevent committing, but it could be worth to take a closer look and figure out if there's something we can do about it. I had to spend quite a bit of time on performance analysis for the last two upgrades and it made quite a difference. For v31 I had to add an additional patch that didn't make it into v31 for example.
The performance measurements show the number of seconds a non-visual replay of approximately 10'000 turns took. The hashes are different, but when I run the visual replay simultaneously with both versions, I can't spot any differences and the minimap looks exactly the same in the end. The "petra bugfix" mentioned there is something that got fixed in SVN already, so nothing to worry about. sm38 + petra bugfix in workers.js hash: acb4f8e26b36ee0bef10b0add2be8d83 234.285325253 seconds 243.424827335 seconds 249.598170723 seconds
SVN r18513 + petra bugfix in workers.js hash: dd9b4305f4939dc632fbdc9a4f3c1053 233.902549491 seconds 233.991263663 seconds 233.655866539 seconds
As already mentioned in the previous review (but I've done some more research and have some more details):
- SpiderMonkey build flags in build.sh and build-osx-libs.sh should be checked again.
- SpiderMonkey always builds with generationl GC (GGC) enabled, so "--enable-gcgenerational" can be removed. Relevant Bugzilla bugs: 1107349
- Tracelogging is now built by default, so the comments about "--enable-trace-logging" can be removed or have to be modified. The line about DTRACE_LOG_DIR should still work, but since the tracelogger is now built by default, we might want to use the default value of SpiderMonkey but still keep the line around in build.sh if someone needs to change the path (comment it). Relevant Bugzilla bugs: 1071546
comment:12 by , 8 years ago
Keywords: | rfc removed |
---|
Thanks a lot for the complete review :)
I will work on this as soon as I'm back.
comment:15 by , 8 years ago
Keywords: | review added |
---|
Attached patch properly calls JS_ShutDown. It is not possible to call JS_Init
again after JS_ShutDown
, so we must have to handle this limitation.
comment:16 by , 8 years ago
"++m_RuntimeInstances;" shouldn't be inside the if-block. If I fix that, it triggers the assertion on line 118 of ScriptRuntime.cpp when pyrogenesis is started without a "-mod=public" argument (because the engine tries to shut down and restart with the public mod).
comment:17 by , 8 years ago
Keywords: | review removed |
---|
by , 8 years ago
Attachment: | JS_ShutDown.patch added |
---|
by , 8 years ago
Attachment: | JS_ShutDown_SVN_1.0.diff added |
---|
JS_Shutdown patch for SVN with validation and RAII approach
comment:20 by , 8 years ago
Keywords: | review removed |
---|
comment:21 by , 8 years ago
Keywords: | review added |
---|
This is ready to commit: https://github.com/na-Itms/0ad/tree/sm38
The performance stagnation noticed by Yves comes from SM taking a long time to compile some functions. I could not determine what caused those functions to be so difficult to compile. On top of that I encountered a lot of issues because SM38 is already an old version, so the codebase has changed too much and the tracelogging tools are not compatible anymore.
I suggest committing that (the performance is not made worse either) and starting to work immediately on the SM45 upgrade, for which the JIT compiler improved and for which it is still possible to propose patches if we have problems.
Since the last review, I updated the build scripts (bc850dc) and added a source/tools directory for outputting the traces, along with a useful script that I will document in EngineProfiling (e95ffbc 3a54d0a, see next comment).
comment:22 by , 8 years ago
Little update to the tracelogging script (I'm still not good at writing sh scripts!) The new commit is 3a54d0a.
by , 8 years ago
Attachment: | Bug_1227028_Mod.diff added |
---|
Modified version of the patch in bug 1227028 (modified context lines in Ion.cpp)
comment:23 by , 8 years ago
I finally managed to pick the right set of patches to fix the problem with missing stop information in the generated data and to implement regular flushing of tracelogger data to the disk to prevent out of memory issues.
I'm still not sure if the generated tracelogger data is correct, though.
Add this to patch.sh:
# TraceLogger: Assertion failure: i < size_, at js/src/vm/TraceLoggingTypes.h:210". # Also fix stop-information to make reduce.py work correctly. patch -p1 < ../Bug_1223767.diff # TraceLogger: Limit the memory tracelogger can take. # This causes tracelogger to flush data to the disk regularly and prevents out of # memory issues if a lot of data gets logged. # Flushing causes a segfault during shrinking GC after this patch, but one of the # following patches resolves that issue (don't know which one exactly). patch -p1 < ../Bug_1227914.diff # Fix tracelogger destructor that touches possibly uninitialised hash table. # This is also a prereq for the patch in bug 1223636 because some of its context # lines are modified in this patch. patch -p1 < ../Bug_1155618.diff # Tracelogger - Don't treat extraTextId as containing only extra ids # This fixes an assertion failure: id == nextTextId at js/src/vm/TraceLoggingGraph.cpp patch -p1 < ../Bug_1223636.diff # TraceLogger - Fix when to keep the payload of a TraceLogger event # This fixes an assertion failure: textId < uint32_t(1 << 31) at js/src/vm/TraceLoggingGraph.h # The original patch is slightly modified because some context lines in Ion.cpp did not match. patch -p1 < ../Bug_1227028_Mod.diff
The patches: Bug_1223767.diff Bug_1227914.diff Bug_1155618.diff Bug_1223636.diff Bug 1227028 but there's a modified version that applies: Bug_1227028_Mod.diff
EDIT: Actually I'm quite sure the data is still incorrect. What you see on the right side in the tracelogger gui when you click somewhere on the graph should be a callstack. This shows impossible callstacks. Also there are some functions that were compiled 0 times according to the tracelogger but still run in IonMonkey. I've tested with a small log just from opening the game and closing it again after waiting a minute on the main menu. This log looks correct, even after calling reduce.py on it.
follow-up: 27 comment:24 by , 8 years ago
Some more patches to append to patch.sh:
# TraceLogger - Handle failing to add to pointermap gracefully patch -p1 < ../Bug_1266649.diff # Tracelogger: Don't cache based on pointers to movable gc things patch -p1 < ../Bug_1280648_Mod.diff patch -p1 < ../Bug_1224123.diff # Tracelogger: fix the use of LastEntryId in tracelogger.h (prereq for Bug_1231170.diff) patch -p1 < ../Bug_1231170.diff # Use size in debugger instead of the current id to track last logged item patch -p1 < ../Bug_1221844_1.diff # Part 1: TraceLogger: Move TraceLogger_Invalidation to LOG_ITEM. patch -p1 < ../Bug_1221844.diff # Part 2: TraceLogger: Add some debug checks to logTimestamp. patch -p1 < ../Bug_1255766.diff patch -p1 < ../Bug_1259403_1.diff # Tracelogger: Only increase capacity by multiples of 2 patch -p1 < ../Bug_1259403_2.diff # Tracelogger: Always make sure there are 3 free slots for events
This solves incorrect stacks displayed in the tracelogger and probably more issues related to it. Somehow it did not exit some nodes when it should have and caused the stack getting nested deeper and deeper the longer the trace ran.
I'm trying to figure out if the data is correct now. It still seems strange that it shows 0 times compiled but > 0% runtime in Ion mode. It might be because it counts the compiling in the helper threads sometimes, but I don't know if that's true. It also seems suspicious that Timer.js:67 still makes up >10% total runtime in a non-visual replay and I'm not sure how it counts "internal" time exactly. Trying to figure these things out now.
follow-up: 26 comment:25 by , 8 years ago
Regarding r18584: Why is this using GetSingleton()
explicitly, instead of doing what all the other "singletons" we have are doing? Also the getter already ensures that it is initialized. Why is it using a list instead of a vector (doing swap and pop) given that the order isn't important? Using full include paths would be nice, even if some of the surrounding code doesn't do that.
comment:26 by , 8 years ago
I'm glad to see your comments on tickets and your commits again! :)
Replying to leper:
Regarding r18584: Why is this using
GetSingleton()
explicitly, instead of doing what all the other "singletons" we have are doing?
Do you mean adding a define like g_ScriptEngine that for ScriptEngine::GetSingleton()? Honestly, I didn't notice that it's done that way in other cases. However, I'm not quite sure if it's a good thing or not. It's a bit like trying to hide that it's a singleton.
Replying to leper:
Also the getter already ensures that it is initialized.
I assume you mean the two lines with "ENSURE" in ScriptRuntime.cpp. I've noticed that and even asked Itms about it during the review. Neither of us had a strong opinion about it, but the pro-argument was that this check is something we explicitly want and therefore it's good to write the check explicitly, even if it's a bit of a duplicate. It also gives a more specific error message.
Replying to leper:
Why is it using a list instead of a vector (doing swap and pop) given that the order isn't important?
My thought was that the order of adding and removing runtimes can be arbitrary and using a vector could cause "holes" of unused memory. It's just one, two or maybe three elements, so that's like 128 bit of memory wasted in the worst case and less if we consider that lists also need pointers to the next element. If you think it should be changed, that's OK for me.
Replying to leper:
Using full include paths would be nice, even if some of the surrounding code doesn't do that.
Ah, I've missed that for script ScriptTypes.h. We have actually discussed during the review if the full include path should be used everywhere or just for other projects than the current one. We didn't really come to a conclusion because we don't have that defined anywhere in our guidelines (I couldn't find it at least) and it's also not consistently done so far. I've "kind of" decided to use the full path, but I didn't carefully check all files because we don't really have a rule for that.
comment:27 by , 8 years ago
Replying to Yves:
I'm trying to figure out if the data is correct now. It still seems strange that it shows 0 times compiled but > 0% runtime in Ion mode. It might be because it counts the compiling in the helper threads sometimes, but I don't know if that's true. It also seems suspicious that Timer.js:67 still makes up >10% total runtime in a non-visual replay and I'm not sure how it counts "internal" time exactly. Trying to figure these things out now.
I've asked h4writer on the #jsapi channel today. Reduce.py ignores the data for everything that's shorter than a certain threshold. This threshold goes up the more data you collect, which means it's very high in our case. This causes compilation events to be ignored and explains why the count can be 0 even though it runs in ion mode. Much worse is the fact that this also applies to the number for total runtime per function. Functions with a high runtime per call show a higher runtime than functions which run the same time in total but are called more often and take less time per call. Reduce.py writes a special corrections file by default to fix these issues, but there was a bug and the tracelogger didn't actually use these corrections to display the data. This is now fixed an the data really looks a lot different and much more plausible. Instead of > 10%, Timer.js:67 now only takes 2.84%.
Internal time is still around 30%, which seems quite a lot to me, but he said that's possible. The tracelogger now doesn't include this internal time in the total time of functions anymore, which is much more intuitive. Before this change, there was a function that took around 8% total time but spent more than 99% flushing tracelogger data (so it wasn't expensive at all but just "unlucky" that flushing happened during the runtime of that function).
To sum it up, I'd say the data looks plausible now if you apply all the patches I've listed above and update the tracelogger (the client from https://github.com/h4writer/tracelogger) to the most recent version.
by , 8 years ago
Attachment: | Bug_1280648_Mod.diff added |
---|
comment:28 by , 8 years ago
Bug_1266649.diff Bug_1280648_Mod.diff: attached to the ticket Bug_1224123.diff Bug_1231170.diff Bug_1221844_1.diff Bug_1221844.diff Bug_1255766.diff Bug_1259403_1.diff Bug_1259403_2.diff
comment:30 by , 8 years ago
Keywords: | review removed |
---|
I've looked through all the commits separately and couldn't find many issues, well done! It was quite convenient that you have split up the changes into different commits so well.
General - Issues/TODOs/Comments:
Some comments to specific changes
0f5b2e57 Remove workaround.
564131b5 TODOs.
9d6a7823 JS_GetStringCharsAndLength was removed, use JS_Get{Latin1,TwoByte}StringCharsAndLength instead
I doubt it makes a big difference for performance with move constructors, but maybe a little and it looks a bit better style-wise for me.
takes a char16_t* parameter. I've spent some time digging through the SpiderMonkey code and figured out that it actually "deflates" them automatically, which is very good because we can take advantage of the improved strings for property names without having to worry about that.
aa596b92 Remove workaround for crash when using multiple ctxts per runtime
c22317ca The GC API changed ...
92fe1422 The JS_LookupProperty{,ById} API was removed.
95834e9d Cleanup, can be dropped or moved elsewhere.
288af6f3 JS_NewObject -> JS_NewPlainObject.
02ea3451 Some JSClass stubs were removed, and the pointers are nullable.
8dec5d5a Update ObjectToIDMap to the ESR38 version.
a03f7fc1 The old debug api was removed.