This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$parse performance/style - #8901

Closed
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf
Closed

$parse performance/style#8901
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf

Conversation

@jbedard

Copy link
Copy Markdown
Contributor

c074181 might be the only one worth merging to allow the Parser/Lexer objects to be GCed.

f4ea3c9 addresses a TODO although I didn't notice any major improvements (even though the removed wrapper method is often ~10% when profiling...). Unfortunately the wrapper method is still needed for the expressions returned from $parse, but use of getterFns within other expressions don't have the wrapper. This also required a minor error message change.

f4ea3c9 could be expanded in other ways though. Maybe allowing $parseed methods to return something such as a $$watchFn property that can be watched instead of the full expression being watched. The simple case would be returning the raw getterFn instead of the wrapper for simple foo.bar expressions. A more complicated case would be expressions such as myVar % 2 === 0 returning only the myVargetterFn to be watched (and then a special watch delegate to see if the full expression actually changed, which makes it more complicated...). Or only watching the input+args to filters etc. Not sure how common or useful those would be though...

The rest are mostly style/simplifying but I thought I'd leave them in there.

@btford

Copy link
Copy Markdown
Contributor

@jbedard thanks for the PR! can you add a benchmark to https://github.com/angular/angular.js/tree/master/benchmarks to prove that these changes are beneficial?

@btfordbtford added this to the 1.3.0-rc.2 milestone Sep 3, 2014
@jbedard
jbedardforce-pushed the parse-perf branch 2 times, most recently from 05ee69e to eb47e91CompareSeptember 4, 2014 15:57
@jbedard

Copy link
Copy Markdown
ContributorAuthor

@btford I've added a new benchpress benchmark for execution of $parse()ed expressions (fd45e8a). It currently has tests for the different types of expressions (property, binary op, filter, ...). Basically it generates data (2000 rows right now), ng-repeats a bunch of expressions (12 per test right now, except object literals that are too slow) and then measures the digest (x50 right now) time.

I updated eb47e91 such that the wrapper function is now only needed for one-time binding so $parse()ed properties now benefit form this as well. (A wrapper is needed for one-time because the one-time :: is not actually part of parsing so both ::foo and foo now return the exact same getterFn result, but they have different $$watchDelegates so they need to be different functions returned from $parse).

Here are the numbers (ms) for the current tests in the benchmark (12 expressions x 2000 rows x 50 digests):

TestOldNewExplanation
simple properties11094needs a few runs to stabilize but seems consistent
field accessors193178$parsePathGetter was ~5% in a quick profile which matches the numbers
field indexors11601160$parsePathGetter was negligible compared to ensureSafeObject + $parseObjectIndex
prop/operators206186$parsePathGetter was ~8% in a quick profile which matches the numbers
prop/filters328326$parsePathGetter was negligible compared to $parseFilter + pipe operator + binaryFn
prop/literals/func559522$parsePathGetter was mostly negligible compared to $parseFunctionCall + .apply + ensureSafeObject
prop/literals/{}14741440$parsePathGetter was negligible since it is mainly constants in the object, the .length seems to make the minor difference
prop/literals/[]1003979(same as object literal)

@jbedardjbedard mentioned this pull request Sep 5, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
…ions
This allows the parser and lexer objects to get GC-ed once the expression
is parsed.
Part of #8901
@IgorMinarIgorMinar self-assigned this Sep 8, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
@jbedard

Copy link
Copy Markdown
ContributorAuthor

Thanks for looking into all of these and getting them in so fast! And note my comment regarding the changed tests/error-message if you haven't already (can avoid changing the tests/message if we want, see jbedard@cec3344)

mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jbedard@btford@IgorMinar@Narretz@mary-poppins
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$parse performance/style - #8901

Closed
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf
Closed

$parse performance/style#8901
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf

Conversation

@jbedard

Copy link
Copy Markdown
Contributor

c074181 might be the only one worth merging to allow the Parser/Lexer objects to be GCed.

f4ea3c9 addresses a TODO although I didn't notice any major improvements (even though the removed wrapper method is often ~10% when profiling...). Unfortunately the wrapper method is still needed for the expressions returned from $parse, but use of getterFns within other expressions don't have the wrapper. This also required a minor error message change.

