Closed Bug 89567 Opened 24 years ago Closed 4 years ago

Store text in nsTextFragments in contiguous space

Categories

(Core :: DOM: Core & HTML, defect)

defect
Not set
normal

Tracking

()

RESOLVED INACTIVE

People

(Reporter: bratell, Assigned: bratell)

References

Details

(Keywords: perf)

Attachments

(1 file)

nsTextFragments are malloc happy. Not that they do more than one malloc each, but on some pages there will be many, many textfragments, each very small, so we get thousands of allocations of like 10 bytes each. It would be much, much faster to allocate like 10000 bytes and then sharing that buffer. I see the comment // XXX nsTextFragmentPool? so maybe it's already planned. Would that be possible? I don't know enough about the ownership model to know if this is a reasonable request. The allocations are 1-2% of the table stress case.
->DOM Other, since this is content code.
Assignee: karnaze → jst
Component: Layout → DOM Other
QA Contact: petersen → gerardok
I've implemented an allocator which takes the (mostly very small) blocks from a bigger buffer. This improved the performance, but I'm not sure about memory usage and/or leaks. Anyway, now I use a static nsTextFragmentBuffer which has the buffers that the blocks are allocated from, but I would like it to be owned by the presentation shell. Is that possible? I need it so that different pages get their memory from distinct buffers so that buffers are deallocated correctly. So my questions are two. 1. Who can own the TextFragmentBuffer so that they are limited to one page and still outlives the TextFragments? 2. Are there alreay code (in NSPR?) to do this; allocate memory from a big block without caring very much for reusing returned memory.
My plan is to attach these allocators to the presshells but I don't know how to get access to the nsPresShell from a textfragment or a textframe?
Assignee: jst → bratell
Blocks: 54542
Target Milestone: --- → mozilla0.9.3
nsCOMPtr<nsIPresShell> shell; aPresContext->GetShell(getter_AddRefs(shell));
I should have looked harder before formulating my question. Apparently the text fragments are created in content, when creating a nsGenericDOMDataNode. There is nothing to hang the pool on when the nsGenericDOMDataNode constructor is called (I think) but I guess I can lazily set a better place later since the nsTextFragment doesn't allocate memory until set to a string. In the nsGenericDOMDataNode there are an nsIDocument and an nsIContent. Is any of those a good place? i.e. do they survive the DOM data node and the nsTextFragment and will they stay the same all the time?
I still don't know where to store the allocator but it is a good change. I will try to get this fixed in 0.9.4.
Target Milestone: mozilla0.9.3 → mozilla0.9.4
Summary: Store text in nsTextFragments in contiguos space → Store text in nsTextFragments in contiguous space
jst, is the nsTextFragments (the nsGenericDOMDataNodes) all created on the same thread?
Target Milestone: mozilla0.9.4 → ---
Yes, all DOM text nodes are created on the main thread. It's unfortunate that there is no good place to hang an arena for something like this, we can't use the document, we can't use the presshell...
Keywords: mozilla0.9.9, perf
Regarding the keyword 'mozilla0.9.9'. While I would like to do something about this, I have no idea how to proceed. As jst says, there is just nowhere to put an arena. Doing it globally would cause internal memory fragmentation and make the process grow and grow and grow. You can test the attached patch, if it still applies to the code. Maybe, just maybe, would it be possible to put something arena-like on the document (or presshell) and when the document is torn down, see what nodes are used from other places and then move their strings over to the normal heap. There are meny "if":s in such a solution. How do we know which nodes to move to a heap? Is it possible to move the strings or are people holding onto string pointers? How do we know where a string is allocated without wasting memory? Can a text fragment be in several documents at once? The benefits would be memory (I think the heap can have ~100% memory overhead for nodes the size we allocate) and performance during page load/creation but until we have a plan for how to do this, this is just a reminder.
Keywords: mozilla1.0+
Any feedback regarding Daniel's patch?
Daniel, what is the status of this bug? how you got one finished bug?
I don't think this is solvable right now. :-( There are no place to put the text repository and using a global repository would leak too much memory in fragmentation.
What about trying a sort of repository hashed per document, so that, e.g., GetText() ultimately boils down to calling a global GetText(aDocument, ...) which could allocate/reuse a big block as you suggested. Then, the repository could register itself as an observer of the document to release its per-document data when the corresponding document is destroyed.
We could also just create a static arena scoped to the nsTextFragment class, no?
A static arena is kind of what malloc is, so we won't win much performance there for a lot of more complexity. The win is we can allocate all the text fragments for a page in one (or a few) blocks and the release them with one (or a few) free call(s). But we have to have an owner for that block that knows when it can safely be freed and I don't know where to find one. One problem (I think) is that some document fragments can live longer than the page where they originated. Otherwise, if a fragment cannot live longer than the document, rbs idea might work.
Textfragments can indeed outlive the document. Note that sicking has done some work on using a static shared string for whitespace and such.
QA Contact: gerardok → general
Component: DOM → DOM: Core & HTML
Status: NEW → RESOLVED
Closed: 4 years ago
Resolution: --- → INACTIVE
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: