Movatterモバイル変換


[0]ホーム

URL:


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

Even faster stack traces for _connection.py#2836

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
neoncube2 wants to merge14 commits intomicrosoft:main
base:main
Choose a base branch
Loading
fromneoncube2:custom-iterator-for-faster-stack-trace

Conversation

neoncube2
Copy link
Contributor

@neoncube2neoncube2 commentedApr 30, 2025
edited
Loading

This PR optimizes_connection.py even further. This furtherfixes#2744.

In the current code, we:

  1. Retrieve the entire stack, by callinggetattr(task, "__pw_stack__", inspect.stack(0))
  2. Parse the entire stack
  3. Throw away all of the parsed stack except for the first relevant frame, unless we're tracing (e.g. unlessself._tracing_count > 0)

This PR makes it so that we only retrieve and parse as much of the stack as necessary.

Test code:

asyncdeftest_speed_test(page:Page)->None:start_time=time.time()foriinrange(0,1000):awaitpage.evaluate('() => 1 + 1')print(time.time()-start_time)

Before this PR: 4s
With this PR: 1.75s

Speed improvement: 2.3x

I'd like add tests for whenself._is_internal_type = True, but I'm not sure the best way to go about constructing an internal type and then triggering an exception in it. (Any suggestions?)

Similarly, I'd like to add tests for whengetattr(task, "__pw_stack__") returns a value, but again, I'm not sure when this occurs. If anyone has suggestions, please let me know! :)

@neoncube2neoncube2 changed the titleEven faster stack tracesEven faster stack traces for _connection.pyApr 30, 2025
@neoncube2
Copy link
ContributorAuthor

Ready to rerun tests

@neoncube2
Copy link
ContributorAuthor

Probably best to wait until#2840 is merged, and then I can run checks locally.

def needs_full_stack_trace(self) -> bool:
return self._tracing_count > 0

def get_frame_info(self) -> Iterator[FrameInfo]:
Copy link
Member

Choose a reason for hiding this comment

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

Just thinking out loud - why does it need to be an Iterator in order to get the faster stacktraces? I assume that we call it only when we actually need it in line 546 and 566?

Also should we maybe use this similar function in playwright/_impl/_sync_base.pyplaywright/_impl/_sync_base.py:108` ? Then sync users - what the majority is - would benefit as well?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

As to your question: In the original code, when we were callinginspect.stack(0), it would immediately walk the entire stack (essentially, it would callframe.f_back in a loop until there were no more frames). This is pretty expensive. By using an iterator, we delay walking the stack until we need it, and then we can only walk part of the stack (becauseframe.f_back is only called when we need another frame)

Basically: Callingframe.f_back is more expensive than one might think.

Thanks for the heads up aboutplaywright/_impl/_sync_base.pyplaywright/_impl/_sync_base.py:108! :) No wonder I couldn't find any information about__pw_stack__... I thought it was being set byasyncio, but it's actually being set by this package! XD

Let me take a look.

Copy link
ContributorAuthor

@neoncube2neoncube2May 6, 2025
edited
Loading

Choose a reason for hiding this comment

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

@mxschmitt Now that I'm working on this again, I see what you mean about the iterator. I think that once I merge the logic in_sync_base.py and_connection.py, this PR should be a lot cleaner (and faster!) :)

mxschmitt reacted with thumbs up emoji
@neoncube2
Copy link
ContributorAuthor

@mxschmitt I'm still working on this, but I've split off a few simple and easy to review optimizations into#2844

@neoncube2
Copy link
ContributorAuthor

neoncube2 commentedMay 14, 2025
edited
Loading

@mxschmitt While continuing to work on this, I've discovered something interesting.

  1. In_sync_base.py, we set__pw_stack__ and__pw_stack_trace__
  2. In_connection.py, we check to see if the current task has__pw_stack__ or__pw_stack_trace__ set, and if not, we generate a new stack trace to use.

Interestingly, for all of the tests in thetests\ folder,__pw_stack__ and__pw_stack_trace__ are alwaysNone whenever they're retrieved in_connection.py. This makes me wonder if we should stop setting__pw_stack__ and__pw_stack_trace__ in_sync_base.py (because these values are never being used) or if we just need to better tests to cover this case.

Any thoughts?

@mxschmitt
Copy link
Member

I wonder when it was introduced if it was any different back then:c05cad2#diff-291261f4050ff453e2c661edf96c77af65a779b75815708d924809ee49d5dc64 - would be great to find out if it was used back in the days and not anymore or if our tests don't have the coverage.

@neoncube2
Copy link
ContributorAuthor

neoncube2 commentedJun 5, 2025
edited
Loading

@mxschmitt Similarly, it might be nice to know if sendingapiName andinternal as part of the metadata is necessary or was just added because it was nice to have:

@neoncube2
Copy link
ContributorAuthor

I think that probably the best way to move this PR forward would be to modify the monkeypatch by@SichangHe (#2744 (comment)), as it looks like it preserved the best of all worlds and has the least chance of breakage :)

I'm thinking it would probably make sense to open a new PR for that, but let's keep this PR open for now.

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

@mxschmittmxschmittmxschmitt left review comments

At least 1 approving review is required to merge this pull request.

Assignees
No one assigned
Labels
None yet
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

[Feature]: Option to disableinspect.stack() calls for performance optimization
2 participants
@neoncube2@mxschmitt

[8]ページ先頭

©2009-2025 Movatter.jp