Skip to content

proc_macro: don't pass a client-side function pointer through the server. #97461

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 1 commit into from
May 28, 2022

Conversation

eddyb
Copy link
Member

@eddyb eddyb commented May 27, 2022

Before this PR, proc_macro::bridge::Client<F> contained both:

  • the C ABI entry-point run, that the server can call to start the client
  • some "payload" f: F passed to that entry-point
    • in practice, this was always a (client-side Rust ABI) fn pointer to the actual function the proc macro author wrote, i.e. #[proc_macro] fn foo(input: TokenStream) -> TokenStream

In other words, the client was passing one of its (Rust) fn pointers to the server, which was passing it back to the client, for the client to call (see later below for why that was ever needed).

I was inspired by @nnethercote's attempt to remove the get_handle_counters field from Client (see #97004 (comment)), which combined with removing the f ("payload") field, could theoretically allow for a #[repr(transparent)] Client that mostly just newtypes the C ABI entry-point fn pointer (and in the context of e.g. wasm isolation, that's all you want, since you can reason about it from outside the wasm VM, as just a 32-bit "function table index", that you can pass to the wasm VM to call that function).


So this PR removes that "payload". But it's not a simple refactor: the reason the field existed in the first place is because monomorphizing over a function type doesn't let you call the function without having a value of that type, because function types don't implement anything like Default, i.e.:

extern "C" fn ffi_wrapper<A, R, F: Fn(A) -> R>(arg: A) -> R {
    let f: F = ???; // no way to get a value of `F`
    f(arg)
}

That could be solved with something like this, if it was allowed:

extern "C" fn ffi_wrapper<
    A, R,
    F: Fn(A) -> R,
    const f: F // not allowed because the type is a generic param
>(arg: A) -> R {
    f(arg)
}

