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

Reduce allocations in the Task structure #11389

Closed
brson opened this issue Jan 8, 2014 · 2 comments
Closed

Reduce allocations in the Task structure #11389

brson opened this issue Jan 8, 2014 · 2 comments
Labels
A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows E-hard Call for participation: Hard difficulty. Experience needed to fix: A lot. I-slow Issue: Problems and improvements with respect to performance of generated code.

Comments

@brson
Copy link
Contributor

brson commented Jan 8, 2014

Spawning a green Task right now incurs untold numbers of allocations. It would be super nice to reduce this to ~1 allocation. Doing so will require a lot of trickery.

alexcrichton added a commit to alexcrichton/rust that referenced this issue Feb 14, 2014
The condition was the wrong direction and it also didn't take equality into
account. Tests were added for both cases.

For the small benchmark of `task::try(proc() {}).unwrap()`, this takes the
iteration time on OSX from 15119 ns/iter to 6179 ns/iter (timed with
RUST_THREADS=1)

cc rust-lang#11389
alexcrichton added a commit to alexcrichton/rust that referenced this issue Feb 14, 2014
One of these is allocated for every task, trying to cut down on allocations

cc rust-lang#11389
alexcrichton added a commit to alexcrichton/rust that referenced this issue Feb 14, 2014
Instead, use an enum to allow running both a procedure and sending the task
result over a channel. I expect the common case to be sending on a channel (e.g.
task::try), so don't require an extra allocation in the common case.

cc rust-lang#11389
alexcrichton added a commit to alexcrichton/rust that referenced this issue Feb 14, 2014
Two unfortunate allocations were wrapping a proc() in a proc() with
GreenTask::build_start_wrapper, and then boxing this proc in a ~proc() inside of
Context::new(). Both of these allocations were a direct result from two
conditions:

1. The Context::new() function has a nice api of taking a procedure argument to
   start up a new context with. This inherently required an allocation by
   build_start_wrapper because extra code needed to be run around the edges of a
   user-provided proc() for a new task.

2. The initial bootstrap code only understood how to pass one argument to the
   next function. By modifying the assembly and entry points to understand more
   than one argument, more information is passed through in registers instead of
   allocating a pointer-sized context.

This is sadly where I end up throwing mips under a bus because I have no idea
what's going on in the mips context switching code and don't know how to modify
it.

Closes rust-lang#7767
cc rust-lang#11389
@emberian
Copy link
Member

So, today we get:

[19:01:11]/tmp> ltrace -e malloc+free ./foo 
foo->malloc(784)                                                                                  = 0x21f0010
foo->malloc(96)                                                                                   = 0x21f03c0
foo->malloc(96)                                                                                   = 0x21f0430
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x21f05d0
foo->malloc(96)                                                                                   = 0x21f0980
foo->malloc(96)                                                                                   = 0x21f09f0
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x21f0b90
foo->malloc(96)                                                                                   = 0x21f0fc0
foo->malloc(96)                                                                                   = 0x21f1030
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x21f11d0
foo->malloc(96)                                                                                   = 0x21f1600
foo->malloc(96)                                                                                   = 0x21f1670
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x21f1810
foo->malloc(96)                                                                                   = 0x21f1c40
foo->malloc(96)                                                                                   = 0x21f1cb0
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x21f1e50
foo->malloc(96)                                                                                   = 0x21f2280
foo->malloc(96)                                                                                   = 0x21f22f0
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x21f2490
foo->malloc(96)                                                                                   = 0x21f29c0
foo->malloc(96)                                                                                   = 0x21f2a30
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x21f2bd0
foo->malloc(96)                                                                                   = 0x21f3100
foo->malloc(96)                                                                                   = 0x21f3170
libpthread.so.0->free(0)                                                                          = <void>
hello world
+++ exited (status 0) +++

from:

#![feature(phase)]

#[phase(plugin)]
extern crate green;

green_start!(main)

fn main() {
    std::task::spawn(proc() {
        println!("hello world");
    });
}

and with another hello world task:

foo->malloc(784)                                                                                  = 0x1100010
foo->malloc(96)                                                                                   = 0x11003c0
foo->malloc(96)                                                                                   = 0x1100430
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x11005d0
foo->malloc(96)                                                                                   = 0x1100980
foo->malloc(96)                                                                                   = 0x11009f0
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x1100b90
foo->malloc(96)                                                                                   = 0x1100fc0
foo->malloc(96)                                                                                   = 0x1101030
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x11011d0
foo->malloc(96)                                                                                   = 0x1101600
foo->malloc(96)                                                                                   = 0x1101670
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x1101810
foo->malloc(96)                                                                                   = 0x1101c40
foo->malloc(96)                                                                                   = 0x1101cb0
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x1101e50
foo->malloc(96)                                                                                   = 0x1102280
foo->malloc(96)                                                                                   = 0x11022f0
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x1102490
foo->malloc(96)                                                                                   = 0x11029c0
foo->malloc(96)                                                                                   = 0x1102a30
libpthread.so.0->free(0)                                                                          = <void>
foo->malloc(784)                                                                                  = 0x1102bd0
foo->malloc(96)                                                                                   = 0x1103100
foo->malloc(96)                                                                                   = 0x1103170
libpthread.so.0->free(0)                                                                          = <void>
hello world
hello world
+++ exited (status 0) +++

For a difference of exactly 0 mallocs! Do you have a testcase, @brson?

@steveklabnik
Copy link
Member

Green threads are gone.

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 E-hard Call for participation: Hard difficulty. Experience needed to fix: A lot. I-slow Issue: Problems and improvements with respect to performance of generated code.
Projects
None yet
Development

No branches or pull requests

3 participants