Skip to content

[WebProfilerBundle] Improve Ajax Profiling Performance (javascript) #20197

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 13, 2016

Conversation

patrick-mcdougle
Copy link
Contributor

Q A
Branch? master
Bug fix? kinda (is bad performance a bug?)
New feature? kinda (is increased performance a feature?)
BC breaks? no (unless performance is a BC break)
Deprecations? no
Tests pass? do we have JS tests?
Fixed tickets #20155
License MIT
Doc PR n/a

The old version of this JS re-rendered the entire list of ajax calls which was causing some performance issues when people had high numbers of ajax requests (increasingly common as people create SPAs.

This PR changes the behavior of the ajax profiler to be more smart about the DOM manipulations it makes. Instead of re-rendering the entire list, on any AJAX requests/responses, it instead adds the row to the profiler when an AJAX request is made, adding the DOM node as a property of the request on the requestStack. When the AJAX response comes back, it updates the existing DOM node instead of re-creating it (and all of the others).

I've tested this on my machine using a modern version of chrome. I don't think I'm doing anything fancy, so I think the likelihood that I broke something is minimal.

I've left a couple of the commits separate, because they represent distinct ideas. The first commit is just some consistency/cleanup. The second commit is the meat of the work. Its diff is basically useless since I've added two new functions and modified one function heavily. I tried to make the diff as easy to read as possible, but it's still pretty rough. The third commit removes some functions/calls that I don't think need to be there now that this is re-written, but I wanted to leave them in a separate commit for ease of revert if they are indeed needed.

var renderAjaxRequests = function() {
var requestCounter = document.querySelectorAll('.sf-toolbar-ajax-requests');
if (!requestCounter.length) {
var requestCounter = document.querySelectorAll('.sf-toolbar-ajax-requests')[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you want only one,use document.querySelector instead

return;
}
requestCounter.textContent = requestStack.length;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this DOM updates should be done after the retrieval of other needed nodes, to group read and writes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the readability > that the performance gain by moving all the writes in the same place. But will re-arrange if you still disagree.


var row = document.createElement('tr');
rows.insertBefore(row, rows.firstChild);
var infoSpan = document.querySelectorAll(".sf-toolbar-ajax-info")[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

querySelector should be used here

durationCell.textContent = '-';
}
row.appendChild(durationCell);
var tbody = document.querySelectorAll('.sf-toolbar-ajax-request-list')[0];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be querySelector

@@ -237,91 +241,86 @@
}

{% if excluded_ajax_paths is defined %}
if (window.fetch && window.fetch.polyfill === undefined) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep the indentation inside the Twig if. It makes the template much more readable

@patrick-mcdougle
Copy link
Contributor Author

@stof if you get a chance, could you review again? Merge maybe?

@patrick-mcdougle
Copy link
Contributor Author

@stof any chance this can get on the 3.2 train?

@javiereguiluz javiereguiluz added this to the 3.3 milestone Nov 7, 2016
@patrick-mcdougle
Copy link
Contributor Author

@stof @fabpot Now that we've bumped to 3.3, how about a merge on this bad boy?

@patrick-mcdougle
Copy link
Contributor Author

@javiereguiluz @stof @fabpot Bump

@fabpot
Copy link
Member

fabpot commented Dec 13, 2016

Thank you @patrick-mcdougle.

@fabpot fabpot merged commit 65e391c into symfony:master Dec 13, 2016
fabpot added a commit that referenced this pull request Dec 13, 2016
… (javascript) (patrick-mcdougle)

This PR was squashed before being merged into the 3.3-dev branch (closes #20197).

Discussion
----------

[WebProfilerBundle] Improve Ajax Profiling Performance (javascript)

| Q | A |
| --- | --- |
| Branch? | master |
| Bug fix? | kinda (is bad performance a bug?) |
| New feature? | kinda (is increased performance a feature?) |
| BC breaks? | no (unless performance is a BC break) |
| Deprecations? | no |
| Tests pass? | do we have JS tests? |
| Fixed tickets | #20155 |
| License | MIT |
| Doc PR | n/a |

The old version of this JS re-rendered the entire list of ajax calls which was causing some performance issues when people had high numbers of ajax requests (increasingly common as people create SPAs.

This PR changes the behavior of the ajax profiler to be more smart about the DOM manipulations it makes. Instead of re-rendering the entire list, on any AJAX requests/responses, it instead adds the row to the profiler when an AJAX request is made, adding the DOM node as a property of the request on the requestStack. When the AJAX response comes back, it updates the existing DOM node instead of re-creating it (and all of the others).

I've tested this on my machine using a modern version of chrome. I don't think I'm doing anything fancy, so I think the likelihood that I broke something is minimal.

I've left a couple of the commits separate, because they represent distinct ideas. The first commit is just some consistency/cleanup. The second commit is the meat of the work. Its diff is basically useless since I've added two new functions and modified one function heavily. I tried to make the diff as easy to read as possible, but it's still pretty rough. The third commit removes some functions/calls that I don't think need to be there now that this is re-written, but I wanted to leave them in a separate commit for ease of revert if they are indeed needed.

Commits
-------

65e391c Replace occurances of querySelectorAll with querySelector
fddff26 Put back the indentation
9942edd Remove unnecessary method calls/definitions
2c053ee Rewrite ajax profiling for performance
da621c9 Fix indentation & JS Cleanup
@patrick-mcdougle patrick-mcdougle deleted the fix-20155 branch January 17, 2017 02:35
@nicolas-grekas nicolas-grekas modified the milestones: 3.x, 3.3 Mar 24, 2017
@fabpot fabpot mentioned this pull request May 1, 2017
ostrolucky pushed a commit to ostrolucky/symfony that referenced this pull request Mar 25, 2018
…ormance (javascript) (patrick-mcdougle)

This PR was squashed before being merged into the 3.3-dev branch (closes symfony#20197).

Discussion
----------

[WebProfilerBundle] Improve Ajax Profiling Performance (javascript)

| Q | A |
| --- | --- |
| Branch? | master |
| Bug fix? | kinda (is bad performance a bug?) |
| New feature? | kinda (is increased performance a feature?) |
| BC breaks? | no (unless performance is a BC break) |
| Deprecations? | no |
| Tests pass? | do we have JS tests? |
| Fixed tickets | symfony#20155 |
| License | MIT |
| Doc PR | n/a |

The old version of this JS re-rendered the entire list of ajax calls which was causing some performance issues when people had high numbers of ajax requests (increasingly common as people create SPAs.

This PR changes the behavior of the ajax profiler to be more smart about the DOM manipulations it makes. Instead of re-rendering the entire list, on any AJAX requests/responses, it instead adds the row to the profiler when an AJAX request is made, adding the DOM node as a property of the request on the requestStack. When the AJAX response comes back, it updates the existing DOM node instead of re-creating it (and all of the others).

I've tested this on my machine using a modern version of chrome. I don't think I'm doing anything fancy, so I think the likelihood that I broke something is minimal.

I've left a couple of the commits separate, because they represent distinct ideas. The first commit is just some consistency/cleanup. The second commit is the meat of the work. Its diff is basically useless since I've added two new functions and modified one function heavily. I tried to make the diff as easy to read as possible, but it's still pretty rough. The third commit removes some functions/calls that I don't think need to be there now that this is re-written, but I wanted to leave them in a separate commit for ease of revert if they are indeed needed.

Commits
-------

65e391c Replace occurances of querySelectorAll with querySelector
fddff26 Put back the indentation
9942edd Remove unnecessary method calls/definitions
2c053ee Rewrite ajax profiling for performance
da621c9 Fix indentation & JS Cleanup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants