Skip to content

Commit 06e3e63

Browse files
committed
flate: return CVec<u8> rather than copying into a new vector.
This trades an O(n) allocation + memcpy for a O(1) proc allocation (for the destructor). Most users only need &[u8] anyway (all of the users in the main repo), and so this offers large gains.
1 parent 768b96e commit 06e3e63

File tree

7 files changed

+40
-28
lines changed

7 files changed

+40
-28
lines changed

mk/crates.mk

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ DEPS_rustc := syntax native:rustllvm flate arena serialize sync getopts \
6565
collections time extra
6666
DEPS_rustdoc := rustc native:sundown serialize sync getopts collections \
6767
test time
68-
DEPS_flate := std native:miniz
68+
DEPS_flate := std extra native:miniz
6969
DEPS_arena := std collections
7070
DEPS_glob := std
7171
DEPS_serialize := std

src/libextra/c_vec.rs

+16
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@
3535
* if necessary.
3636
*/
3737

38+
use std::cast;
3839
use std::ptr;
40+
use std::raw;
3941

4042
/**
4143
* The type representing a foreign chunk of memory
@@ -111,6 +113,20 @@ impl <T> CVec<T> {
111113
}
112114
}
113115

116+
/// View the stored data as a slice.
117+
pub fn as_slice<'a>(&'a self) -> &'a [T] {
118+
unsafe {
119+
cast::transmute(raw::Slice { data: self.base as *T, len: self.len })
120+
}
121+
}
122+
123+
/// View the stored data as a mutable slice.
124+
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
125+
unsafe {
126+
cast::transmute(raw::Slice { data: self.base as *T, len: self.len })
127+
}
128+
}
129+
114130
/**
115131
* Retrieves an element at a given index
116132
*

src/libflate/lib.rs

+18-23
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ Simple compression
2020
#[license = "MIT/ASL2"];
2121
#[allow(missing_doc)];
2222

23+
extern crate extra;
2324
use std::libc::{c_void, size_t, c_int};
2425
use std::libc;
25-
use std::vec;
26+
use extra::c_vec::CVec;
2627

2728
pub mod rustrt {
2829
use std::libc::{c_int, c_void, size_t};
@@ -33,63 +34,57 @@ pub mod rustrt {
3334
src_buf_len: size_t,
3435
pout_len: *mut size_t,
3536
flags: c_int)
36-
-> *c_void;
37+
-> *mut c_void;
3738

3839
pub fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void,
3940
src_buf_len: size_t,
4041
pout_len: *mut size_t,
4142
flags: c_int)
42-
-> *c_void;
43+
-> *mut c_void;
4344
}
4445
}
4546

4647
static LZ_NORM : c_int = 0x80; // LZ with 128 probes, "normal"
4748
static TINFL_FLAG_PARSE_ZLIB_HEADER : c_int = 0x1; // parse zlib header and adler32 checksum
4849
static TDEFL_WRITE_ZLIB_HEADER : c_int = 0x01000; // write zlib header and adler32 checksum
4950

50-
fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> ~[u8] {
51+
fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> CVec<u8> {
5152
unsafe {
5253
let mut outsz : size_t = 0;
5354
let res = rustrt::tdefl_compress_mem_to_heap(bytes.as_ptr() as *c_void,
5455
bytes.len() as size_t,
5556
&mut outsz,
5657
flags);
57-
assert!(res as int != 0);
58-
let out = vec::raw::from_buf_raw(res as *u8,
59-
outsz as uint);
60-
libc::free(res as *mut c_void);
61-
out
58+
assert!(!res.is_null());
59+
CVec::new_with_dtor(res as *mut u8, outsz as uint, proc() libc::free(res))
6260
}
6361
}
6462

65-
pub fn deflate_bytes(bytes: &[u8]) -> ~[u8] {
63+
pub fn deflate_bytes(bytes: &[u8]) -> CVec<u8> {
6664
deflate_bytes_internal(bytes, LZ_NORM)
6765
}
6866

69-
pub fn deflate_bytes_zlib(bytes: &[u8]) -> ~[u8] {
67+
pub fn deflate_bytes_zlib(bytes: &[u8]) -> CVec<u8> {
7068
deflate_bytes_internal(bytes, LZ_NORM | TDEFL_WRITE_ZLIB_HEADER)
7169
}
7270

73-
fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> ~[u8] {
71+
fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> CVec<u8> {
7472
unsafe {
7573
let mut outsz : size_t = 0;
7674
let res = rustrt::tinfl_decompress_mem_to_heap(bytes.as_ptr() as *c_void,
7775
bytes.len() as size_t,
7876
&mut outsz,
7977
flags);
80-
assert!(res as int != 0);
81-
let out = vec::raw::from_buf_raw(res as *u8,
82-
outsz as uint);
83-
libc::free(res as *mut c_void);
84-
out
78+
assert!(!res.is_null());
79+
CVec::new_with_dtor(res as *mut u8, outsz as uint, proc() libc::free(res))
8580
}
8681
}
8782

88-
pub fn inflate_bytes(bytes: &[u8]) -> ~[u8] {
83+
pub fn inflate_bytes(bytes: &[u8]) -> CVec<u8> {
8984
inflate_bytes_internal(bytes, 0)
9085
}
9186

92-
pub fn inflate_bytes_zlib(bytes: &[u8]) -> ~[u8] {
87+
pub fn inflate_bytes_zlib(bytes: &[u8]) -> CVec<u8> {
9388
inflate_bytes_internal(bytes, TINFL_FLAG_PARSE_ZLIB_HEADER)
9489
}
9590

@@ -115,19 +110,19 @@ mod tests {
115110
debug!("de/inflate of {} bytes of random word-sequences",
116111
input.len());
117112
let cmp = deflate_bytes(input);
118-
let out = inflate_bytes(cmp);
113+
let out = inflate_bytes(cmp.as_slice());
119114
debug!("{} bytes deflated to {} ({:.1f}% size)",
120115
input.len(), cmp.len(),
121116
100.0 * ((cmp.len() as f64) / (input.len() as f64)));
122-
assert_eq!(input, out);
117+
assert_eq!(input.as_slice(), out.as_slice());
123118
}
124119
}
125120

126121
#[test]
127122
fn test_zlib_flate() {
128123
let bytes = ~[1, 2, 3, 4, 5];
129124
let deflated = deflate_bytes(bytes);
130-
let inflated = inflate_bytes(deflated);
131-
assert_eq!(inflated, bytes);
125+
let inflated = inflate_bytes(deflated.as_slice());
126+
assert_eq!(inflated.as_slice(), bytes.as_slice());
132127
}
133128
}

src/librustc/back/link.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ fn link_rlib(sess: Session,
944944
// into the archive.
945945
let bc = obj_filename.with_extension("bc");
946946
match fs::File::open(&bc).read_to_end().and_then(|data| {
947-
fs::File::create(&bc).write(flate::deflate_bytes(data))
947+
fs::File::create(&bc).write(flate::deflate_bytes(data).as_slice())
948948
}) {
949949
Ok(()) => {}
950950
Err(e) => {

src/librustc/back/lto.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ pub fn run(sess: session::Session, llmod: ModuleRef,
5858
let bc = bc.expect("missing bytecode in archive!");
5959
let bc = time(sess.time_passes(), format!("inflate {}.bc", name), (), |_|
6060
flate::inflate_bytes(bc));
61-
let ptr = bc.as_ptr();
61+
let ptr = bc.as_slice().as_ptr();
6262
debug!("linking {}", name);
6363
time(sess.time_passes(), format!("ll link {}", name), (), |()| unsafe {
6464
if !llvm::LLVMRustLinkInExternalBitcode(llmod,

src/librustc/metadata/cstore.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use metadata::loader;
1818

1919
use std::cell::RefCell;
2020
use collections::HashMap;
21+
use extra::c_vec::CVec;
2122
use syntax::ast;
2223
use syntax::parse::token::IdentInterner;
2324

@@ -28,7 +29,7 @@ use syntax::parse::token::IdentInterner;
2829
pub type cnum_map = @RefCell<HashMap<ast::CrateNum, ast::CrateNum>>;
2930

3031
pub enum MetadataBlob {
31-
MetadataVec(~[u8]),
32+
MetadataVec(CVec<u8>),
3233
MetadataArchive(loader::ArchiveMetadata),
3334
}
3435

src/librustc/middle/trans/base.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2569,7 +2569,7 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> ~[u8] {
25692569
let encode_parms = crate_ctxt_to_encode_parms(cx, encode_inlined_item);
25702570
let metadata = encoder::encode_metadata(encode_parms, krate);
25712571
let compressed = encoder::metadata_encoding_version +
2572-
flate::deflate_bytes(metadata);
2572+
flate::deflate_bytes(metadata).as_slice();
25732573
let llmeta = C_bytes(compressed);
25742574
let llconst = C_struct([llmeta], false);
25752575
let name = format!("rust_metadata_{}_{}_{}", cx.link_meta.crateid.name,

0 commit comments

Comments
 (0)