about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-12-17 16:45:13 -0800
committerBrian Anderson <banderson@mozilla.com>2011-12-20 20:15:09 -0800
commitaeadc6269ef76f4425a49d892ceac7ea311ef5c1 (patch)
treee62356f817552b6430f43b6c72964325791418d1
parent128621be97d425a1d19e6640c8aee4fb6fca430b (diff)
downloadrust-aeadc6269ef76f4425a49d892ceac7ea311ef5c1.tar.gz
rust-aeadc6269ef76f4425a49d892ceac7ea311ef5c1.zip
wip
-rw-r--r--src/libcore/core.rs14
-rw-r--r--src/rt/circular_buffer.h2
-rw-r--r--src/rt/rust_task.cpp12
-rw-r--r--src/rt/rust_task.h1
-rw-r--r--src/test/bench/task-perf-one-million.rs60
5 files changed, 88 insertions, 1 deletions
diff --git a/src/libcore/core.rs b/src/libcore/core.rs
index 48e7a5f64ca..22f5dda00d8 100644
--- a/src/libcore/core.rs
+++ b/src/libcore/core.rs
@@ -6,6 +6,7 @@
 import option::{some,  none};
 import option = option::t;
 export option, some, none;
+export repeat;
 
 // Export the log levels as global constants. Higher levels mean
 // more-verbosity. Error is the bottom level, default logging level is
@@ -15,3 +16,16 @@ const error : int = 0;
 const warn : int = 1;
 const info : int = 2;
 const debug : int = 3;
+
+/*
+Function: repeat
+
+Execute a function for a set number of times
+*/
+fn repeat(times: uint, f: block()) {
+    let i = 0u;
+    while i < times {
+        f();
+        i += 1u;
+    }
+}
diff --git a/src/rt/circular_buffer.h b/src/rt/circular_buffer.h
index f06e700b2f8..ae08c0c6074 100644
--- a/src/rt/circular_buffer.h
+++ b/src/rt/circular_buffer.h
@@ -7,7 +7,7 @@
 
 class
 circular_buffer : public kernel_owned<circular_buffer> {
-    static const size_t INITIAL_CIRCULAR_BUFFER_SIZE_IN_UNITS = 8;
+    static const size_t INITIAL_CIRCULAR_BUFFER_SIZE_IN_UNITS = 1;
     static const size_t MAX_CIRCULAR_BUFFER_SIZE = 1 << 24;
 
 public:
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index 2e6c41a8e79..89570782942 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -404,6 +404,9 @@ rust_task::yield(size_t time_in_us, bool *killed) {
         *killed = true;
     }
 
+    // We're not going to need any extra stack for a while
+    clear_stack_cache();
+
     yield_timer.reset_us(time_in_us);
 
     // Return to the scheduler.
@@ -747,6 +750,15 @@ rust_task::del_stack() {
 }
 
 void
+rust_task::clear_stack_cache() {
+    A(sched, stk != NULL, "Expected to have a stack");
+    if (stk->prev != NULL) {
+        free_stk(this, stk->prev);
+        stk->prev = NULL;
+    }
+}
+
+void
 rust_task::record_stack_limit() {
     // The function prolog compares the amount of stack needed to the end of
     // the stack. As an optimization, when the frame size is less than 256
diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h
index 21d20691ac6..ba116c5a7bc 100644
--- a/src/rt/rust_task.h
+++ b/src/rt/rust_task.h
@@ -203,6 +203,7 @@ rust_task : public kernel_owned<rust_task>, rust_cond
     void reset_stack_limit();
     bool on_rust_stack();
     void check_stack_canary();
+    void clear_stack_cache();
 };
 
 //
diff --git a/src/test/bench/task-perf-one-million.rs b/src/test/bench/task-perf-one-million.rs
new file mode 100644
index 00000000000..8430351b7e9
--- /dev/null
+++ b/src/test/bench/task-perf-one-million.rs
@@ -0,0 +1,60 @@
+// xfail-test FIXME: Can't run under valgrind - too much RAM
+// FIXME: This doesn't spawn close to a million tasks yet
+
+tag msg {
+    ready(comm::chan<msg>);
+    start;
+    done(int);
+}
+
+fn calc(&&args: (int, comm::chan<msg>)) {
+    let (depth, parent_ch) = args;
+    let port = comm::port();
+    let children = depth > 0 ? 20u : 0u;
+    let child_chs = [];
+    let sum = 0;
+
+    repeat (children) {||
+        task::spawn((depth - 1, comm::chan(port)), calc);
+    }
+
+    repeat (children) {||
+        alt comm::recv(port) {
+          ready(child_ch) {
+            child_chs += [child_ch];
+          }
+        }
+    }
+
+    comm::send(parent_ch, ready(comm::chan(port)));
+
+    alt comm::recv(port) {
+        start. {
+          vec::iter (child_chs) { |child_ch|
+              comm::send(child_ch, start);
+          }
+        }
+    }
+
+    repeat (children) {||
+        alt comm::recv(port) {
+          done(child_sum) { sum += child_sum; }
+        }
+    }
+
+    comm::send(parent_ch, done(sum + 1));
+}
+
+fn main() {
+    let port = comm::port();
+    task::spawn((3, comm::chan(port)), calc);
+    alt comm::recv(port) {
+      ready(chan) {
+        comm::send(chan, start);
+      }
+    }
+    let sum = alt comm::recv(port) {
+      done(sum) { sum }
+    };
+    log #fmt("How many tasks? That's right, %d tasks.", sum);
+}
\ No newline at end of file