Am 31.01.2013 23:37, schrieb Patrick Walton:
Hi everyone,
With the revamp of the scheduler underway, I'd like to propose a
change to the way C functions work.
Currently, we generate a shim and a stack switch for every function
call from Rust to C and likewise from C to Rust, except for functions
annotated with `#[rust_stack]`. These wrappers result in a significant
performance overhead. For some workloads this performance overhead is
acceptable in order to maintain small stacks. For some workloads the
performance overhead is undesirable.
For instance, the DOM in Servo requires lots of very small calls from
JavaScript to Rust. The overhead of stack switching swamps most of the
time here. Popular Web benchmarks will do things like
`someElement.clientX;` over and over, which require calls from
JavaScript to Rust to retrieve a cached value. So we must carefully
consider every CPU cycle spent in the C-to-Rust transition.
To address these issues I would like to propose a somewhat radical
change: don't have the compiler generate stack switching stubs at all.
Instead, the scheduler can expose a primitive that generates the stack
switch, and it's the programmer's responsibility to perform the stack
switch to call out to C functions. To avoid the obvious footgun here,
I propose a lint pass, on by default, that ensures that functions not
annotated with `#[rust_stack]` are called inside a stack switching
helper.
The rationale here is as follows:
1. It should be possible to group many C calls under a single stack
switching operation. For example:
do stackswitch {
c_function_1();
c_function_2();
c_function_3();
}
wouldn't it be possible for this case to just do:
extern mod lib_c {
#[rust_stack]
fn c_function_1();
#[rust_stack]
fn c_function_2();
#[rust_stack]
fn c_function_3();
}
and then calling it like above with *one* "do stackswitch"?
The default would still be to do a stack switch. If you need to call
c_function_1 sometimes with a stack switch, and sometimes
in a group of other functions (with just one stack switch for that
group), we could have something like this:
extern mod lib_c {
// This is the default
fn c_function_1();
#[rust_stack]
fn c_function_1() as rs_c_function1();
}
Then use lib_c::c_function_1() when you want a stack switch, or
rs_c_function1() without. One could go further
and auto generate for mod lib_c a sub module called "rs" (for rust
stack), where each function has a #[rust_stack]
directive in front of it, so you don't have to declare it twice.
This woudl give use: lib_c::c_function_1() and lib_c::rs::c_function_1().
Regards,
Michael
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev