On Fri, Feb 1, 2013 at 12:09 PM, Michael Neumann <mneum...@ntecs.de> wrote:
> 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 > Rust-dev@mozilla.org > https://mail.mozilla.org/**listinfo/rust-dev<https://mail.mozilla.org/listinfo/rust-dev> > I would have a stupid proposal: what if the C function declaration was annotated not with #[rust_stack] but with #[stack 5k] instead. That is, instead of having a single blunt tool, let the programmer declare how much stack is necessary for the C function and let the compiler reason about it to guarantee that enough stack is available. extern mod lib_c { #[stack 4k] fn c_function_1(); #[stack unlimited] fn c_function_2(); #[stack 16k] fn c_function_3(); } Then when the compiler sees a bunch of C functions: fn func(x: int) { c_function_1(); c_function_1(); c_function_1(); c_function_3(); } => if one is marked as "unlimited", then it performs stack switching (once); this can deferred to the branch the function is called in if judged "better". => otherwise, it evaluates the maximum amount of stack needed and prepares it at the beginning of the function, as usual Advantages: + Code is not invalidated, only the function declarations are, and it's easy enough to do a bulk replace #[rust_stack] -> #[stack 4k] + The information can bubble up at "func" automatically, so that caller of "func" can perform the switch/reservation themselves if it's judged profitable. Disadvantages: - Myth of the sufficiently smart compiler spotted. -- Matthieu
_______________________________________________ Rust-dev mailing list Rust-dev@mozilla.org https://mail.mozilla.org/listinfo/rust-dev