f4ea3c9 could be expanded in other ways though. Maybe allowing $parseed methods to return something such as a $$watchFn property that can be watched instead of the full expression being watched. The simple case would be returning the raw getterFn instead of the wrapper for simple foo.bar expressions. A more complicated case would be expressions such as myVar % 2 === 0 returning only the myVargetterFn to be watched (and then a special watch delegate to see if the full expression actually changed, which makes it more complicated...). Or only watching the input+args to filters etc. Not sure how common or useful those would be though...

The rest are mostly style/simplifying but I thought I'd leave them in there.

@btford

Copy link
Copy Markdown
Contributor

@jbedard thanks for the PR! can you add a benchmark to https://github.com/angular/angular.js/tree/master/benchmarks to prove that these changes are beneficial?

@btfordbtford added this to the 1.3.0-rc.2 milestone Sep 3, 2014
@jbedard
jbedardforce-pushed the parse-perf branch 2 times, most recently from 05ee69e to eb47e91CompareSeptember 4, 2014 15:57
@jbedard

Copy link
Copy Markdown
ContributorAuthor

@btford I've added a new benchpress benchmark for execution of $parse()ed expressions (fd45e8a). It currently has tests for the different types of expressions (property, binary op, filter, ...). Basically it generates data (2000 rows right now), ng-repeats a bunch of expressions (12 per test right now, except object literals that are too slow) and then measures the digest (x50 right now) time.

I updated eb47e91 such that the wrapper function is now only needed for one-time binding so $parse()ed properties now benefit form this as well. (A wrapper is needed for one-time because the one-time :: is not actually part of parsing so both ::foo and foo now return the exact same getterFn result, but they have different $$watchDelegates so they need to be different functions returned from $parse).

Here are the numbers (ms) for the current tests in the benchmark (12 expressions x 2000 rows x 50 digests):

TestOldNewExplanation
simple properties11094needs a few runs to stabilize but seems consistent
field accessors193178$parsePathGetter was ~5% in a quick profile which matches the numbers
field indexors11601160$parsePathGetter was negligible compared to ensureSafeObject + $parseObjectIndex
prop/operators206186$parsePathGetter was ~8% in a quick profile which matches the numbers
prop/filters328326$parsePathGetter was negligible compared to $parseFilter + pipe operator + binaryFn
prop/literals/func559522$parsePathGetter was mostly negligible compared to $parseFunctionCall + .apply + ensureSafeObject
prop/literals/{}14741440$parsePathGetter was negligible since it is mainly constants in the object, the .length seems to make the minor difference
prop/literals/[]1003979(same as object literal)

@jbedardjbedard mentioned this pull request Sep 5, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
…ions
This allows the parser and lexer objects to get GC-ed once the expression
is parsed.
Part of #8901
@IgorMinarIgorMinar self-assigned this Sep 8, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
@jbedard

Copy link
Copy Markdown
ContributorAuthor

Thanks for looking into all of these and getting them in so fast! And note my comment regarding the changed tests/error-message if you haven't already (can avoid changing the tests/message if we want, see jbedard@cec3344)

mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jbedard@btford@IgorMinar@Narretz@mary-poppins
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$parse performance/style - #8901

Closed
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf
Closed

$parse performance/style#8901
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf

Conversation

@jbedard

Copy link
Copy Markdown
Contributor

c074181 might be the only one worth merging to allow the Parser/Lexer objects to be GCed.

f4ea3c9 addresses a TODO although I didn't notice any major improvements (even though the removed wrapper method is often ~10% when profiling...). Unfortunately the wrapper method is still needed for the expressions returned from $parse, but use of getterFns within other expressions don't have the wrapper. This also required a minor error message change.

f4ea3c9 could be expanded in other ways though. Maybe allowing $parseed methods to return something such as a $$watchFn property that can be watched instead of the full expression being watched. The simple case would be returning the raw getterFn instead of the wrapper for simple foo.bar expressions. A more complicated case would be expressions such as myVar % 2 === 0 returning only the myVargetterFn to be watched (and then a special watch delegate to see if the full expression actually changed, which makes it more complicated...). Or only watching the input+args to filters etc. Not sure how common or useful those would be though...

The rest are mostly style/simplifying but I thought I'd leave them in there.

@btford

Copy link
Copy Markdown
Contributor