Instead, this PR contains a workaround in proc_macro::bridge::selfless_reify (see its module-level comment for more details) that can provide something similar to the ffi_wrapper example above, but limited to F being Copy and ZST (and requiring an F value to prove the caller actually can create values of F and it's not uninhabited or some other unsound situation).


Hopefully this time we don't have a performance regression, and this has a chance to land.

cc @mystor @bjorn3

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label May 27, 2022
@rust-highfive

This comment was marked as off-topic.

@rust-highfive
Copy link
Contributor

r? @petrochenkov

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 27, 2022
@eddyb
Copy link
Member Author

eddyb commented May 27, 2022

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion.

@rustbot label: +S-waiting-on-perf

@rustbot rustbot added the S-waiting-on-perf Status: Waiting on a perf run to be completed. label May 27, 2022
@bors
Copy link
Collaborator

bors commented May 27, 2022

⌛ Trying commit ba869ade7c9da9b487be4457f3826b33a4fa2f20 with merge 3fd3bd768ea1fe15e6ae0e911231ff515283a2d0...

@rust-log-analyzer

This comment has been minimized.

@eddyb
Copy link
Member Author

eddyb commented May 27, 2022

(I have a fix for the tidy error but I'll only push it after the try build hopefully succeeds, to avoid confusing it - IIRC in the past the bot forgot to post any updates if the HEAD of the branch changed)

Copy link
Member

@bjorn3 bjorn3 left a comment

Choose a reason for hiding this comment

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

Overall approach makes sense to me.

LL | pub const fn custom_derive(
| ^^^^^^^^^^^^^
LL | expand: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ProcMacro::custom_derive`
Copy link
Member

Choose a reason for hiding this comment

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

This is a diagnostic regression to the point where I think it becomes next to useless for many people.

Copy link
Member

Choose a reason for hiding this comment

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

Taking a look again on my desktop as opposed to my phone, I guess it is not too bad.

@bors
Copy link
Collaborator

bors commented May 27, 2022

☀️ Try build successful - checks-actions
Build commit: 3fd3bd768ea1fe15e6ae0e911231ff515283a2d0 (3fd3bd768ea1fe15e6ae0e911231ff515283a2d0)

@rust-timer
Copy link
Collaborator

Queued 3fd3bd768ea1fe15e6ae0e911231ff515283a2d0 with parent 56fd680, future comparison URL.

@rust-timer
Copy link
Collaborator

Finished benchmarking commit (3fd3bd768ea1fe15e6ae0e911231ff515283a2d0): comparison url.

Instruction count

  • Primary benchmarks: mixed results
  • Secondary benchmarks: 🎉 relevant improvements found
mean1 max count2
Regressions 😿
(primary)
0.6% 0.7% 3
Regressions 😿
(secondary)
N/A N/A 0
Improvements 🎉
(primary)
-0.4% -0.8% 12
Improvements 🎉
(secondary)
-2.7% -5.3% 10
All 😿🎉 (primary) -0.2% -0.8% 15

Max RSS (memory usage)

Results
  • Primary benchmarks: 😿 relevant regression found
  • Secondary benchmarks: mixed results
mean1 max count2
Regressions 😿
(primary)
2.6% 2.6% 1
Regressions 😿
(secondary)
2.1% 2.7% 2
Improvements 🎉
(primary)
N/A N/A 0
Improvements 🎉
(secondary)
-1.5% -2.1% 2
All 😿🎉 (primary) 2.6% 2.6% 1

Cycles

Results
  • Primary benchmarks: no relevant changes found
  • Secondary benchmarks: mixed results
mean1 max count2
Regressions 😿
(primary)
N/A N/A 0
Regressions 😿
(secondary)
2.2% 2.2% 1
Improvements 🎉
(primary)
N/A N/A 0
Improvements 🎉
(secondary)
-3.7% -4.0% 2
All 😿🎉 (primary) N/A N/A 0

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf.

Next Steps: If you can justify the regressions found in this try perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please fix the regressions and do another perf run. If the next run shows neutral or positive results, the label will be automatically removed.

@bors rollup=never
@rustbot label: +S-waiting-on-review -S-waiting-on-perf +perf-regression

Footnotes

  1. the arithmetic mean of the percent change 2 3

  2. number of relevant changes 2 3

@rustbot rustbot added perf-regression Performance regression. and removed S-waiting-on-perf Status: Waiting on a perf run to be completed. labels May 27, 2022
@eddyb eddyb force-pushed the proc-macro-less-payload branch from ba869ad to 78a83b0 Compare May 27, 2022 22:01
@petrochenkov
Copy link
Contributor

r? @bjorn3

@rust-highfive rust-highfive assigned bjorn3 and unassigned petrochenkov May 27, 2022
@bjorn3
Copy link
Member

bjorn3 commented May 28, 2022

@bors r+

@bors
Copy link
Collaborator

bors commented May 28, 2022

📌 Commit 78a83b0 has been approved by bjorn3

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 28, 2022
@bors
Copy link
Collaborator

bors commented May 28, 2022

⌛ Testing commit 78a83b0 with merge 116201e...

@bors
Copy link
Collaborator

bors commented May 28, 2022

☀️ Test successful - checks-actions
Approved by: bjorn3
Pushing 116201e to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label May 28, 2022
@bors bors merged commit 116201e into rust-lang:master May 28, 2022
@rustbot rustbot added this to the 1.63.0 milestone May 28, 2022
@rust-timer
Copy link
Collaborator

Finished benchmarking commit (116201e): comparison url.

Instruction count

  • Primary benchmarks: mixed results
  • Secondary benchmarks: 🎉 relevant improvements found
mean1 max count2
Regressions 😿
(primary)
0.5% 0.5% 2
Regressions 😿
(secondary)
N/A N/A 0
Improvements 🎉
(primary)
-0.4% -0.8% 11
Improvements 🎉
(secondary)
-2.6% -5.4% 10
All 😿🎉 (primary) -0.3% -0.8% 13

Max RSS (memory usage)

Results
  • Primary benchmarks: mixed results
  • Secondary benchmarks: mixed results
mean1 max count2
Regressions 😿
(primary)
2.4% 2.4% 1
Regressions 😿
(secondary)
3.7% 3.7% 1
Improvements 🎉
(primary)
-3.3% -5.9% 3
Improvements 🎉
(secondary)
-4.2% -5.5% 3
All 😿🎉 (primary) -1.9% -5.9% 4

Cycles

Results
  • Primary benchmarks: 😿 relevant regression found
  • Secondary benchmarks: 🎉 relevant improvements found
mean1 max count2
Regressions 😿
(primary)
2.2% 2.2% 1
Regressions 😿
(secondary)
N/A N/A 0
Improvements 🎉
(primary)
N/A N/A 0
Improvements 🎉
(secondary)
-3.1% -4.2% 6
All 😿🎉 (primary) 2.2% 2.2% 1

If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf.

Next Steps: If you can justify the regressions found in this perf run, please indicate this with @rustbot label: +perf-regression-triaged along with sufficient written justification. If you cannot justify the regressions please open an issue or create a new PR that fixes the regressions, add a comment linking to the newly created issue or PR, and then add the perf-regression-triaged label to this PR.

@rustbot label: +perf-regression

Footnotes

  1. the arithmetic mean of the percent change 2 3

  2. number of relevant changes 2 3

@eddyb eddyb deleted the proc-macro-less-payload branch May 29, 2022 05:30
@pnkfelix
Copy link
Member

pnkfelix commented Jun 1, 2022

Visiting for rustc-perf triage.

  • On the primary benchmarks, this mostly yielded small improvements; the one exception was serde_derive, which regressed by ~0.5% for the full and incr-full variants.
Benchmark Profile Scenario % Change Significance Factor?
serde_derive-1.0.136 debug full 0.50% 1.69x
serde_derive-1.0.136 debug incr-full 0.47% 1.88x
  • Looking at the flamegraphs for the before and after commits, and at the table at bottom of details page, it seems like the instruction-count regression is in codegen_module
  • Looking at the history of serde_derive-debug (massively zoomed in on the "Percent Delta from First" Graph kind), it seems reasonable to think that something did happen on this PR:

image

  • .... but I also don't really think its a big enough regression to be worth tearing our hair out over. This is a (smallish) win overall, and even for serde_derive-debug, it is a small regression in the context of much larger wins, so overall the trajectory is good.

@rustbot label: +perf-regression-triaged

@rustbot rustbot added the perf-regression-triaged The performance regression has been triaged. label Jun 1, 2022
@eddyb
Copy link
Member Author

eddyb commented Jun 18, 2022

@pnkfelix Sorry, didn't see this at first - the explanation is that a lot of proc_macro changes are tradeoffs: taking slightly longer to compile a proc macro can help it run faster, and we're effectively measuring "runtime" performance of proc macros in the benchmarks that improved.

(Note, however, that since Cargo doesn't even build proc macro crates with optimizations, the effect is not as drastic as it could otherwise be)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. perf-regression Performance regression. perf-regression-triaged The performance regression has been triaged. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants