All Projects → maciejhirsz → Beef

maciejhirsz / Beef

Licence: other
Faster, more compact implementation of std::borrow::Cow

Programming Languages

rust
11053 projects

Labels

Projects that are alternatives of or similar to Beef

Rubble
(going to be a) BLE stack for embedded Rust
Stars: ✭ 292 (+54.5%)
Mutual labels:  no-std
Cortex M Rtic
Real-Time Interrupt-driven Concurrency (RTIC) framework for ARM Cortex-M microcontrollers
Stars: ✭ 623 (+229.63%)
Mutual labels:  no-std
Governor
A rate-limiting library for Rust (formerly ratelimit_meter)
Stars: ✭ 99 (-47.62%)
Mutual labels:  no-std
Nvptx
How to: Run Rust code on your NVIDIA GPU
Stars: ✭ 335 (+77.25%)
Mutual labels:  no-std
Serde
Serialization framework for Rust
Stars: ✭ 4,901 (+2493.12%)
Mutual labels:  no-std
Byte
A low-level, zero-copy, panic-free, binary serializer and deserializer. (parser and encoder)
Stars: ✭ 29 (-84.66%)
Mutual labels:  no-std
Drone Core
The core crate for Drone, an Embedded Operating System.
Stars: ✭ 263 (+39.15%)
Mutual labels:  no-std
Pin Project
A crate for safe and ergonomic pin-projection.
Stars: ✭ 174 (-7.94%)
Mutual labels:  no-std
Heapless
Heapless, `static` friendly data structures
Stars: ✭ 575 (+204.23%)
Mutual labels:  no-std
Bitmatch
A Rust crate that allows you to match, bind, and pack the individual bits of integers.
Stars: ✭ 82 (-56.61%)
Mutual labels:  no-std
Time
Simple time handling in Rust
Stars: ✭ 334 (+76.72%)
Mutual labels:  no-std
Cortex M
Low level access to Cortex-M processors
Stars: ✭ 379 (+100.53%)
Mutual labels:  no-std
Rhai
Rhai - An embedded scripting language for Rust.
Stars: ✭ 958 (+406.88%)
Mutual labels:  no-std
Embedded Graphics
A no_std graphics library for embedded applications
Stars: ✭ 293 (+55.03%)
Mutual labels:  no-std
Drone
CLI utility for Drone, an Embedded Operating System.
Stars: ✭ 114 (-39.68%)
Mutual labels:  no-std
Cortex M Rt
Minimal startup / runtime for Cortex-M microcontrollers
Stars: ✭ 286 (+51.32%)
Mutual labels:  no-std
Xargo
The sysroot manager that lets you build and customize `std`
Stars: ✭ 841 (+344.97%)
Mutual labels:  no-std
Auto enums
A library for to allow multiple return types by automatically generated enum.
Stars: ✭ 188 (-0.53%)
Mutual labels:  no-std
Utest
Unit `#[test]`ing for microcontrollers and other `no_std` systems
Stars: ✭ 119 (-37.04%)
Mutual labels:  no-std
Wyhash Rs
wyhash fast portable non-cryptographic hashing algorithm and random number generator in Rust
Stars: ✭ 44 (-76.72%)
Mutual labels:  no-std

beef

Travis shield Crates.io version shield Crates.io license shield

Faster, more compact implementation of Cow.

Changelog - Documentation - Cargo - Repository

use beef::Cow;

let borrowed: Cow<str> = Cow::borrowed("Hello");
let owned: Cow<str> = Cow::owned(String::from("World"));

assert_eq!(
    format!("{} {}!", borrowed, owned),
    "Hello World!",
);

There are two versions of Cow exposed by this crate:

  • beef::Cow is 3 words wide: pointer, length, and capacity. It stores the ownership tag in capacity.
  • beef::lean::Cow is 2 words wide, storing length, capacity, and the ownership tag all in one word.

Both versions are leaner than the std::borrow::Cow:

use std::mem::size_of;

const WORD: usize = size_of::<usize>();

assert_eq!(size_of::<std::borrow::Cow<str>>(), 4 * WORD);
assert_eq!(size_of::<beef::Cow<str>>(), 3 * WORD);
assert_eq!(size_of::<beef::lean::Cow<str>>(), 2 * WORD);

How does it work?

The standard library Cow is an enum with two variants:

pub enum Cow<'a, B> where
    B: 'a + ToOwned + ?Sized,
{
    Borrowed(&'a B),
    Owned(<B as ToOwned>::Owned),
}

For the most common pairs of values - &str and String, or &[u8] and Vec<u8> - this means that the entire enum is 4 words wide:

                                                 Padding
                                                    |
                                                    v
          +-----------+-----------+-----------+-----------+
Borrowed: | Tag       | Pointer   | Length    | XXXXXXXXX |
          +-----------+-----------+-----------+-----------+

          +-----------+-----------+-----------+-----------+
Owned:    | Tag       | Pointer   | Length    | Capacity  |
          +-----------+-----------+-----------+-----------+

Instead of being an enum with a tag, beef::Cow uses capacity to determine whether the value it's holding is owned (capacity is greater than 0), or borrowed (capacity is 0).

beef::lean::Cow goes even further and puts length and capacity on a single 64 word.

                 +-----------+-----------+-----------+
beef::Cow        | Pointer   | Length    | Capacity? |
                 +-----------+-----------+-----------+

                 +-----------+-----------+
beef::lean::Cow  | Pointer   | Cap | Len |
                 +-----------+-----------+

Any owned Vec or String that has 0 capacity is effectively treated as a borrowed value. Since having no capacity means there is no actual allocation behind the pointer, this is safe.

Benchmarks

cargo +nightly bench

Microbenchmarking obtaining a &str reference is rather flaky and you can have widely different results. In general the following seems to hold true:

  • beef::Cow and beef::lean::Cow are faster than std::borrow::Cow at obtaining a reference &T. This makes sense since we avoid the enum tag branching.
  • The 3-word beef::Cow is faster at creating borrowed variants, but slower at creating owned variants than std::borrow::Cow.
  • The 2-word beef::lean::Cow is faster at both.
running 9 tests
test beef_as_ref            ... bench:          57 ns/iter (+/- 15)
test beef_create            ... bench:         135 ns/iter (+/- 5)
test beef_create_mixed      ... bench:         659 ns/iter (+/- 52)
test lean_beef_as_ref       ... bench:          50 ns/iter (+/- 2)
test lean_beef_create       ... bench:          77 ns/iter (+/- 3)
test lean_beef_create_mixed ... bench:         594 ns/iter (+/- 52)
test std_as_ref             ... bench:          70 ns/iter (+/- 6)
test std_create             ... bench:         142 ns/iter (+/- 7)
test std_create_mixed       ... bench:         663 ns/iter (+/- 32)

License

This crate is distributed under the terms of both the MIT license and the Apache License (Version 2.0). Choose whichever one works best for you.

See LICENSE-APACHE and LICENSE-MIT for details.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].