@jbedard thanks for the PR! can you add a benchmark to https://github.com/angular/angular.js/tree/master/benchmarks to prove that these changes are beneficial?

@btfordbtford added this to the 1.3.0-rc.2 milestone Sep 3, 2014
@jbedard
jbedardforce-pushed the parse-perf branch 2 times, most recently from 05ee69e to eb47e91CompareSeptember 4, 2014 15:57
@jbedard

Copy link
Copy Markdown
ContributorAuthor

@btford I've added a new benchpress benchmark for execution of $parse()ed expressions (fd45e8a). It currently has tests for the different types of expressions (property, binary op, filter, ...). Basically it generates data (2000 rows right now), ng-repeats a bunch of expressions (12 per test right now, except object literals that are too slow) and then measures the digest (x50 right now) time.

I updated eb47e91 such that the wrapper function is now only needed for one-time binding so $parse()ed properties now benefit form this as well. (A wrapper is needed for one-time because the one-time :: is not actually part of parsing so both ::foo and foo now return the exact same getterFn result, but they have different $$watchDelegates so they need to be different functions returned from $parse).

Here are the numbers (ms) for the current tests in the benchmark (12 expressions x 2000 rows x 50 digests):

TestOldNewExplanation
simple properties11094needs a few runs to stabilize but seems consistent
field accessors193178$parsePathGetter was ~5% in a quick profile which matches the numbers
field indexors11601160$parsePathGetter was negligible compared to ensureSafeObject + $parseObjectIndex
prop/operators206186$parsePathGetter was ~8% in a quick profile which matches the numbers
prop/filters328326$parsePathGetter was negligible compared to $parseFilter + pipe operator + binaryFn
prop/literals/func559522$parsePathGetter was mostly negligible compared to $parseFunctionCall + .apply + ensureSafeObject
prop/literals/{}14741440$parsePathGetter was negligible since it is mainly constants in the object, the .length seems to make the minor difference
prop/literals/[]1003979(same as object literal)

@jbedardjbedard mentioned this pull request Sep 5, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
…ions
This allows the parser and lexer objects to get GC-ed once the expression
is parsed.
Part of #8901
@IgorMinarIgorMinar self-assigned this Sep 8, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
@jbedard

Copy link
Copy Markdown
ContributorAuthor

Thanks for looking into all of these and getting them in so fast! And note my comment regarding the changed tests/error-message if you haven't already (can avoid changing the tests/message if we want, see jbedard@cec3344)

mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jbedard@btford@IgorMinar@Narretz@mary-poppins
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$parse performance/style - #8901

Closed
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf
Closed

$parse performance/style#8901
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf

Conversation

@jbedard

Copy link
Copy Markdown
Contributor

c074181 might be the only one worth merging to allow the Parser/Lexer objects to be GCed.

f4ea3c9 addresses a TODO although I didn't notice any major improvements (even though the removed wrapper method is often ~10% when profiling...). Unfortunately the wrapper method is still needed for the expressions returned from $parse, but use of getterFns within other expressions don't have the wrapper. This also required a minor error message change.

f4ea3c9 could be expanded in other ways though. Maybe allowing $parseed methods to return something such as a $$watchFn property that can be watched instead of the full expression being watched. The simple case would be returning the raw getterFn instead of the wrapper for simple foo.bar expressions. A more complicated case would be expressions such as myVar % 2 === 0 returning only the myVargetterFn to be watched (and then a special watch delegate to see if the full expression actually changed, which makes it more complicated...). Or only watching the input+args to filters etc. Not sure how common or useful those would be though...

The rest are mostly style/simplifying but I thought I'd leave them in there.

@btford

Copy link
Copy Markdown
Contributor

@jbedard thanks for the PR! can you add a benchmark to https://github.com/angular/angular.js/tree/master/benchmarks to prove that these changes are beneficial?

@btfordbtford added this to the 1.3.0-rc.2 milestone Sep 3, 2014
@jbedard
jbedardforce-pushed the parse-perf branch 2 times, most recently from 05ee69e to eb47e91CompareSeptember 4, 2014 15:57
@jbedard

Copy link
Copy Markdown
ContributorAuthor

@btford I've added a new benchpress benchmark for execution of $parse()ed expressions (fd45e8a). It currently has tests for the different types of expressions (property, binary op, filter, ...). Basically it generates data (2000 rows right now), ng-repeats a bunch of expressions (12 per test right now, except object literals that are too slow) and then measures the digest (x50 right now) time.

I updated eb47e91 such that the wrapper function is now only needed for one-time binding so $parse()ed properties now benefit form this as well. (A wrapper is needed for one-time because the one-time :: is not actually part of parsing so both ::foo and foo now return the exact same getterFn result, but they have different $$watchDelegates so they need to be different functions returned from $parse).

Here are the numbers (ms) for the current tests in the benchmark (12 expressions x 2000 rows x 50 digests):

TestOldNewExplanation
simple properties11094needs a few runs to stabilize but seems consistent
field accessors193178$parsePathGetter was ~5% in a quick profile which matches the numbers
field indexors11601160$parsePathGetter was negligible compared to ensureSafeObject + $parseObjectIndex
prop/operators206186$parsePathGetter was ~8% in a quick profile which matches the numbers
prop/filters328326$parsePathGetter was negligible compared to $parseFilter + pipe operator + binaryFn
prop/literals/func559522$parsePathGetter was mostly negligible compared to $parseFunctionCall + .apply + ensureSafeObject
prop/literals/{}14741440$parsePathGetter was negligible since it is mainly constants in the object, the .length seems to make the minor difference
prop/literals/[]1003979(same as object literal)

@jbedardjbedard mentioned this pull request Sep 5, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
…ions
This allows the parser and lexer objects to get GC-ed once the expression
is parsed.
Part of #8901
@IgorMinarIgorMinar self-assigned this Sep 8, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
@jbedard

Copy link
Copy Markdown
ContributorAuthor

Thanks for looking into all of these and getting them in so fast! And note my comment regarding the changed tests/error-message if you haven't already (can avoid changing the tests/message if we want, see jbedard@cec3344)

mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jbedard@btford@IgorMinar@Narretz@mary-poppins
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$parse performance/style - #8901

Closed
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf
Closed

$parse performance/style#8901
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf

Conversation

@jbedard

Copy link
Copy Markdown
Contributor

c074181 might be the only one worth merging to allow the Parser/Lexer objects to be GCed.

f4ea3c9 addresses a TODO although I didn't notice any major improvements (even though the removed wrapper method is often ~10% when profiling...). Unfortunately the wrapper method is still needed for the expressions returned from $parse, but use of getterFns within other expressions don't have the wrapper. This also required a minor error message change.

f4ea3c9 could be expanded in other ways though. Maybe allowing $parseed methods to return something such as a $$watchFn property that can be watched instead of the full expression being watched. The simple case would be returning the raw getterFn instead of the wrapper for simple foo.bar expressions. A more complicated case would be expressions such as myVar % 2 === 0 returning only the myVargetterFn to be watched (and then a special watch delegate to see if the full expression actually changed, which makes it more complicated...). Or only watching the input+args to filters etc. Not sure how common or useful those would be though...

The rest are mostly style/simplifying but I thought I'd leave them in there.

@btford

Copy link
Copy Markdown
Contributor

@jbedard thanks for the PR! can you add a benchmark to https://github.com/angular/angular.js/tree/master/benchmarks to prove that these changes are beneficial?

@btfordbtford added this to the 1.3.0-rc.2 milestone Sep 3, 2014
@jbedard
jbedardforce-pushed the parse-perf branch 2 times, most recently from 05ee69e to eb47e91CompareSeptember 4, 2014 15:57
@jbedard

Copy link
Copy Markdown
ContributorAuthor

@btford I've added a new benchpress benchmark for execution of $parse()ed expressions (fd45e8a). It currently has tests for the different types of expressions (property, binary op, filter, ...). Basically it generates data (2000 rows right now), ng-repeats a bunch of expressions (12 per test right now, except object literals that are too slow) and then measures the digest (x50 right now) time.

I updated eb47e91 such that the wrapper function is now only needed for one-time binding so $parse()ed properties now benefit form this as well. (A wrapper is needed for one-time because the one-time :: is not actually part of parsing so both ::foo and foo now return the exact same getterFn result, but they have different $$watchDelegates so they need to be different functions returned from $parse).

Here are the numbers (ms) for the current tests in the benchmark (12 expressions x 2000 rows x 50 digests):

