Skip to content

Commit f681420

Browse files
committed
auto merge of #15915 : erickt/rust/master, r=alexcrichton
std: rename MemWriter to SeekableMemWriter, add seekless MemWriter Not all users of MemWriter need to seek, but having MemWriter seekable adds between 3-29% in overhead in certain circumstances. This fixes that performance gap by making a non-seekable MemWriter, and creating a new SeekableMemWriter for those circumstances when that functionality is actually needed. ``` test io::mem::test::bench_buf_reader ... bench: 682 ns/iter (+/- 85) test io::mem::test::bench_buf_writer ... bench: 580 ns/iter (+/- 57) test io::mem::test::bench_mem_reader ... bench: 793 ns/iter (+/- 99) test io::mem::test::bench_mem_writer_001_0000 ... bench: 48 ns/iter (+/- 27) test io::mem::test::bench_mem_writer_001_0010 ... bench: 65 ns/iter (+/- 27) = 153 MB/s test io::mem::test::bench_mem_writer_001_0100 ... bench: 132 ns/iter (+/- 12) = 757 MB/s test io::mem::test::bench_mem_writer_001_1000 ... bench: 802 ns/iter (+/- 151) = 1246 MB/s test io::mem::test::bench_mem_writer_100_0000 ... bench: 481 ns/iter (+/- 28) test io::mem::test::bench_mem_writer_100_0010 ... bench: 1957 ns/iter (+/- 126) = 510 MB/s test io::mem::test::bench_mem_writer_100_0100 ... bench: 8222 ns/iter (+/- 434) = 1216 MB/s test io::mem::test::bench_mem_writer_100_1000 ... bench: 82496 ns/iter (+/- 11191) = 1212 MB/s test io::mem::test::bench_seekable_mem_writer_001_0000 ... bench: 48 ns/iter (+/- 2) test io::mem::test::bench_seekable_mem_writer_001_0010 ... bench: 64 ns/iter (+/- 2) = 156 MB/s test io::mem::test::bench_seekable_mem_writer_001_0100 ... bench: 129 ns/iter (+/- 7) = 775 MB/s test io::mem::test::bench_seekable_mem_writer_001_1000 ... bench: 801 ns/iter (+/- 159) = 1248 MB/s test io::mem::test::bench_seekable_mem_writer_100_0000 ... bench: 711 ns/iter (+/- 51) test io::mem::test::bench_seekable_mem_writer_100_0010 ... bench: 2532 ns/iter (+/- 227) = 394 MB/s test io::mem::test::bench_seekable_mem_writer_100_0100 ... bench: 8962 ns/iter (+/- 947) = 1115 MB/s test io::mem::test::bench_seekable_mem_writer_100_1000 ... bench: 85086 ns/iter (+/- 11555) = 1175 MB/s ```
2 parents 3ab170f + 2bcb4bd commit f681420

File tree

14 files changed

+531
-145
lines changed

14 files changed

+531
-145
lines changed

