Optimize creation of buffered readers/writers#10424
Conversation
I was benchmarking rust-http recently, and I saw that 50% of its time was spent creating buffered readers/writers. Albeit rust-http wasn't using std::rt::io::buffered, but the same idea applies here. It's much cheaper to malloc a large region and not initialize it than to set it all to 0. Buffered readers/writers never use uninitialized data, and their internal buffers are encapsulated, so any usage of uninitialized slots are an implementation bug in the readers/writers.
|
I was wondering if this also applies in general to all reader's read method. Currently, Reader::read requires an initialized vector to be passed. Wouldn't it be better to pass an empty vector and read data up to its capacity? I did something similar in rust-fuse when reading commands from a fd that's connected to the kernel driver: channel.rs, method receive(). |
|
I agree that right now we don't really have a safe way of specifying "read into this unallocated data". It's tough because you can only set the length on an owned vector, and I would much rather have |
|
This is a common enough pattern that would be nice to have a function that gives you uninitialized u8s. There are security implications to handing out uninitialized buffers though so we'd probably want to talk over whether this is a 'safe' operation. |
|
One option that may be a bit safer is to provide a method that returns a zeroed vector instead of an uninitialized vector. I'm not sure how smart the |
|
@brson: our "behaviours considered unsafe" section includes "Reads of undef (uninitialized) memory", so presumably |
I was benchmarking rust-http recently, and I saw that 50% of its time was spent creating buffered readers/writers. Albeit rust-http wasn't using std::rt::io::buffered, but the same idea applies here. It's much cheaper to malloc a large region and not initialize it than to set it all to 0. Buffered readers/writers never use uninitialized data, and their internal buffers are encapsulated, so any usage of uninitialized slots are an implementation bug in the readers/writers.
|
@sfackler, sadly at least on OSX calloc is not nearly as fast as malloc. In a small |
|
Bummer. I wonder if jemalloc does any better. Are there any plans to switch back to that? |
|
We don't have any concrete plans, but I also don't think that we'd turn it down at all. It would be nice to have some numbers to back the change, however. |
|
Based off of some quick checks, it looks like |
|
Interesting! That's not a bad reason to start looking into jemalloc again. |
#10424 did optimizations without adding a way to measure their effect and ensure no regressions. This fixes that.
…shearth manual_let_else: support struct patterns This adds upon the improvements of rust-lang#10797 and: * Only prints `()` around `Or` patterns at the top level (fixing a regression of rust-lang#10797) * Supports multi-binding patterns: `let (u, v) = if let (Some(u_i), Ok(v_i)) = ex { (u_i, v_i) } else ...` * Traverses through tuple patterns: `let v = if let (Some(v), None) = ex { v } else ...` * Supports struct patterns: `let v = if let S { v, w, } = ex { (v, w) } else ...` ``` changelog: [`manual_let_else`]: improve pattern printing to support struct patterns ``` fixes rust-lang#10708 fixes rust-lang#10424
I was benchmarking rust-http recently, and I saw that 50% of its time was spent
creating buffered readers/writers. Albeit rust-http wasn't using
std::rt::io::buffered, but the same idea applies here. It's much cheaper to
malloc a large region and not initialize it than to set it all to 0. Buffered
readers/writers never use uninitialized data, and their internal buffers are
encapsulated, so any usage of uninitialized slots are an implementation bug in
the readers/writers.