TestOldNewExplanation
simple properties11094needs a few runs to stabilize but seems consistent
field accessors193178$parsePathGetter was ~5% in a quick profile which matches the numbers
field indexors11601160$parsePathGetter was negligible compared to ensureSafeObject + $parseObjectIndex
prop/operators206186$parsePathGetter was ~8% in a quick profile which matches the numbers
prop/filters328326$parsePathGetter was negligible compared to $parseFilter + pipe operator + binaryFn
prop/literals/func559522$parsePathGetter was mostly negligible compared to $parseFunctionCall + .apply + ensureSafeObject
prop/literals/{}14741440$parsePathGetter was negligible since it is mainly constants in the object, the .length seems to make the minor difference
prop/literals/[]1003979(same as object literal)

@jbedardjbedard mentioned this pull request Sep 5, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
…ions
This allows the parser and lexer objects to get GC-ed once the expression
is parsed.
Part of #8901
@IgorMinarIgorMinar self-assigned this Sep 8, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
@jbedard

Copy link
Copy Markdown
ContributorAuthor

Thanks for looking into all of these and getting them in so fast! And note my comment regarding the changed tests/error-message if you haven't already (can avoid changing the tests/message if we want, see jbedard@cec3344)

mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jbedard@btford@IgorMinar@Narretz@mary-poppins
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$parse performance/style - #8901

Closed
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf
Closed

$parse performance/style#8901
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf

Conversation

@jbedard

Copy link
Copy Markdown
Contributor

c074181 might be the only one worth merging to allow the Parser/Lexer objects to be GCed.

f4ea3c9 addresses a TODO although I didn't notice any major improvements (even though the removed wrapper method is often ~10% when profiling...). Unfortunately the wrapper method is still needed for the expressions returned from $parse, but use of getterFns within other expressions don't have the wrapper. This also required a minor error message change.

f4ea3c9 could be expanded in other ways though. Maybe allowing $parseed methods to return something such as a $$watchFn property that can be watched instead of the full expression being watched. The simple case would be returning the raw getterFn instead of the wrapper for simple foo.bar expressions. A more complicated case would be expressions such as myVar % 2 === 0 returning only the myVargetterFn to be watched (and then a special watch delegate to see if the full expression actually changed, which makes it more complicated...). Or only watching the input+args to filters etc. Not sure how common or useful those would be though...

The rest are mostly style/simplifying but I thought I'd leave them in there.

@btford

Copy link
Copy Markdown
Contributor

@jbedard thanks for the PR! can you add a benchmark to https://github.com/angular/angular.js/tree/master/benchmarks to prove that these changes are beneficial?

@btfordbtford added this to the 1.3.0-rc.2 milestone Sep 3, 2014
@jbedard
jbedardforce-pushed the parse-perf branch 2 times, most recently from 05ee69e to eb47e91CompareSeptember 4, 2014 15:57
@jbedard

Copy link
Copy Markdown
ContributorAuthor

@btford I've added a new benchpress benchmark for execution of $parse()ed expressions (fd45e8a). It currently has tests for the different types of expressions (property, binary op, filter, ...). Basically it generates data (2000 rows right now), ng-repeats a bunch of expressions (12 per test right now, except object literals that are too slow) and then measures the digest (x50 right now) time.

I updated eb47e91 such that the wrapper function is now only needed for one-time binding so $parse()ed properties now benefit form this as well. (A wrapper is needed for one-time because the one-time :: is not actually part of parsing so both ::foo and foo now return the exact same getterFn result, but they have different $$watchDelegates so they need to be different functions returned from $parse).

Here are the numbers (ms) for the current tests in the benchmark (12 expressions x 2000 rows x 50 digests):

TestOldNewExplanation
simple properties11094needs a few runs to stabilize but seems consistent
field accessors193178$parsePathGetter was ~5% in a quick profile which matches the numbers
field indexors11601160$parsePathGetter was negligible compared to ensureSafeObject + $parseObjectIndex
prop/operators206186$parsePathGetter was ~8% in a quick profile which matches the numbers
prop/filters328326$parsePathGetter was negligible compared to $parseFilter + pipe operator + binaryFn
prop/literals/func559522$parsePathGetter was mostly negligible compared to $parseFunctionCall + .apply + ensureSafeObject
prop/literals/{}14741440$parsePathGetter was negligible since it is mainly constants in the object, the .length seems to make the minor difference
prop/literals/[]1003979(same as object literal)