Diff for: src/libcollections/string.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ impl String {
688688
/// assert_eq!(s.shift_char(), Some('o'));
689689
/// assert_eq!(s.shift_char(), None);
690690
/// ```
691-
pub fn shift_char (&mut self) -> Option<char> {
691+
pub fn shift_char(&mut self) -> Option<char> {
692692
let len = self.len();
693693
if len == 0 {
694694
return None

Diff for: src/librustc/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ extern crate time;
4848
#[phase(plugin, link)] extern crate log;
4949
#[phase(plugin, link)] extern crate syntax;
5050

51+
#[cfg(test)]
52+
extern crate test;
53+
5154
mod diagnostics;
5255

5356
pub mod back {
@@ -129,6 +132,7 @@ pub mod util {
129132

130133
pub mod common;
131134
pub mod ppaux;
135+
pub mod io;
132136
pub mod nodemap;
133137
}
134138

Diff for: src/librustc/metadata/encoder.rs

+12-12
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ use middle::ty;
2626
use middle::typeck;
2727
use middle::stability;
2828
use middle;
29+
use util::io::SeekableMemWriter;
2930
use util::nodemap::{NodeMap, NodeSet};
3031

3132
use serialize::Encodable;
3233
use std::cell::RefCell;
3334
use std::gc::Gc;
3435
use std::hash::Hash;
3536
use std::hash;
36-
use std::io::MemWriter;
3737
use std::mem;
3838
use std::collections::HashMap;
3939
use syntax::abi;
@@ -61,7 +61,7 @@ pub enum InlinedItemRef<'a> {
6161
IIForeignRef(&'a ast::ForeignItem)
6262
}
6363

64-
pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
64+
pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
6565

6666
pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
6767
ebml_w: &mut Encoder,
@@ -1407,7 +1407,7 @@ fn encode_info_for_items(ecx: &EncodeContext,
14071407
// Path and definition ID indexing
14081408

14091409
fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1410-
write_fn: |&mut MemWriter, &T|) {
1410+
write_fn: |&mut SeekableMemWriter, &T|) {
14111411
let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
14121412
for elt in index.move_iter() {
14131413
let h = hash::hash(&elt.val) as uint;
@@ -1424,7 +1424,7 @@ fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
14241424
ebml_w.start_tag(tag_index_buckets_bucket_elt);
14251425
assert!(elt.pos < 0xffff_ffff);
14261426
{
1427-
let wr: &mut MemWriter = ebml_w.writer;
1427+
let wr: &mut SeekableMemWriter = ebml_w.writer;
14281428
wr.write_be_u32(elt.pos as u32);
14291429
}
14301430
write_fn(ebml_w.writer, &elt.val);
@@ -1436,15 +1436,15 @@ fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
14361436
ebml_w.start_tag(tag_index_table);
14371437
for pos in bucket_locs.iter() {
14381438
assert!(*pos < 0xffff_ffff);
1439-
let wr: &mut MemWriter = ebml_w.writer;
1439+
let wr: &mut SeekableMemWriter = ebml_w.writer;
14401440
wr.write_be_u32(*pos as u32);
14411441
}
14421442
ebml_w.end_tag();
14431443
ebml_w.end_tag();
14441444
}
14451445

1446-
fn write_i64(writer: &mut MemWriter, &n: &i64) {
1447-
let wr: &mut MemWriter = writer;
1446+
fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
1447+
let wr: &mut SeekableMemWriter = writer;
14481448
assert!(n < 0x7fff_ffff);
14491449
wr.write_be_u32(n as u32);
14501450
}
@@ -1545,14 +1545,14 @@ fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
15451545

15461546
ebml_w.start_tag(tag_lang_items_item_id);
15471547
{
1548-
let wr: &mut MemWriter = ebml_w.writer;
1548+
let wr: &mut SeekableMemWriter = ebml_w.writer;
15491549
wr.write_be_u32(i as u32);
15501550
}
15511551
ebml_w.end_tag(); // tag_lang_items_item_id
15521552

15531553
ebml_w.start_tag(tag_lang_items_item_node_id);
15541554
{
1555-
let wr: &mut MemWriter = ebml_w.writer;
1555+
let wr: &mut SeekableMemWriter = ebml_w.writer;
15561556
wr.write_be_u32(id.node as u32);
15571557
}
15581558
ebml_w.end_tag(); // tag_lang_items_item_node_id
@@ -1824,12 +1824,12 @@ pub static metadata_encoding_version : &'static [u8] =
18241824
0, 0, 0, 1 ];
18251825

18261826
pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1827-
let mut wr = MemWriter::new();
1827+
let mut wr = SeekableMemWriter::new();
18281828
encode_metadata_inner(&mut wr, parms, krate);
18291829
wr.unwrap().move_iter().collect()
18301830
}
18311831

1832-
fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1832+
fn encode_metadata_inner(wr: &mut SeekableMemWriter, parms: EncodeParams, krate: &Crate) {
18331833
struct Stats {
18341834
attr_bytes: u64,
18351835
dep_bytes: u64,
@@ -1982,7 +1982,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
19821982

19831983
// Get the encoded string for a type
19841984
pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
1985-
let mut wr = MemWriter::new();
1985+
let mut wr = SeekableMemWriter::new();
19861986
tyencode::enc_ty(&mut wr, &tyencode::ctxt {
19871987
diag: tcx.sess.diagnostic(),
19881988
ds: def_to_string,

Diff for: src/librustc/metadata/tyencode.rs

+23-22
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
use std::cell::RefCell;
1717
use std::collections::HashMap;
18-
use std::io::MemWriter;
1918

2019
use middle::subst;
2120
use middle::subst::VecPerParamSpace;
@@ -28,6 +27,8 @@ use syntax::ast::*;
2827
use syntax::diagnostic::SpanHandler;
2928
use syntax::parse::token;
3029

30+
use util::io::SeekableMemWriter;
31+
3132
macro_rules! mywrite( ($($arg:tt)*) => ({ write!($($arg)*); }) )
3233

3334
pub struct ctxt<'a> {
@@ -48,7 +49,7 @@ pub struct ty_abbrev {
4849

4950
pub type abbrev_map = RefCell<HashMap<ty::t, ty_abbrev>>;
5051

51-
pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
52+
pub fn enc_ty(w: &mut SeekableMemWriter, cx: &ctxt, t: ty::t) {
5253
match cx.abbrevs.borrow_mut().find(&t) {
5354
Some(a) => { w.write(a.s.as_bytes()); return; }
5455
None => {}
@@ -72,19 +73,19 @@ pub fn enc_ty(w: &mut MemWriter, cx: &ctxt, t: ty::t) {
7273
}
7374
}
7475

75-
fn enc_mutability(w: &mut MemWriter, mt: ast::Mutability) {
76+
fn enc_mutability(w: &mut SeekableMemWriter, mt: ast::Mutability) {
7677
match mt {
7778
MutImmutable => (),
7879
MutMutable => mywrite!(w, "m"),
7980
}
8081
}
8182

82-
fn enc_mt(w: &mut MemWriter, cx: &ctxt, mt: ty::mt) {
83+
fn enc_mt(w: &mut SeekableMemWriter, cx: &ctxt, mt: ty::mt) {
8384
enc_mutability(w, mt.mutbl);
8485
enc_ty(w, cx, mt.ty);
8586
}
8687

87-
fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
88+
fn enc_opt<T>(w: &mut SeekableMemWriter, t: Option<T>, enc_f: |&mut SeekableMemWriter, T|) {
8889
match t {
8990
None => mywrite!(w, "n"),
9091
Some(v) => {
@@ -94,10 +95,10 @@ fn enc_opt<T>(w: &mut MemWriter, t: Option<T>, enc_f: |&mut MemWriter, T|) {
9495
}
9596
}
9697

97-
fn enc_vec_per_param_space<T>(w: &mut MemWriter,
98+
fn enc_vec_per_param_space<T>(w: &mut SeekableMemWriter,
9899
cx: &ctxt,
99100
v: &VecPerParamSpace<T>,
100-
op: |&mut MemWriter, &ctxt, &T|) {
101+
op: |&mut SeekableMemWriter, &ctxt, &T|) {
101102
for &space in subst::ParamSpace::all().iter() {
102103
mywrite!(w, "[");
103104
for t in v.get_slice(space).iter() {
@@ -107,13 +108,13 @@ fn enc_vec_per_param_space<T>(w: &mut MemWriter,
107108
}
108109
}
109110

110-
pub fn enc_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::Substs) {
111+
pub fn enc_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::Substs) {
111112
enc_region_substs(w, cx, &substs.regions);
112113
enc_vec_per_param_space(w, cx, &substs.types,
113114
|w, cx, &ty| enc_ty(w, cx, ty));
114115
}
115116

116-
fn enc_region_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::RegionSubsts) {
117+
fn enc_region_substs(w: &mut SeekableMemWriter, cx: &ctxt, substs: &subst::RegionSubsts) {
117118
match *substs {
118119
subst::ErasedRegions => {
119120
mywrite!(w, "e");
@@ -126,7 +127,7 @@ fn enc_region_substs(w: &mut MemWriter, cx: &ctxt, substs: &subst::RegionSubsts)
126127
}
127128
}
128129

129-
fn enc_region(w: &mut MemWriter, cx: &ctxt, r: ty::Region) {
130+
fn enc_region(w: &mut SeekableMemWriter, cx: &ctxt, r: ty::Region) {
130131
match r {
131132
ty::ReLateBound(id, br) => {
132133
mywrite!(w, "b[{}|", id);
@@ -161,7 +162,7 @@ fn enc_region(w: &mut MemWriter, cx: &ctxt, r: ty::Region) {
161162
}
162163
}
163164

164-
fn enc_bound_region(w: &mut MemWriter, cx: &ctxt, br: ty::BoundRegion) {
165+
fn enc_bound_region(w: &mut SeekableMemWriter, cx: &ctxt, br: ty::BoundRegion) {
165166
match br {
166167
ty::BrAnon(idx) => {
167168
mywrite!(w, "a{}|", idx);
@@ -177,12 +178,12 @@ fn enc_bound_region(w: &mut MemWriter, cx: &ctxt, br: ty::BoundRegion) {
177178
}
178179
}
179180

180-
pub fn enc_trait_ref(w: &mut MemWriter, cx: &ctxt, s: &ty::TraitRef) {
181+
pub fn enc_trait_ref(w: &mut SeekableMemWriter, cx: &ctxt, s: &ty::TraitRef) {
181182
mywrite!(w, "{}|", (cx.ds)(s.def_id));
182183
enc_substs(w, cx, &s.substs);
183184
}
184185

185-
pub fn enc_trait_store(w: &mut MemWriter, cx: &ctxt, s: ty::TraitStore) {
186+
pub fn enc_trait_store(w: &mut SeekableMemWriter, cx: &ctxt, s: ty::TraitStore) {
186187
match s {
187188
ty::UniqTraitStore => mywrite!(w, "~"),
188189
ty::RegionTraitStore(re, m) => {
@@ -193,7 +194,7 @@ pub fn enc_trait_store(w: &mut MemWriter, cx: &ctxt, s: ty::TraitStore) {
193194
}
194195
}
195196

196-
fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
197+
fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
197198
match *st {
198199
ty::ty_nil => mywrite!(w, "n"),
199200
ty::ty_bot => mywrite!(w, "z"),
@@ -293,33 +294,33 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
293294
}
294295
}
295296

296-
fn enc_fn_style(w: &mut MemWriter, p: FnStyle) {
297+
fn enc_fn_style(w: &mut SeekableMemWriter, p: FnStyle) {
297298
match p {
298299
NormalFn => mywrite!(w, "n"),
299300
UnsafeFn => mywrite!(w, "u"),
300301
}
301302
}
302303

303-
fn enc_abi(w: &mut MemWriter, abi: Abi) {
304+
fn enc_abi(w: &mut SeekableMemWriter, abi: Abi) {
304305
mywrite!(w, "[");
305306
mywrite!(w, "{}", abi.name());
306307
mywrite!(w, "]")
307308
}
308309

309-
fn enc_onceness(w: &mut MemWriter, o: Onceness) {
310+
fn enc_onceness(w: &mut SeekableMemWriter, o: Onceness) {
310311
match o {
311312
Once => mywrite!(w, "o"),
312313
Many => mywrite!(w, "m")
313314
}
314315
}
315316

316-
pub fn enc_bare_fn_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::BareFnTy) {
317+
pub fn enc_bare_fn_ty(w: &mut SeekableMemWriter, cx: &ctxt, ft: &ty::BareFnTy) {
317318
enc_fn_style(w, ft.fn_style);
318319
enc_abi(w, ft.abi);
319320
enc_fn_sig(w, cx, &ft.sig);
320321
}
321322

322-
pub fn enc_closure_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
323+
pub fn enc_closure_ty(w: &mut SeekableMemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
323324
enc_fn_style(w, ft.fn_style);
324325
enc_onceness(w, ft.onceness);
325326
enc_trait_store(w, cx, ft.store);
@@ -330,7 +331,7 @@ pub fn enc_closure_ty(w: &mut MemWriter, cx: &ctxt, ft: &ty::ClosureTy) {
330331
enc_abi(w, ft.abi);
331332
}
332333

333-
fn enc_fn_sig(w: &mut MemWriter, cx: &ctxt, fsig: &ty::FnSig) {
334+
fn enc_fn_sig(w: &mut SeekableMemWriter, cx: &ctxt, fsig: &ty::FnSig) {
334335
mywrite!(w, "[{}|", fsig.binder_id);
335336
for ty in fsig.inputs.iter() {
336337
enc_ty(w, cx, *ty);
@@ -344,7 +345,7 @@ fn enc_fn_sig(w: &mut MemWriter, cx: &ctxt, fsig: &ty::FnSig) {
344345
enc_ty(w, cx, fsig.output);
345346
}
346347

347-
fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
348+
fn enc_bounds(w: &mut SeekableMemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
348349
for bound in bs.builtin_bounds.iter() {
349350
match bound {
350351
ty::BoundSend => mywrite!(w, "S"),
@@ -363,7 +364,7 @@ fn enc_bounds(w: &mut MemWriter, cx: &ctxt, bs: &ty::ParamBounds) {
363364
mywrite!(w, ".");
364365
}
365366

366-
pub fn enc_type_param_def(w: &mut MemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
367+
pub fn enc_type_param_def(w: &mut SeekableMemWriter, cx: &ctxt, v: &ty::TypeParameterDef) {
367368
mywrite!(w, "{}:{}|{}|{}|",
368369
token::get_ident(v.ident), (cx.ds)(v.def_id),
369370
v.space.to_uint(), v.index);

Diff for: src/librustc/middle/astencode.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use middle::subst;
2828
use middle::subst::VecPerParamSpace;
2929
use middle::typeck::{MethodCall, MethodCallee, MethodOrigin};
3030
use middle::{ty, typeck};
31+
use util::io::SeekableMemWriter;
3132
use util::ppaux::ty_to_string;
3233

3334
use syntax::{ast, ast_map, ast_util, codemap, fold};
@@ -39,7 +40,6 @@ use syntax;
3940

4041
use libc;
4142
use std::io::Seek;
42-
use std::io::MemWriter;
4343
use std::mem;
4444
use std::gc::GC;
4545

@@ -73,7 +73,7 @@ trait tr_intern {
7373
fn tr_intern(&self, xcx: &ExtendedDecodeContext) -> ast::DefId;
7474
}
7575

76-
pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
76+
pub type Encoder<'a> = writer::Encoder<'a, SeekableMemWriter>;
7777

7878
// ______________________________________________________________________
7979
// Top-level methods.
@@ -1573,10 +1573,8 @@ fn mk_ctxt() -> parse::ParseSess {
15731573

15741574
#[cfg(test)]
15751575
fn roundtrip(in_item: Option<Gc<ast::Item>>) {
1576-
use std::io::MemWriter;
1577-
15781576
let in_item = in_item.unwrap();
1579-
let mut wr = MemWriter::new();
1577+
let mut wr = SeekableMemWriter::new();
15801578
{
15811579
let mut ebml_w = writer::Encoder::new(&mut wr);
15821580
encode_item_ast(&mut ebml_w, in_item);

0 commit comments

Comments
 (0)