Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-135953: Add flamegraph reporter to sampling profiler #138304

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

Closed
lkollar wants to merge 19 commits into python:main from lkollar:profiling/flamegraph

Conversation

Copy link
Contributor

@lkollar lkollar commented Aug 31, 2025
edited by bedevere-app bot
Loading

Add --flamegraph option to the sampling profiler to produce a self-contained HTML report.

Copy link
Member

@AA-Turner AA-Turner left a comment

Choose a reason for hiding this comment

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

Brief review of the JS code. Please disregard any feedback that is irrelevant due to use of the D3 framework -- I am primarily used to working with vanilla/framework-less JS.

On formatting, obviously PEP 8 doesn't apply as it's not Python code, but it would still be good to keep to the spirit of it, and wrap at 79 characters or thereabouts for readability.

I've had advice/reviews in the past that from a security perspective it's best to avoid constructing HTML in JS directly and instead use e.g. document.createElement(). I don't know enough about the D3/JS interactions to know if this applies here, though. There was one place that looked like it was performing HTML escaping in JavaScript, which seems like something we might consider doing in the Python layer before the data gets to JS?

A

Copy link
Member

@AA-Turner AA-Turner Sep 9, 2025

Choose a reason for hiding this comment

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

Potentially use the SVG instead? https://github.com/python/devguide/blob/main/_static/python-logo.svg?short_path=f69d24a

The SVG is ~18x smaller, but it hasn't been minified.

Copy link
Member

@AA-Turner AA-Turner Sep 9, 2025

Choose a reason for hiding this comment

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

Perhaps add .min.js to the list of generated files in .gitattributes?

Comment on lines +19 to +46
.style("position", "absolute")
.style("padding", "20px")
.style("background", "white")
.style("color", "#2e3338")
.style("border-radius", "8px")
.style("font-size", "14px")
.style("border", "1px solid #e9ecef")
.style("box-shadow", "0 8px 30px rgba(0, 0, 0, 0.15)")
.style("z-index", "1000")
.style("pointer-events", "none")
.style("font-weight", "400")
.style("line-height", "1.5")
.style("max-width", "500px")
.style("font-family", "'Source Sans Pro', sans-serif")
.style("opacity", 0);
Copy link
Member

@AA-Turner AA-Turner Sep 9, 2025

Choose a reason for hiding this comment

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

Is it possible to apply these styles via a class, instead of inline?

}

const pythonTooltip = flamegraph.tooltip.defaultFlamegraphTooltip();

Copy link
Member

@AA-Turner AA-Turner Sep 9, 2025

Choose a reason for hiding this comment

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

Suggested change

const sourceLines = source
.map(
(line) =>
`<div style="font-family: 'SF Mono', 'Monaco', 'Consolas', monospace; font-size: 12px; color: ${line.startsWith("→") ? "#3776ab" : "#5a6c7d"}; white-space: pre; line-height: 1.4; padding: 2px 0;">${line.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")}</div>`,
Copy link
Member

@AA-Turner AA-Turner Sep 9, 2025

Choose a reason for hiding this comment

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

Likewise, is it possible to use a class instead of inline styles?

Should we escape the HTML (line.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")) whilst we're still in Python?

For the color codes, could we use CSS variables so that if we change them in the future, we only need to change it in one place?

Comment on lines 87 to 94
${
calls > 0
? `
<span style="color: #5a6c7d; font-weight: 500;">Function Calls:</span>
<strong style="color: #2e3338;">${calls.toLocaleString()}</strong>
`
: ""
}
Copy link
Member

@AA-Turner AA-Turner Sep 9, 2025

Choose a reason for hiding this comment

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

Perhaps extract to local variables instead of nested substitutions?

}

// Wait for libraries to load
document.addEventListener("DOMContentLoaded", function () {
Copy link
Member

@AA-Turner AA-Turner Sep 9, 2025

Choose a reason for hiding this comment

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

My understanding is that DOMContentLoaded may fire before the script loads, so the suggested pattern is to check for document.readyState. I don't know if this applies here or not, though.

Comment on lines 240 to 241
// Add search functionality - wait for chart to be ready
if (searchInput) {
Copy link
Member

@AA-Turner AA-Turner Sep 9, 2025

Choose a reason for hiding this comment

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

Could this block be extracted to a helper function?

def _create_flamegraph_html(self, data):
data_json = json.dumps(data)

template_dir = pathlib.Path(__file__).parent
Copy link
Member

@AA-Turner AA-Turner Sep 9, 2025

Choose a reason for hiding this comment

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

Should we use importlib.resources here? I believe e.g. for the Windows embedable builds, the stdlib is distributed as a zip file so modules might not have a __file__ attribute.

Copy link
Member

I've had advice/reviews in the past that from a security perspective it's best to avoid constructing HTML in JS directly and instead use e.g. document.createElement(). I don't know enough about the D3/JS interactions to know if this applies here, though. There was one place that looked like it was performing HTML escaping in JavaScript, which seems like something we might consider doing in the Python layer before the data gets to JS?

Since this is a static template there are no advantages of doing this and having the web parts in Python is a bit messy specially since we cannot use something like Jinja. Having all the web parts in JS or the template itself is a common practice for this case and keeps the Python code focused just on the data part and not in creating HTML. Also since this is just a static file served with no dependencies so there are no concerns aboutsecurity or injection so I prefer to maximize maintainability.

I will give it a pass with prettier to format it as you indicate :)

AA-Turner reacted with thumbs up emoji

Copy link
Contributor Author

lkollar commented Sep 9, 2025

Thanks for the review @AA-Turner. I think I addressed everything except for the comments around constructing HTML in JS. I also ended up breaking up the JS functions a bit in 7c4d792 as it was getting really unwieldy and I think this will make maintenance easier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Reviewers

@AA-Turner AA-Turner AA-Turner left review comments

@emmatyping emmatyping emmatyping left review comments

@pablogsal pablogsal pablogsal left review comments

Assignees
No one assigned
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

AltStyle によって変換されたページ (->オリジナル) /