@jbedardjbedard mentioned this pull request Sep 5, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
…ions
This allows the parser and lexer objects to get GC-ed once the expression
is parsed.
Part of #8901
@IgorMinarIgorMinar self-assigned this Sep 8, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
@jbedard

Copy link
Copy Markdown
ContributorAuthor

Thanks for looking into all of these and getting them in so fast! And note my comment regarding the changed tests/error-message if you haven't already (can avoid changing the tests/message if we want, see jbedard@cec3344)

mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jbedard@btford@IgorMinar@Narretz@mary-poppins
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$parse performance/style - #8901

Closed
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf
Closed

$parse performance/style#8901
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf

Conversation

@jbedard

Copy link
Copy Markdown
Contributor

c074181 might be the only one worth merging to allow the Parser/Lexer objects to be GCed.

f4ea3c9 addresses a TODO although I didn't notice any major improvements (even though the removed wrapper method is often ~10% when profiling...). Unfortunately the wrapper method is still needed for the expressions returned from $parse, but use of getterFns within other expressions don't have the wrapper. This also required a minor error message change.

f4ea3c9 could be expanded in other ways though. Maybe allowing $parseed methods to return something such as a $$watchFn property that can be watched instead of the full expression being watched. The simple case would be returning the raw getterFn instead of the wrapper for simple foo.bar expressions. A more complicated case would be expressions such as myVar % 2 === 0 returning only the myVargetterFn to be watched (and then a special watch delegate to see if the full expression actually changed, which makes it more complicated...). Or only watching the input+args to filters etc. Not sure how common or useful those would be though...

The rest are mostly style/simplifying but I thought I'd leave them in there.

@btford

Copy link
Copy Markdown
Contributor

@jbedard thanks for the PR! can you add a benchmark to https://github.com/angular/angular.js/tree/master/benchmarks to prove that these changes are beneficial?

@btfordbtford added this to the 1.3.0-rc.2 milestone Sep 3, 2014
@jbedard
jbedardforce-pushed the parse-perf branch 2 times, most recently from 05ee69e to eb47e91CompareSeptember 4, 2014 15:57
@jbedard

Copy link
Copy Markdown
ContributorAuthor

@btford I've added a new benchpress benchmark for execution of $parse()ed expressions (fd45e8a). It currently has tests for the different types of expressions (property, binary op, filter, ...). Basically it generates data (2000 rows right now), ng-repeats a bunch of expressions (12 per test right now, except object literals that are too slow) and then measures the digest (x50 right now) time.

I updated eb47e91 such that the wrapper function is now only needed for one-time binding so $parse()ed properties now benefit form this as well. (A wrapper is needed for one-time because the one-time :: is not actually part of parsing so both ::foo and foo now return the exact same getterFn result, but they have different $$watchDelegates so they need to be different functions returned from $parse).

Here are the numbers (ms) for the current tests in the benchmark (12 expressions x 2000 rows x 50 digests):

TestOldNewExplanation
simple properties11094needs a few runs to stabilize but seems consistent
field accessors193178$parsePathGetter was ~5% in a quick profile which matches the numbers
field indexors11601160$parsePathGetter was negligible compared to ensureSafeObject + $parseObjectIndex
prop/operators206186$parsePathGetter was ~8% in a quick profile which matches the numbers
prop/filters328326$parsePathGetter was negligible compared to $parseFilter + pipe operator + binaryFn
prop/literals/func559522$parsePathGetter was mostly negligible compared to $parseFunctionCall + .apply + ensureSafeObject
prop/literals/{}14741440$parsePathGetter was negligible since it is mainly constants in the object, the .length seems to make the minor difference
prop/literals/[]1003979(same as object literal)

@jbedardjbedard mentioned this pull request Sep 5, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
…ions
This allows the parser and lexer objects to get GC-ed once the expression
is parsed.
Part of #8901
@IgorMinarIgorMinar self-assigned this Sep 8, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
@jbedard

Copy link
Copy Markdown
ContributorAuthor

Thanks for looking into all of these and getting them in so fast! And note my comment regarding the changed tests/error-message if you haven't already (can avoid changing the tests/message if we want, see jbedard@cec3344)

mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jbedard@btford@IgorMinar@Narretz@mary-poppins
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

$parse performance/style - #8901

Closed
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf
Closed

$parse performance/style#8901
jbedard wants to merge 7 commits into
angular:masterfrom
jbedard:parse-perf

Conversation

@jbedard

Copy link
Copy Markdown
Contributor

c074181 might be the only one worth merging to allow the Parser/Lexer objects to be GCed.

f4ea3c9 addresses a TODO although I didn't notice any major improvements (even though the removed wrapper method is often ~10% when profiling...). Unfortunately the wrapper method is still needed for the expressions returned from $parse, but use of getterFns within other expressions don't have the wrapper. This also required a minor error message change.

f4ea3c9 could be expanded in other ways though. Maybe allowing $parseed methods to return something such as a $$watchFn property that can be watched instead of the full expression being watched. The simple case would be returning the raw getterFn instead of the wrapper for simple foo.bar expressions. A more complicated case would be expressions such as myVar % 2 === 0 returning only the myVargetterFn to be watched (and then a special watch delegate to see if the full expression actually changed, which makes it more complicated...). Or only watching the input+args to filters etc. Not sure how common or useful those would be though...

The rest are mostly style/simplifying but I thought I'd leave them in there.

@btford

Copy link
Copy Markdown
Contributor

@jbedard thanks for the PR! can you add a benchmark to https://github.com/angular/angular.js/tree/master/benchmarks to prove that these changes are beneficial?

@btfordbtford added this to the 1.3.0-rc.2 milestone Sep 3, 2014
@jbedard
jbedardforce-pushed the parse-perf branch 2 times, most recently from 05ee69e to eb47e91CompareSeptember 4, 2014 15:57
@jbedard

Copy link
Copy Markdown
ContributorAuthor

@btford I've added a new benchpress benchmark for execution of $parse()ed expressions (fd45e8a). It currently has tests for the different types of expressions (property, binary op, filter, ...). Basically it generates data (2000 rows right now), ng-repeats a bunch of expressions (12 per test right now, except object literals that are too slow) and then measures the digest (x50 right now) time.

I updated eb47e91 such that the wrapper function is now only needed for one-time binding so $parse()ed properties now benefit form this as well. (A wrapper is needed for one-time because the one-time :: is not actually part of parsing so both ::foo and foo now return the exact same getterFn result, but they have different $$watchDelegates so they need to be different functions returned from $parse).

Here are the numbers (ms) for the current tests in the benchmark (12 expressions x 2000 rows x 50 digests):

TestOldNewExplanation
simple properties11094needs a few runs to stabilize but seems consistent
field accessors193178$parsePathGetter was ~5% in a quick profile which matches the numbers
field indexors11601160$parsePathGetter was negligible compared to ensureSafeObject + $parseObjectIndex
prop/operators206186$parsePathGetter was ~8% in a quick profile which matches the numbers
prop/filters328326$parsePathGetter was negligible compared to $parseFilter + pipe operator + binaryFn
prop/literals/func559522$parsePathGetter was mostly negligible compared to $parseFunctionCall + .apply + ensureSafeObject
prop/literals/{}14741440$parsePathGetter was negligible since it is mainly constants in the object, the .length seems to make the minor difference
prop/literals/[]1003979(same as object literal)

@jbedardjbedard mentioned this pull request Sep 5, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
IgorMinar pushed a commit that referenced this pull request Sep 7, 2014
…ions
This allows the parser and lexer objects to get GC-ed once the expression
is parsed.
Part of #8901
@IgorMinarIgorMinar self-assigned this Sep 8, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
IgorMinar pushed a commit to IgorMinar/angular.js that referenced this pull request Sep 9, 2014
@jbedard

Copy link
Copy Markdown
ContributorAuthor

Thanks for looking into all of these and getting them in so fast! And note my comment regarding the changed tests/error-message if you haven't already (can avoid changing the tests/message if we want, see jbedard@cec3344)

mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
mgallag pushed a commit to mgallag/angular.js that referenced this pull request Sep 10, 2014
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
ggershoni pushed a commit to ggershoni/angular.js that referenced this pull request Sep 29, 2015
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jbedard@btford@IgorMinar@Narretz@mary-poppins