Calling DOMParser.parseFromString 100k times leaves 100MB of heap-unclassified memory

NEW
Unassigned

Status

()

Core
HTML: Parser
6 years ago
a year ago

People

(Reporter: florian, Unassigned)

Tracking

({memory-leak})

Trunk
x86
Mac OS X
memory-leak
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: [MemShrink:P2])

(Reporter)

Description

6 years ago
I see heap-unclassified in about:memory increase by about 100MB after executing this line in the error console and pressing "Minimize memory usage":

var parser = Components.classes["@mozilla.org/xmlextras/domparser;1"].createInstance(Components.interfaces.nsIDOMParser); for (var i = 0; i < 100000; ++i) parser.parseFromString("foo", "text/html");

Note: be sure to have the gecko profiler or any add-on using a Jetpack older than 1.10 disabled, otherwise bug 769483 will be in your way.

Note2: Executing this 100k times seems excessive, but Thunderbird actually calls parseFromString once for each received IM or tweet, so it can be called thousands of times within hours (or minutes if the user is in very busy IRC channels).
(Reporter)

Comment 1

6 years ago
Adding [MemShrink] in the whiteboard and CC'ing njn, in case it's something that the memshrink team cares about.

Here are the 3 largest unreported block groups in DMD's output after running the testcase in comment 0:

Unreported: 4,761 blocks in block group 1 of 1,862
 58,503,168 bytes (39,116,376 requested / 19,386,792 slop)
 36,69% of the heap (36,69% cumulative);  44,85% of unreported (44,85% cumulative)
 Allocated at
   0_asl_msg_test_expression (in libsystem_c.dylib) + 83
   0_asl_msg_new_key_val_op (in libsystem_c.dylib) + 571
      0L_ArenaAllocate (plarena.c:200, in libplds4.dylib)
      0nsFixedSizeAllocator::Alloc(unsigned long) (in XUL) (nsFixedSizeAllocator.cpp:95)
      0nsNodeInfo::Create(nsIAtom*, nsIAtom*, int, unsigned short, nsIAtom*, nsNodeInfoManager*) (in XUL) (nsNodeInfo.cpp:64)
      0nsNodeInfoManager::GetNodeInfo(nsIAtom*, nsIAtom*, int, unsigned short, nsIAtom*) (in XUL) (nsNodeInfoManager.cpp:225)
      0nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor*, nsIContent**) (in XUL) (nsHtml5TreeOperation.cpp:340)
      0sHtml5TreeOpExecutor::FlushDocumentWrite() (nsHtml5TreeOpExecutor.cpp:653, in XUL)
      0nsHtml5StringParser::Tokenize(nsAString_internal const&, nsIDocument*, bool) (in XUL) (nsAutoPtr.h:124)
      0nsHtml5StringParser::ParseDocument(nsAString_internal const&, nsIDocument*, bool) (in XUL) (nsHtml5StringParser.cpp:88)
      0nsContentUtils::ParseDocumentHTML(nsAString_internal const&, nsIDocument*, bool) (in XUL) (AutoRestore.h:40)
      0nsDOMParser::ParseFromString(nsAString_internal const&, char const*, nsIDOMDocument**) (in XUL) (nsDOMParser.cpp:93)
      0nsDOMParser::ParseFromString(nsAString_internal const&, mozilla::dom::SupportedTypeValues::valuelist, mozilla::ErrorResult&) (in XUL) (nsDOMParser.cpp:50)
      0mozilla::dom::DOMParserBinding::parseFromString(JSContext*, JS::Handle<JSObject*>, nsDOMParser*, unsigned int, JS::Value*) (in XUL) (DOMParserBinding.cpp:70)
      0mozilla::dom::DOMParserBinding::genericMethod(JSContext*, unsigned int, JS::Value*) (in XUL) (DOMParserBinding.cpp:398)

Unreported: 1,587 blocks in block group 2 of 1,862
 19,501,056 bytes (13,038,792 requested / 6,462,264 slop)
 12,23% of the heap (48,92% cumulative);  14,95% of unreported (59,79% cumulative)
 Allocated at
   0_asl_msg_test_expression (in libsystem_c.dylib) + 83
   0_asl_msg_new_key_val_op (in libsystem_c.dylib) + 571
      0L_ArenaAllocate (plarena.c:200, in libplds4.dylib)
      0nsFixedSizeAllocator::Alloc(unsigned long) (in XUL) (nsFixedSizeAllocator.cpp:95)
      0nsNodeInfo::Create(nsIAtom*, nsIAtom*, int, unsigned short, nsIAtom*, nsNodeInfoManager*) (in XUL) (nsNodeInfo.cpp:64)
      0nsNodeInfoManager::GetNodeInfo(nsIAtom*, nsIAtom*, int, unsigned short, nsIAtom*) (in XUL) (nsNodeInfoManager.cpp:225)
      0sNodeInfoManager::GetTextNodeInfo() (nsNodeInfoManager.cpp:316, in XUL)
      0NS_NewTextNode(nsIContent**, nsNodeInfoManager*) (in XUL) (nsTextNode.cpp:100)
      0nsHtml5TreeOperation::AppendText(unsigned short const*, unsigned int, nsIContent*, nsHtml5TreeOpExecutor*) (in XUL) (nsCOMPtr.h:764)
      0nsHtml5TreeOperation::Perform(nsHtml5TreeOpExecutor*, nsIContent**) (in XUL) (nsHtml5TreeOperation.cpp:511)
      0sHtml5TreeOpExecutor::FlushDocumentWrite() (nsHtml5TreeOpExecutor.cpp:653, in XUL)
      0nsHtml5StringParser::Tokenize(nsAString_internal const&, nsIDocument*, bool) (in XUL) (nsAutoPtr.h:124)
      0nsHtml5StringParser::ParseDocument(nsAString_internal const&, nsIDocument*, bool) (in XUL) (nsHtml5StringParser.cpp:88)
      0nsContentUtils::ParseDocumentHTML(nsAString_internal const&, nsIDocument*, bool) (in XUL) (AutoRestore.h:40)
      0nsDOMParser::ParseFromString(nsAString_internal const&, char const*, nsIDOMDocument**) (in XUL) (nsDOMParser.cpp:93)
      0nsDOMParser::ParseFromString(nsAString_internal const&, mozilla::dom::SupportedTypeValues::valuelist, mozilla::ErrorResult&) (in XUL) (nsDOMParser.cpp:50)
      0mozilla::dom::DOMParserBinding::parseFromString(JSContext*, JS::Handle<JSObject*>, nsDOMParser*, unsigned int, JS::Value*) (in XUL) (DOMParserBinding.cpp:70)
      0mozilla::dom::DOMParserBinding::genericMethod(JSContext*, unsigned int, JS::Value*) (in XUL) (DOMParserBinding.cpp:398)

Unreported: 1,587 blocks in block group 3 of 1,862
 19,501,056 bytes (13,038,792 requested / 6,462,264 slop)
 12,23% of the heap (61,15% cumulative);  14,95% of unreported (74,74% cumulative)
 Allocated at
   0_asl_msg_test_expression (in libsystem_c.dylib) + 83
   0_asl_msg_new_key_val_op (in libsystem_c.dylib) + 571
      0L_ArenaAllocate (plarena.c:200, in libplds4.dylib)
      0nsFixedSizeAllocator::Alloc(unsigned long) (in XUL) (nsFixedSizeAllocator.cpp:95)
      0nsNodeInfo::Create(nsIAtom*, nsIAtom*, int, unsigned short, nsIAtom*, nsNodeInfoManager*) (in XUL) (nsNodeInfo.cpp:64)
      0nsNodeInfoManager::GetNodeInfo(nsIAtom*, nsIAtom*, int, unsigned short, nsIAtom*) (in XUL) (nsNodeInfoManager.cpp:225)
      0sNodeInfoManager::GetDocumentNodeInfo() (nsNodeInfoManager.cpp:347, in XUL)
      0sDocument::Init() (nsDocument.cpp:1807, in XUL)
      0sHTMLDocument::Init() (nsHTMLDocument.cpp:257, in XUL)
      0NS_NewHTMLDocument(nsIDocument**, bool) (in XUL) (nsHTMLDocument.cpp:181)
      0NS_NewDOMDocument(nsIDOMDocument**, nsAString_internal const&, nsAString_internal const&, nsIDOMDocumentType*, nsIURI*, nsIURI*, nsIPrincipal*, bool, nsIScriptGlobalObject*, DocumentFlavor) (in XUL) (nsXMLDocument.cpp:87)
      0nsDOMParser::SetUpDocument(DocumentFlavor, nsIDOMDocument**) (in XUL) (nsDOMParser.cpp:508)
      0nsDOMParser::ParseFromString(nsAString_internal const&, char const*, nsIDOMDocument**) (in XUL) (nsDOMParser.cpp:77)
      0nsDOMParser::ParseFromString(nsAString_internal const&, mozilla::dom::SupportedTypeValues::valuelist, mozilla::ErrorResult&) (in XUL) (nsDOMParser.cpp:50)
      0mozilla::dom::DOMParserBinding::parseFromString(JSContext*, JS::Handle<JSObject*>, nsDOMParser*, unsigned int, JS::Value*) (in XUL) (DOMParserBinding.cpp:70)
      0mozilla::dom::DOMParserBinding::genericMethod(JSContext*, unsigned int, JS::Value*) (in XUL) (DOMParserBinding.cpp:398)
Whiteboard: [MemShrink]
Thanks for running DMD!

bz, any ideas if the existing DOM reporters should catch this?


> 0mozilla::dom::DOMParserBinding::genericMethod(JSContext*, unsigned int, JS::Value*) (in XUL) (DOMParserBinding.cpp:398)

BTW, I think you must have an oldish version of DMD (e.g. one from just after it landed).  If you update, the '0' at the start should go away and the PC will be printed at the end of each line.
Does this memory go away if you minimize memory usage?
(Reporter)

Comment 4

6 years ago
(In reply to Justin Lebar [:jlebar] from comment #3)
> Does this memory go away if you minimize memory usage?

Yes and no. After running the test case, about:memory shows 1GB of heap-unclassified. After clicking "minimize memory usage", 100MB is left (in addition to the about 25MB that were already there just after starting Firefox).

The report from DMD in comment 1 was after clicking "minimize memory usage", and I think the 3 block groups I pasted in comment 1 are what takes most of the 100MB that stay around forever.
The nodeinfo manager (and the nodeinfos it contains) should probably be reported as part of the document.
(Reporter)

Comment 6

6 years ago
(In reply to Peter Van der Beken [:peterv] from comment #5)
> The nodeinfo manager (and the nodeinfos it contains) should probably be
> reported as part of the document.

I'm not completely sure, but I don't think documents created through DOMParser.parseFromString are visible in about:memory.
Whiteboard: [MemShrink] → [MemShrink:P2]
You need to log in before you can comment on or make changes to this bug.