Closed Bug 89567 Opened 23 years ago Closed 3 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: 3 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: