WebKit icon indicating copy to clipboard operation
WebKit copied to clipboard

Add strong root logging and $vm helpers for memory leak debugging

Open justinmichaud opened this issue 1 year ago โ€ข 7 comments

bf5c23d50f3cce166b4bf04b8b4a13c62c02e651

Add strong root logging and $vm helpers for memory leak debugging
https://bugs.webkit.org/show_bug.cgi?id=277835

Reviewed by NOBODY (OOPS!).

This patch adds some new options for debugging memory leaks. It also
allows $vm to be enabled again on GTK developer builds.

For example, we can debug a memory leak in the JSC heap by:

1) Run:
```
JSC_validateOptions=1 JSC_useDollarVM=1 JSC_logLiveStrongs=1 JSC_dumpHeapOnLowMemory=1 JSC_useSourceProviderCache=0 JSC_useCodeCache=0 WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1 Tools/Scripts/run-minibrowser --gtk --debug https://webkit.org
```

Alternatively, to track C allocations, disable system malloc in CMakeLists.txt (I recommend adding a #if !USE_SYSTEM_MALLOC #error #endif to confirmn), run:

```
JSC_useSourceProviderCache=0 JSC_useCodeCache=0 WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1 MALLOC=0 WEB_PROCESS_CMD_PREFIX="/usr/bin/valgrind --tool=massif " Tools/Scripts/run-minibrowser --gtk --debug https://webkit.org
```

Then, to release memory, dump the JSC heap, and log all remaining Strong<> references, run:

```
javascript:$vm.gc()
javascript:$vm.triggerMemoryPressure()
```

You should get a gc snapshot file. To graph it (or just do dump it to a human-readable format), run:
```
Tools/Scripts/heap-snapshot-to-graphviz.js /tmp/GCHeapM8FVBp  ~/
dot -Tsvg ~/GCDebugging.gv.txt -O
```

You can edit `heap-snapshot-to-graphviz.js` to print root paths, and there are many other graph-related things you can do in js.

You can also open this file in WebInspector by adding a JavaScript allocations track, and clicking the second import button (not the main import button).

If you see that your heap objects are kept alive by StrongReferences, then the strong logging may point to which C++ object is keeping them alive, and you can continue your investigation from there.

As a general tip, you should ensure instrumentingAgents.inspectorEnvironment().developerExtrasEnabled() is false on your platform when diagnosing these bugs, since WebInspector can keep things alive unnecesarily.

It may also be helpful to disable Process Swap on Naviagation.

* Source/JavaScriptCore/heap/Heap.cpp:
(JSC::Heap::addCoreConstraints):
(JSC::StrongLoggingDisabledScope::StrongLoggingDisabledScope):
(JSC::StrongLoggingDisabledScope::~StrongLoggingDisabledScope):
(JSC::debugReportLiveStrong):
(JSC::debugReportDeadStrong):
(JSC::debugLogAllLiveStrongs):
* Source/JavaScriptCore/heap/Heap.h:
* Source/JavaScriptCore/heap/MarkedSpace.h:
* Source/JavaScriptCore/heap/MarkedSpaceInlines.h:
(JSC::MarkedSpace::forEachWeakInParallel):
* Source/JavaScriptCore/heap/Strong.h:
(JSC::Strong::Strong):
(JSC::Strong::~Strong):
* Source/JavaScriptCore/heap/StrongInlines.h:
(JSC::shouldStrongDestructorGrabLock>::Strong):
(JSC::shouldStrongDestructorGrabLock>::set):
* Source/JavaScriptCore/runtime/OptionsList.h:
* Source/JavaScriptCore/runtime/VM.cpp:
(JSC::VM::VM):
* Source/JavaScriptCore/tools/JSDollarVM.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
(JSC::JSDollarVM::finishCreation):
* Source/WTF/wtf/MemoryPressureHandler.cpp:
(WTF::MemoryPressureHandler::setShouldUsePeriodicMemoryMonitor):
* Source/WebCore/bindings/js/GCController.h:
* Source/WebInspectorUI/UserInterface/Workers/HeapSnapshot/HeapSnapshot.js:
(HeapSnapshot):
(HeapSnapshot.prototype.shortestGCRootPath):
(HeapSnapshot.prototype.serializeEdge):
(HeapSnapshot.prototype._determineGCRootPaths):
* Source/WebKit/NetworkProcess/soup/NetworkProcessSoup.cpp:
(WebKit::NetworkProcess::platformInitializeNetworkProcess):
* Source/WebKit/WebProcess/WebProcess.cpp:
(WebKit::WebProcess::initializeWebProcess):
* Source/cmake/OptionsGTK.cmake:
* Tools/Scripts/heap-snapshot-to-graphviz.js: Added.
(true.console.log.string_appeared_here.escapeOutput):
(return.unsafe.replace):

https://github.com/WebKit/WebKit/commit/3cc7b3cd3ebe21596a75a73eb5738df556114ca7

Misc iOS, visionOS, tvOS & watchOS macOS Linux Windows
โŒ ๐Ÿงช style โœ… ๐Ÿ›  ios โœ… ๐Ÿ›  mac โœ… ๐Ÿ›  wpe โœ… ๐Ÿ›  wincairo
โœ… ๐Ÿงช bindings โœ… ๐Ÿ›  ios-sim โœ… ๐Ÿ›  mac-AS-debug โœ… ๐Ÿงช wpe-wk2 โœ… ๐Ÿงช wincairo-tests
โœ… ๐Ÿงช webkitperl โœ… ๐Ÿงช ios-wk2 โœ… ๐Ÿงช api-mac โœ… ๐Ÿงช api-wpe
โœ… ๐Ÿงช ios-wk2-wpt โœ… ๐Ÿงช mac-wk1 โœ… ๐Ÿ›  wpe-cairo
โœ… ๐Ÿ›  ๐Ÿงช jsc โœ… ๐Ÿงช api-ios โœ… ๐Ÿงช mac-wk2 โœ… ๐Ÿ›  gtk
โœ… ๐Ÿ›  ๐Ÿงช jsc-arm64 โœ… ๐Ÿ›  vision โœ… ๐Ÿงช mac-AS-debug-wk2 โœ… ๐Ÿงช gtk-wk2
โœ… ๐Ÿ›  vision-sim โœ… ๐Ÿงช mac-wk2-stress โœ… ๐Ÿงช api-gtk
โœ… ๐Ÿงช vision-wk2 โœ… ๐Ÿ›  jsc-armv7
โœ… ๐Ÿ›  tv โŒ ๐Ÿงช jsc-armv7-tests
โœ… ๐Ÿ›  tv-sim
โœ… ๐Ÿ›  watch
โœ… ๐Ÿ›  watch-sim

justinmichaud avatar Aug 08 '24 23:08 justinmichaud

This patch adds some new options for debugging memory leaks

Can you define what kind of "memory leaks" you are referring to here? (1) C/C++ code memory leaks? (2) JS heap "memory leaks" due to JS code retaining memory longer than needed?

MenloDorian avatar Aug 15 '24 23:08 MenloDorian

In my case, it appeared that a WebInspector log kept a js global object alive even after navigating away from the page. WPE doesn't enable PSON unfortunately, so bugs like these casue embedded devices to leak memory

justinmichaud avatar Aug 19 '24 22:08 justinmichaud

Committed 284791@main (41dc316f40f4): https://commits.webkit.org/284791@main

Reviewed commits have been landed. Closing PR #31924 and removing active labels.

webkit-commit-queue avatar Oct 07 '24 22:10 webkit-commit-queue