Skip to content
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

allow choosing the initial stack size #5768

Closed
thestinger opened this issue Apr 7, 2013 · 12 comments
Closed

allow choosing the initial stack size #5768

thestinger opened this issue Apr 7, 2013 · 12 comments
Labels
A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code.

Comments

@thestinger
Copy link
Contributor

The main task could just start with a big stack segment (like 8MiB), and choosing whether a spawned task uses the conservative stack growth strategy could be optional. Segmented stacks are a scalability feature so the main task won't matter. On x86_64 Linux, a stack will be lazily allocated page-by-page anyway and the address space doesn't matter, it just won't shrink back down like a segmented stack. I don't know about other platforms.

The API could be opt-in or opt-out, as long as it's possible to use segmented stacks for scaling I/O and avoid them for code that really needs performance (memory locality matters a lot, the allocations themselves probably aren't too bad).

@brson, @pcwalton: any thoughts on whether this would be a sane thing to do?

@brson
Copy link
Contributor

brson commented Apr 8, 2013

When you say that 'on x86_64 linux, a stack will be lazily allocated page-by-page anyway' that would only be true if the main task ran on the main thread and used its stack (or possibly if it used a pthread's stack), which it does not. The thread's stack is used by the scheduler, not tasks, and no tasks even run on the main thread by default.

We could dedicate the main thread to the main task - it has been requested before - but it has a lot of consequences, making the main task 'special' in a number of ways (e.g. tasks that are expected to be on the main thread can never migrate to other threads, communication with the main task will have different performance characteristics than other general tasks). Personally, I like that there is no difference between the main task and any other task. It's consistent. It's also a little wasteful though since every program is guaranteed to have at least two threads.

If the only goal is to avoid allocating stack segments then I think a solution in which users can declare that a function requires a large stack is sufficient, or one where they call a closure that preallocates a large stack.

#[fixed_stack_segment]
fn main() { }

@thestinger
Copy link
Contributor Author

I wasn't really thinking about a pthread stack vs. the stack segment Rust grabs with malloc since both will be allocated only when they actually touch a page.

@brson
Copy link
Contributor

brson commented Apr 8, 2013

you're right about that of course.

@bblum
Copy link
Contributor

bblum commented Jun 21, 2013

RUST_MIN_STACK controls the preallocated stack size, right? I feel like we can just couple that with a compiler option to omit the stack-check prelude. I doubt that a per-function attribute will be sufficient for the common use case.

nominating feature-complete milestone

@bblum
Copy link
Contributor

bblum commented Jun 21, 2013

One of my friends is presently writing a kernel with rust, so I asked what he's doing to deal with this, and he said he's set __morestack to just fail. This could be an "intermediate" approach, as it doesn't save the speed of omitting function preludes, but it does save the allocation part. The other nice part of that is you get your canary automatically checked at each function call. So in addition to being able to omit the prelude when compiling ("disabling the canary"), you could opt to leave those in but use a runtime flag to disable the allocation.

@thestinger
Copy link
Contributor Author

@bblum: it would be nice to be able to set it on a per-task basis though, so you can use tasks with big stacks (likely mapped 1:1 with threads) and still use a bunch of lightweight ones for I/O

@bblum
Copy link
Contributor

bblum commented Jun 22, 2013

oh that's a good point. you couldn't get the removing-the-prelude optimization, but you could have a scheduler option to stop it from allocating.

@thestinger
Copy link
Contributor Author

I think the best way to do this would be exposing the ability to choose the initial stack segment size in the task module so I updated the title to reflect that.

do spawn(0) {
    // smallest possible stack size, the current default
}

do spawn(std::os::stack_size()) {
    // get the platform stack size from pthread_attr_getstacksize
}

do spawn(4 * 1024) {
    // reserve close to the known required space, to get the best of both worlds
}

It would be nice if we had default parameters... although we might disagree on the default.

@thestinger
Copy link
Contributor Author

@bblum: When we do implement segmented stacks again, we could investigate the performance characteristics of using a single guard page at the end of every stack and catching the failure with a signal.

It would mean the minimal stack size would be 8K (although it would never actually commit the second page), but we would be able to teach LLVM to emit all __morestack preludes for functions using less than 4K.

@graydon
Copy link
Contributor

graydon commented Aug 15, 2013

accepted for backwards-compatible milestone

@alexcrichton
Copy link
Member

In today's meeting we have decided to jettison segmented stacks. I believe that the decision renders this issue moot because there's only one stack size for a task and it's always decided at the time the task is spawned. I may be wrong though, so feel free to reopen!

@stiv-yakovenko
Copy link

So is there a way to set stack size nowdays?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows C-enhancement Category: An issue proposing an enhancement or a PR with one. I-slow Issue: Problems and improvements with respect to performance of generated code.
Projects
None yet
Development

No branches or pull requests

6 participants