diff options
author | David LeGare <legare@google.com> | 2022-03-03 14:41:11 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-03-03 14:41:11 +0000 |
commit | 9ea4a788fd143e5b9234dab5a3b375f6210fb8a8 (patch) | |
tree | df29fa23f8ecd8a1b65de854c4e2907ee3fb5fc7 | |
parent | cfe4c678e3381d05752ca8f985d3713329984c3f (diff) | |
parent | 63072d7e13e328352dd61cfdf9facf3c4bb3ff84 (diff) | |
download | tinyvec-9ea4a788fd143e5b9234dab5a3b375f6210fb8a8.tar.gz |
Update tinyvec to 1.5.1 am: 38f28c3b88 am: 1fb6683fdb am: 63072d7e13
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/tinyvec/+/2005056
Change-Id: Icf038a5b04451ce5da32f5fde54dc9030d4ee5e0
-rw-r--r-- | .cargo_vcs_info.json | 7 | ||||
-rw-r--r-- | .github/workflows/rust.yml | 10 | ||||
-rw-r--r-- | Android.bp | 40 | ||||
-rw-r--r-- | CHANGELOG.md | 11 | ||||
-rw-r--r-- | Cargo.toml | 21 | ||||
-rw-r--r-- | Cargo.toml.orig | 55 | ||||
-rw-r--r-- | METADATA | 10 | ||||
-rw-r--r-- | benches/smallvec.rs | 500 | ||||
-rw-r--r-- | compare_benchmarks.py | 30 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/tinyvec.rs | 19 | ||||
-rw-r--r-- | tests/tinyvec.rs | 15 |
12 files changed, 656 insertions, 64 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 3d0fa1e..6772581 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,6 @@ { "git": { - "sha1": "7518868e4b9c802b214ce393f79f82fa13bef251" - } -} + "sha1": "1ef53f632b9cb6f2e7ff603586f4472317b9a25c" + }, + "path_in_vcs": "" +}
\ No newline at end of file diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 16bf072..050e70d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -11,6 +11,7 @@ jobs: matrix:
rust:
- 1.34.0
+ - 1.36.0
- stable
- beta
- nightly
@@ -25,10 +26,17 @@ jobs: uses: actions-rs/cargo@v1
with:
command: build
- - name: Test on Stable/Beta
+ - name: Build the crate on 1.36 with features.
if: matrix.rust != '1.34.0'
uses: actions-rs/cargo@v1
with:
+ command: build
+ # Using `extern crate alloc` is only possible after 1.36
+ args: --features=alloc,std,grab_spare_slice
+ - name: Test on Stable/Beta
+ if: matrix.rust != '1.34.0' && matrix.rust != '1.36.0'
+ uses: actions-rs/cargo@v1
+ with:
command: test
args: --features=alloc --features=grab_spare_slice --features=rustc_1_40
- name: Test on Nightly with All Features
@@ -44,7 +44,7 @@ rust_library { host_supported: true, crate_name: "tinyvec", cargo_env_compat: true, - cargo_pkg_version: "1.4.0", + cargo_pkg_version: "1.5.1", srcs: ["src/lib.rs"], edition: "2018", features: [ @@ -62,47 +62,29 @@ rust_library { min_sdk_version: "29", } -rust_defaults { - name: "tinyvec_test_defaults", - crate_name: "tinyvec", +rust_test { + name: "tinyvec_test_tests_arrayvec", + host_supported: true, + crate_name: "arrayvec", cargo_env_compat: true, - cargo_pkg_version: "1.4.0", + cargo_pkg_version: "1.5.1", + srcs: ["tests/arrayvec.rs"], test_suites: ["general-tests"], auto_gen_config: true, + test_options: { + unit_test: true, + }, edition: "2018", features: [ "alloc", "default", "tinyvec_macros", ], - flags: [ - "-C debug-assertions=on", - "-C opt-level=3", - ], rustlibs: [ "libcriterion", "libserde_test", + "libsmallvec", "libtinyvec", "libtinyvec_macros", ], } - -rust_test { - name: "tinyvec_test_tests_arrayvec", - defaults: ["tinyvec_test_defaults"], - host_supported: true, - srcs: ["tests/arrayvec.rs"], - test_options: { - unit_test: true, - }, -} - -rust_test { - name: "tinyvec_test_tests_tinyvec", - defaults: ["tinyvec_test_defaults"], - host_supported: true, - srcs: ["tests/tinyvec.rs"], - test_options: { - unit_test: true, - }, -} diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bcc2a1..93ef808 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog
+## 1.5.1
+
+* [madsmtm](https://github.com/madsmtm) fixed an error with the `alloc` feature on very old rustc versions.
+ [pr 154](https://github.com/Lokathor/tinyvec/pull/154)
+
+## 1.5.0
+
+* [eeeebbbbrrrr](https://github.com/eeeebbbbrrrr) added an impl for [std::io::Write](https://doc.rust-lang.org/std/io/trait.Write.html) to `TinyVec` when the element type is `u8`.
+ This is gated behind the new `std` feature.
+ [pr 152](https://github.com/Lokathor/tinyvec/pull/152)
+
## 1.4.0
* [saethlin](https://github.com/saethlin) stabilized the usage of const generics and array map with the `rustc_1_55` feature.
@@ -12,7 +12,7 @@ [package] edition = "2018" name = "tinyvec" -version = "1.4.0" +version = "1.5.1" authors = ["Lokathor <zefria@gmail.com>"] description = "`tinyvec` provides 100% safe vec-like data structures." keywords = ["vec", "no_std", "no-std"] @@ -20,22 +20,30 @@ categories = ["data-structures", "no-std"] license = "Zlib OR Apache-2.0 OR MIT" repository = "https://github.com/Lokathor/tinyvec" [package.metadata.docs.rs] -features = ["alloc", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"] +features = ["alloc", "std", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"] rustdoc-args = ["--cfg", "docs_rs"] [package.metadata.playground] -features = ["alloc", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"] +features = ["alloc", "std", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"] +[profile.bench] +debug = 2 + [profile.test] opt-level = 3 [[test]] name = "tinyvec" -required-features = ["alloc"] +required-features = ["alloc", "std"] [[bench]] name = "macros" harness = false required-features = ["alloc"] + +[[bench]] +name = "smallvec" +harness = false +required-features = ["alloc", "real_blackbox"] [dependencies.arbitrary] version = "1" optional = true @@ -54,11 +62,16 @@ version = "0.3.0" [dev-dependencies.serde_test] version = "1.0" +[dev-dependencies.smallvec] +version = "1" + [features] alloc = ["tinyvec_macros"] default = [] experimental_write_impl = [] grab_spare_slice = [] nightly_slice_partition_dedup = [] +real_blackbox = ["criterion/real_blackbox"] rustc_1_40 = [] rustc_1_55 = ["rustc_1_40"] +std = [] diff --git a/Cargo.toml.orig b/Cargo.toml.orig index a262ed1..28a5874 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,73 +1,90 @@ [package] name = "tinyvec" description = "`tinyvec` provides 100% safe vec-like data structures." -version = "1.4.0" +version = "1.5.1" authors = ["Lokathor <zefria@gmail.com>"] edition = "2018" license = "Zlib OR Apache-2.0 OR MIT" keywords = ["vec", "no_std", "no-std"] categories = ["data-structures", "no-std"] repository = "https://github.com/Lokathor/tinyvec" -
+ [dependencies] tinyvec_macros = { version = "0.1", optional = true } # Provides `Serialize` and `Deserialize` implementations serde = { version = "1.0", optional = true, default-features = false } # Provides derived `Arbitrary` implementations arbitrary = { version = "1", optional = true } -
+ [features] default = [] -
+ # Provide things that utilize the `alloc` crate, namely `TinyVec`. alloc = ["tinyvec_macros"] -
+ +# Provide things that require Rust's `std` module +std = [] + # (not part of Vec!) Extra methods to let you grab the slice of memory after the # "active" portion of an `ArrayVec` or `SliceVec`. grab_spare_slice = [] -
+ # features that require rustc 1.40 # use Vec::append if possible in TinyVec::append - 1.37 # DoubleEndedIterator::nth_back - 1.40 rustc_1_40 = [] -
+ # features that require rustc 1.55 # use const generics to implement Array for all array lengths rustc_1_55 = ["rustc_1_40"] -
+ # allow use of nightly feature `slice_partition_dedup`, # will become useless once that is stabilized: # https://github.com/rust-lang/rust/issues/54279 nightly_slice_partition_dedup = [] -
+ # EXPERIMENTAL: Not part of SemVer. It adds `core::fmt::Write` to `ArrayVec` # and `SliceVec`. It works on Stable Rust, but Vec normally supports the # `std::io::Write` trait instead of `core::fmt::Write`, so we're keeping it as # an experimental impl only for now. experimental_write_impl = [] -
+ +# Some benchmarks are optimized away with the stable black_box function +# which is based on read_volatile. This feature requires inline assembly +# and thus a nightly compiler, but is only used in benchmarks. +real_blackbox = ["criterion/real_blackbox"] + [package.metadata.docs.rs] -features = ["alloc", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"] +features = ["alloc", "std", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"] rustdoc-args = ["--cfg","docs_rs"] -
+ [package.metadata.playground] -features = ["alloc", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"] -
+features = ["alloc", "std", "grab_spare_slice", "rustc_1_40", "rustc_1_55", "serde"] + [profile.test] opt-level = 3 -
+ +[profile.bench] +debug = 2 + [workspace] members = ["fuzz"] -
+ [dev-dependencies] criterion = "0.3.0" serde_test = "1.0" -
+smallvec = "1" + [[test]] name = "tinyvec" -required-features = ["alloc"] -
+required-features = ["alloc", "std"] + [[bench]] name = "macros" harness = false required-features = ["alloc"] + +[[bench]] +name = "smallvec" +harness = false +required-features = ["alloc", "real_blackbox"] @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/tinyvec/tinyvec-1.4.0.crate" + value: "https://static.crates.io/crates/tinyvec/tinyvec-1.5.1.crate" } - version: "1.4.0" + version: "1.5.1" license_type: NOTICE last_upgrade_date { - year: 2021 - month: 9 - day: 22 + year: 2022 + month: 3 + day: 1 } } diff --git a/benches/smallvec.rs b/benches/smallvec.rs new file mode 100644 index 0000000..8cd16d3 --- /dev/null +++ b/benches/smallvec.rs @@ -0,0 +1,500 @@ +//! Benchmarks that compare TinyVec to SmallVec
+//!
+//! All the following commentary is based on the latest nightly at the time:
+//! rustc 1.55.0 (c8dfcfe04 2021-09-06).
+//!
+//! Some of these benchmarks are just a few instructions, so we put our own for loop inside
+//! the criterion::Bencher::iter call. This seems to improve the stability of measurements, and it
+//! has the wonderful side effect of making the emitted assembly easier to follow. Some of these
+//! benchmarks are totally inlined so that there are no calls at all in the hot path, so finding
+//! this for loop is an easy way to find your way around the emitted assembly.
+//!
+//! The clear method is cheaper to call for arrays of elements without a Drop impl, so wherever
+//! possible we reuse a single object in the benchmark loop, with a clear + black_box on each
+//! iteration in an attempt to not make that visible to the optimizer.
+//!
+//! We always call black_box(&v), instead of v = black_box(v) because the latter does a move of the
+//! inline array, which is linear in the size of the array and thus varies based on the array type
+//! being benchmarked, and this move can be more expensive than the function we're trying to
+//! benchmark.
+//!
+//! We also black_box the input to each method call. This has a significant effect on the assembly
+//! emitted, for example if we do not black_box the range we iterate over in the ::push benchmarks,
+//! the loop is unrolled. It's not entirely clear if it's better to black_box the iterator that
+//! yields the items being pushed, or to black_box at a deeper level: v.push(black_box(i)) for
+//! example. Anecdotally, it seems like the latter approach produces unreasonably bad assembly.
+//!
+
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
+use smallvec::SmallVec;
+use std::iter::FromIterator;
+use tinyvec::TinyVec;
+
+const ITERS: usize = 10_000;
+
+macro_rules! tinyvec_benches {
+ ($c:expr, $type:ty ; $len:expr) => {{
+ let mut g = $c.benchmark_group(concat!(
+ "TinyVec_",
+ stringify!($type),
+ "_",
+ stringify!($len)
+ ));
+
+ g.bench_function(
+ concat!(
+ "TinyVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::default"
+ ),
+ |b| {
+ b.iter(|| {
+ for _ in 0..ITERS {
+ let v: TinyVec<[$type; $len]> = TinyVec::default();
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "TinyVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::clone"
+ ),
+ |b| {
+ b.iter(|| {
+ let outer: TinyVec<[$type; $len]> =
+ black_box(TinyVec::from_iter(0..=($len as usize - 1) as _));
+ for _ in 0..ITERS {
+ let v = outer.clone();
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "TinyVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::clear"
+ ),
+ |b| {
+ b.iter(|| {
+ let mut v: TinyVec<[$type; $len]> = TinyVec::default();
+ for _ in 0..ITERS {
+ v.clear();
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "TinyVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::push"
+ ),
+ |b| {
+ b.iter(|| {
+ let mut v: TinyVec<[$type; $len]> = TinyVec::default();
+ for _ in 0..ITERS {
+ v.clear();
+ black_box(&v);
+ for i in black_box(0..=($len as usize - 1) as _) {
+ v.push(i);
+ }
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "TinyVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::from_iter"
+ ),
+ |b| {
+ b.iter(|| {
+ for _ in 0..ITERS {
+ let v: TinyVec<[$type; $len]> =
+ TinyVec::from_iter(black_box(0..=($len as usize - 1) as _));
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "TinyVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::from_slice"
+ ),
+ |b| {
+ b.iter(|| {
+ let data: &[$type] = &[0, 1, 2, 3, 4, 5, 6, 7];
+ for _ in 0..ITERS {
+ let v: TinyVec<[$type; $len]> = TinyVec::from(black_box(data));
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "TinyVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::extend"
+ ),
+ |b| {
+ b.iter(|| {
+ let mut v: TinyVec<[$type; $len]> = black_box(TinyVec::default());
+ for _ in 0..ITERS {
+ v.clear();
+ black_box(&v);
+ v.extend(black_box(0..=($len as usize - 1) as _));
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "TinyVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::extend_from_slice"
+ ),
+ |b| {
+ b.iter(|| {
+ let data: &[$type] = black_box(&[0, 1, 2, 3, 4, 5, 6, 7]);
+ let mut v: TinyVec<[$type; $len]> = black_box(TinyVec::default());
+ for _ in 0..ITERS {
+ v.clear();
+ black_box(&v);
+ v.extend_from_slice(data);
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "TinyVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::insert"
+ ),
+ |b| {
+ b.iter(|| {
+ let mut v: TinyVec<[$type; $len]> = TinyVec::default();
+ for _ in 0..ITERS {
+ v.clear();
+ black_box(&v);
+ for i in black_box(0..=($len as usize - 1) as _) {
+ v.insert(i as usize, i);
+ }
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "TinyVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::remove"
+ ),
+ |b| {
+ b.iter(|| {
+ let outer: TinyVec<[$type; $len]> =
+ black_box(TinyVec::from_iter(0..=($len as usize - 1) as _));
+ for _ in 0..ITERS {
+ let mut v = outer.clone();
+ for i in black_box((0..=($len as usize - 1) as _).rev()) {
+ v.remove(i);
+ }
+ black_box(&v);
+ }
+ });
+ },
+ );
+ }};
+}
+
+fn tinyvec_benches(c: &mut Criterion) {
+ tinyvec_benches!(c, u8; 8);
+ tinyvec_benches!(c, u8; 16);
+ tinyvec_benches!(c, u8; 32);
+ tinyvec_benches!(c, u8; 64);
+ tinyvec_benches!(c, u8; 128);
+ tinyvec_benches!(c, u8; 256);
+ tinyvec_benches!(c, u64; 2);
+ tinyvec_benches!(c, u64; 4);
+ tinyvec_benches!(c, u64; 8);
+ tinyvec_benches!(c, u64; 16);
+ tinyvec_benches!(c, u64; 32);
+}
+
+macro_rules! smallvec_benches {
+ ($c:expr, $type:ty ; $len:expr) => {{
+ let mut g = $c.benchmark_group(concat!(
+ "SmallVec_",
+ stringify!($type),
+ "_",
+ stringify!($len)
+ ));
+
+ g.bench_function(
+ concat!(
+ "SmallVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::default"
+ ),
+ |b| {
+ b.iter(|| {
+ for _ in 0..ITERS {
+ let v: SmallVec<[$type; $len]> = SmallVec::default();
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "SmallVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::clone"
+ ),
+ |b| {
+ b.iter(|| {
+ let outer: SmallVec<[$type; $len]> =
+ black_box(SmallVec::from_iter(0..=($len as usize - 1) as _));
+ for _ in 0..ITERS {
+ let v = outer.clone();
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "SmallVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::clear"
+ ),
+ |b| {
+ b.iter(|| {
+ let mut v: SmallVec<[$type; $len]> = SmallVec::default();
+ for _ in 0..ITERS {
+ v.clear();
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "SmallVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::push"
+ ),
+ |b| {
+ b.iter(|| {
+ let mut v: SmallVec<[$type; $len]> = SmallVec::default();
+ for _ in 0..ITERS {
+ v.clear();
+ black_box(&v);
+ for i in black_box(0..=($len as usize - 1) as _) {
+ v.push(i);
+ }
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "SmallVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::from_iter"
+ ),
+ |b| {
+ b.iter(|| {
+ for _ in 0..ITERS {
+ let v: SmallVec<[$type; $len]> =
+ SmallVec::from_iter(black_box(0..=($len as usize - 1) as _));
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "SmallVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::from_slice"
+ ),
+ |b| {
+ b.iter(|| {
+ let data: &[$type] = &[0, 1, 2, 3, 4, 5, 6, 7];
+ for _ in 0..ITERS {
+ let v: SmallVec<[$type; $len]> = SmallVec::from(black_box(data));
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "SmallVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::extend"
+ ),
+ |b| {
+ b.iter(|| {
+ let mut v: SmallVec<[$type; $len]> = black_box(SmallVec::default());
+ for _ in 0..ITERS {
+ v.clear();
+ black_box(&v);
+ v.extend(black_box(0..=($len as usize - 1) as _));
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "SmallVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::extend_from_slice"
+ ),
+ |b| {
+ b.iter(|| {
+ let data: &[$type] = black_box(&[0, 1, 2, 3, 4, 5, 6, 7]);
+ let mut v: SmallVec<[$type; $len]> = black_box(SmallVec::default());
+ for _ in 0..ITERS {
+ v.clear();
+ black_box(&v);
+ v.extend_from_slice(data);
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "SmallVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::insert"
+ ),
+ |b| {
+ b.iter(|| {
+ let mut v: SmallVec<[$type; $len]> = SmallVec::default();
+ for _ in 0..ITERS {
+ v.clear();
+ black_box(&v);
+ for i in black_box(0..=($len as usize - 1) as _) {
+ v.insert(i as usize, i);
+ }
+ black_box(&v);
+ }
+ });
+ },
+ );
+
+ g.bench_function(
+ concat!(
+ "SmallVec<[",
+ stringify!($type),
+ "; ",
+ stringify!($len),
+ "]>::remove"
+ ),
+ |b| {
+ b.iter(|| {
+ let outer: SmallVec<[$type; $len]> =
+ black_box(SmallVec::from_iter(0..=($len as usize - 1) as _));
+ for _ in 0..ITERS {
+ let mut v = outer.clone();
+ for i in black_box((0..=($len as usize - 1) as _).rev()) {
+ v.remove(i);
+ }
+ black_box(&v);
+ }
+ });
+ },
+ );
+ }};
+}
+
+fn smallvec_benches(c: &mut Criterion) {
+ smallvec_benches!(c, u8; 8);
+ smallvec_benches!(c, u8; 16);
+ smallvec_benches!(c, u8; 32);
+ smallvec_benches!(c, u8; 64);
+ smallvec_benches!(c, u8; 128);
+ smallvec_benches!(c, u8; 256);
+ smallvec_benches!(c, u64; 2);
+ smallvec_benches!(c, u64; 4);
+ smallvec_benches!(c, u64; 8);
+ smallvec_benches!(c, u64; 16);
+ smallvec_benches!(c, u64; 32);
+}
+
+criterion_group!(benches, tinyvec_benches, smallvec_benches);
+criterion_main!(benches);
diff --git a/compare_benchmarks.py b/compare_benchmarks.py new file mode 100644 index 0000000..86eb7e8 --- /dev/null +++ b/compare_benchmarks.py @@ -0,0 +1,30 @@ +import os
+import os.path
+import json
+
+comparisons = []
+
+for (root, _dirs, files) in os.walk('target/criterion'):
+ for file in files:
+ if file == 'estimates.json' and root.endswith(
+ 'new') and 'TinyVec' in root:
+ path = os.path.join(root, file)
+
+ bench_name = path.split('/')[3]
+ tinyvec_time = json.load(open(path))['mean']['point_estimate']
+
+ path = path.replace('TinyVec', 'SmallVec')
+
+ smallvec_time = json.load(open(path))['mean']['point_estimate']
+
+ comparisons.append((bench_name, tinyvec_time / smallvec_time))
+
+comparisons.sort(key=lambda x: x[1])
+longest_name = max(len(c[0]) for c in comparisons)
+for (name, ratio) in comparisons:
+ # Undo the criterion name mangling
+ name = name.replace('_[', '<[')
+ name = name.replace(']___', ']>::')
+
+ name = name.ljust(longest_name)
+ print(f"{name} {ratio:.2f}")
@@ -1,4 +1,4 @@ -#![no_std]
+#![cfg_attr(not(feature = "std"), no_std)]
#![forbid(unsafe_code)]
#![cfg_attr(
feature = "nightly_slice_partition_dedup",
diff --git a/src/tinyvec.rs b/src/tinyvec.rs index 3e884fc..1e11a47 100644 --- a/src/tinyvec.rs +++ b/src/tinyvec.rs @@ -107,8 +107,8 @@ where #[inline]
fn clone(&self) -> Self {
match self {
- Self::Heap(v) => Self::Heap(v.clone()),
- Self::Inline(v) => Self::Inline(v.clone()),
+ TinyVec::Heap(v) => TinyVec::Heap(v.clone()),
+ TinyVec::Inline(v) => TinyVec::Inline(v.clone()),
}
}
@@ -172,6 +172,21 @@ impl<A: Array, I: SliceIndex<[A::Item]>> IndexMut<I> for TinyVec<A> { }
}
+#[cfg(feature = "std")]
+#[cfg_attr(docs_rs, doc(cfg(feature = "std")))]
+impl<A: Array<Item = u8>> std::io::Write for TinyVec<A> {
+ #[inline(always)]
+ fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
+ self.extend_from_slice(buf);
+ Ok(buf.len())
+ }
+
+ #[inline(always)]
+ fn flush(&mut self) -> std::io::Result<()> {
+ Ok(())
+ }
+}
+
#[cfg(feature = "serde")]
#[cfg_attr(docs_rs, doc(cfg(feature = "serde")))]
impl<A: Array> Serialize for TinyVec<A>
diff --git a/tests/tinyvec.rs b/tests/tinyvec.rs index e59a83b..ab4d9bd 100644 --- a/tests/tinyvec.rs +++ b/tests/tinyvec.rs @@ -394,3 +394,18 @@ fn TinyVec_pretty_debug() { assert_eq!(s, expected);
}
+
+#[cfg(feature = "std")]
+#[test]
+fn TinyVec_std_io_write() {
+ use std::io::Write;
+ let mut tv: TinyVec<[u8; 3]> = TinyVec::new();
+
+ tv.write_all(b"foo").ok();
+ assert!(tv.is_inline());
+ assert_eq!(tv, tiny_vec![b'f', b'o', b'o']);
+
+ tv.write_all(b"bar").ok();
+ assert!(tv.is_heap());
+ assert_eq!(tv, tiny_vec![b'f', b'o', b'o', b'b', b'a', b'r']);
+}
|