]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #8356 : toddaaro/rust/ws, r=brson
authorbors <bors@rust-lang.org>
Thu, 8 Aug 2013 23:32:02 +0000 (16:32 -0700)
committerbors <bors@rust-lang.org>
Thu, 8 Aug 2013 23:32:02 +0000 (16:32 -0700)
This pull request converts the scheduler from a naive shared queue scheduler to a naive workstealing scheduler. The deque is still a queue inside a lock, but there is still a substantial performance gain. Fiddling with the messaging benchmark I got a ~10x speedup and observed massively reduced memory usage.

There are still *many* locations for optimization, but based on my experience so far it is a clear performance win as it is now.

1  2 
src/libstd/rt/comm.rs
src/libstd/rt/select.rs

diff --combined src/libstd/rt/comm.rs
index 6dc44dd1193b9e57532df2ca6a55029ec4e307c4,33b4b307af846b3c393105f78ea80c5d4ace1016..936a6526508a93f4c47cf5fdf2d69f4b15c4586f
@@@ -225,9 -225,10 +225,10 @@@ impl<T> Select for PortOne<T> 
      fn optimistic_check(&mut self) -> bool {
          // The optimistic check is never necessary for correctness. For testing
          // purposes, making it randomly return false simulates a racing sender.
-         use rand::{Rand, rng};
-         let mut rng = rng();
-         let actually_check = Rand::rand(&mut rng);
+         use rand::{Rand};
+         let actually_check = do Local::borrow::<Scheduler, bool> |sched| {
+             Rand::rand(&mut sched.rng)
+         };
          if actually_check {
              unsafe { (*self.packet()).state.load(Acquire) == STATE_ONE }
          } else {
@@@ -508,11 -509,7 +509,11 @@@ impl<T> Peekable<T> for Port<T> 
      }
  }
  
 -impl<T> Select for Port<T> {
 +// XXX: Kind of gross. A Port<T> should be selectable so you can make an array
 +// of them, but a &Port<T> should also be selectable so you can select2 on it
 +// alongside a PortOne<U> without passing the port by value in recv_ready.
 +
 +impl<'self, T> Select for &'self Port<T> {
      #[inline]
      fn optimistic_check(&mut self) -> bool {
          do self.next.with_mut_ref |pone| { pone.optimistic_check() }
      }
  }
  
 -impl<T> SelectPort<(T, Port<T>)> for Port<T> {
 -    fn recv_ready(self) -> Option<(T, Port<T>)> {
 +impl<T> Select for Port<T> {
 +    #[inline]
 +    fn optimistic_check(&mut self) -> bool {
 +        (&*self).optimistic_check()
 +    }
 +
 +    #[inline]
 +    fn block_on(&mut self, sched: &mut Scheduler, task: BlockedTask) -> bool {
 +        (&*self).block_on(sched, task)
 +    }
 +
 +    #[inline]
 +    fn unblock_from(&mut self) -> bool {
 +        (&*self).unblock_from()
 +    }
 +}
 +
 +impl<'self, T> SelectPort<T> for &'self Port<T> {
 +    fn recv_ready(self) -> Option<T> {
          match self.next.take().recv_ready() {
              Some(StreamPayload { val, next }) => {
                  self.next.put_back(next);
 -                Some((val, self))
 +                Some(val)
              }
              None => None
          }
diff --combined src/libstd/rt/select.rs
index 84ce36c3e6b5a36007f99ed280cf2b39a3b232a1,07f8ca77d9db4664115baea2cc6f137aad914747..0e8d26e9482bac99761e536d5a16da8c5867195c
@@@ -182,6 -182,7 +182,7 @@@ mod test 
      fn select_stream() {
          use util;
          use comm::GenericChan;
+         use iter::Times;
  
          // Sends 10 buffered packets, and uses select to retrieve them all.
          // Puts the port in a different spot in the vector each time.
                  // get it back out
                  util::swap(port.get_mut_ref(), &mut ports[index]);
                  // NB. Not recv(), because optimistic_check randomly fails.
 -                let (data, new_port) = port.take_unwrap().recv_ready().unwrap();
 -                assert!(data == 31337);
 -                port = Some(new_port);
 +                assert!(port.get_ref().recv_ready().unwrap() == 31337);
              }
          }
      }
  
          fn select_racing_senders_helper(killable: bool, send_on_chans: ~[uint]) {
              use rt::test::spawntask_random;
+             use iter::Times;
  
              do run_in_newsched_task {
                  // A bit of stress, since ordinarily this is just smoke and mirrors.