Bug 108029 - JSC: SourceProviderCache is memory hungry.
Summary: JSC: SourceProviderCache is memory hungry.
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: JavaScriptCore (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Andreas Kling
URL:
Keywords: InRadar, Performance
Depends on:
Blocks:
 
Reported: 2013-01-27 04:58 PST by Andreas Kling
Modified: 2013-01-29 04:02 PST (History)
7 users (show)

See Also:


Attachments
Proposed patch (9.25 KB, patch)
2013-01-27 05:47 PST, Andreas Kling
buildbot: commit-queue-
Details | Formatted Diff | Diff
Proposed patch v2 (9.47 KB, patch)
2013-01-27 06:30 PST, Andreas Kling
sam: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Andreas Kling 2013-01-27 04:58:36 PST
SourceProviderCacheItem currently has two vectors for captured variable names.
Since these vectors are never mutated after creation, we could store them as fixed-sized arrays instead and bake the whole thing into a single allocation.

I have a patch for this that yields a 13.3 MB (~2%) progression on Membuster3.
Comment 1 Andreas Kling 2013-01-27 05:47:55 PST
Created attachment 184911 [details]
Proposed patch
Comment 2 WebKit Review Bot 2013-01-27 05:50:16 PST
Attachment 184911 [details] did not pass style-queue:

Failed to run "['Tools/Scripts/check-webkit-style', '--diff-files', u'Source/JavaScriptCore/ChangeLog', u'Source/JavaScriptCore/parser/Parser.cpp', u'Source/JavaScriptCore/parser/Parser.h', u'Source/JavaScriptCore/parser/SourceProviderCacheItem.h']" exit_code: 1
Source/JavaScriptCore/parser/SourceProviderCacheItem.h:31:  Alphabetical sorting problem.  [build/include_order] [4]
Total errors found: 1 in 4 files


If any of these errors are false positives, please file a bug against check-webkit-style.
Comment 3 Build Bot 2013-01-27 06:11:53 PST
Comment on attachment 184911 [details]
Proposed patch

Attachment 184911 [details] did not pass win-ews (win):
Output: http://queues.webkit.org/results/16138573
Comment 4 Andreas Kling 2013-01-27 06:30:46 PST
Created attachment 184912 [details]
Proposed patch v2

Let's see if we can #pragma our way out of MSVC's whining..
Comment 5 Sam Weinig 2013-01-27 21:50:40 PST
Comment on attachment 184912 [details]
Proposed patch v2

View in context: https://bugs.webkit.org/attachment.cgi?id=184912&action=review

> Source/JavaScriptCore/parser/SourceProviderCacheItem.h:92
> +    ~SourceProviderCacheItem();

This is more common near the top of the class.

> Source/JavaScriptCore/parser/SourceProviderCacheItem.h:110
> +    void* slot = WTF::fastMalloc(objectSize);

I don't think the WTF:: here is needed.
Comment 6 Radar WebKit Bug Importer 2013-01-27 22:00:49 PST
<rdar://problem/13094806>
Comment 7 Andreas Kling 2013-01-27 22:35:39 PST
Committed r140945: <http://trac.webkit.org/changeset/140945>
Comment 8 Geoffrey Garen 2013-01-27 23:50:28 PST
Can we just remove the SourceProvider cache? Now that we cache bytecode, a parsing cache is pure overhead.
Comment 9 Andreas Kling 2013-01-28 01:41:51 PST
(In reply to comment #8)
> Can we just remove the SourceProvider cache? Now that we cache bytecode, a parsing cache is pure overhead.

If we can, that would be another 10.12 MB saved on the benchmark.
Comment 10 Darin Adler 2013-01-28 09:31:23 PST
Comment on attachment 184912 [details]
Proposed patch v2

View in context: https://bugs.webkit.org/attachment.cgi?id=184912&action=review

> Source/JavaScriptCore/parser/SourceProviderCacheItem.h:97
> +    StringImpl* m_variables[0];

Could this have been done with RefPtr<StringImpl> instead? Here’s why I ask:

> Source/JavaScriptCore/parser/SourceProviderCacheItem.h:103
> +        m_variables[i]->deref();

This line of code could have been m_variables[i]::~RefPtr<StringImpl>().

> Source/JavaScriptCore/parser/SourceProviderCacheItem.h:127
> +        m_variables[j] = parameters.usedVariables[i].get();
> +        m_variables[j]->ref();

This line of code could have been m_variables[j] = parameters.usedVariables[i].

> Source/JavaScriptCore/parser/SourceProviderCacheItem.h:131
> +        m_variables[j] = parameters.writtenVariables[i].get();
> +        m_variables[j]->ref();

This line of code could have been m_variables[j] = parameters.usedVariables[i].
Comment 11 Darin Adler 2013-01-28 09:38:39 PST
Comment on attachment 184912 [details]
Proposed patch v2

View in context: https://bugs.webkit.org/attachment.cgi?id=184912&action=review

> Source/JavaScriptCore/parser/Parser.h:340
> +        copyCapturedVariablesToVector(m_writtenVariables, parameters.writtenVariables);
> +        copyCapturedVariablesToVector(m_usedVariables, parameters.usedVariables);

The shrinkToFit call inside copyCapturedVariablesToVector is no longer a useful optimization, and I suggest we remove it, since the vectors are now temporaries.

On the other hand, a reserveInitialCapacity call inside copyCapturedVariablesToVector could cut down on memory allocation. Or even an inline capacity in the vector type.

Not sure if these would help performance, but perhaps.

> Source/JavaScriptCore/parser/Parser.h:352
> +        for (unsigned i = 0; i < info->usedVariablesCount; ++i)
> +            m_usedVariables.add(info->usedVariables()[i]);
> +        for (unsigned i = 0; i < info->writtenVariablesCount; ++i)
> +            m_writtenVariables.add(info->writtenVariables()[i]);

Could this be made more efficient by using reserveCapacity or reserveInitialCapacity?
Comment 12 Andreas Kling 2013-01-29 04:02:42 PST
(In reply to comment #10)
> (From update of attachment 184912 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=184912&action=review
> 
> > Source/JavaScriptCore/parser/SourceProviderCacheItem.h:97
> > +    StringImpl* m_variables[0];
> 
> Could this have been done with RefPtr<StringImpl> instead? Here’s why I ask:

Yes.

> > Source/JavaScriptCore/parser/SourceProviderCacheItem.h:103
> > +        m_variables[i]->deref();
> 
> This line of code could have been m_variables[i]::~RefPtr<StringImpl>().

Sure, that would be nicer.

> > Source/JavaScriptCore/parser/SourceProviderCacheItem.h:127
> > +        m_variables[j] = parameters.usedVariables[i].get();
> > +        m_variables[j]->ref();
> 
> This line of code could have been m_variables[j] = parameters.usedVariables[i].

We'd have to use placement new for these, since m_variables[j] is uninitialized at this point.

(In reply to comment #11)
> (From update of attachment 184912 [details])
> View in context: https://bugs.webkit.org/attachment.cgi?id=184912&action=review
> 
> > Source/JavaScriptCore/parser/Parser.h:340
> > +        copyCapturedVariablesToVector(m_writtenVariables, parameters.writtenVariables);
> > +        copyCapturedVariablesToVector(m_usedVariables, parameters.usedVariables);
> 
> The shrinkToFit call inside copyCapturedVariablesToVector is no longer a useful optimization, and I suggest we remove it, since the vectors are now temporaries.

Indeed, which is why I removed it in this patch. :)

> On the other hand, a reserveInitialCapacity call inside copyCapturedVariablesToVector could cut down on memory allocation. Or even an inline capacity in the vector type.
> 
> Not sure if these would help performance, but perhaps.

Giving it an inline capacity would be a straightforward way to remove at least two (transient) mallocs.

> > Source/JavaScriptCore/parser/Parser.h:352
> > +        for (unsigned i = 0; i < info->usedVariablesCount; ++i)
> > +            m_usedVariables.add(info->usedVariables()[i]);
> > +        for (unsigned i = 0; i < info->writtenVariablesCount; ++i)
> > +            m_writtenVariables.add(info->writtenVariables()[i]);
> 
> Could this be made more efficient by using reserveCapacity or reserveInitialCapacity?

HashSet doesn't have a reserveCapacity mechanism.