17 个版本

0.5.2 2022 年 5 月 27 日
0.5.1 2021 年 7 月 22 日
0.5.0 2021 年 1 月 26 日
0.4.4 2020 年 5 月 2 日
0.4.2 2020 年 3 月 31 日

#34Rust 模式

Download history 138328/week @ 2024-03-04 143232/week @ 2024-03-11 143079/week @ 2024-03-18 144374/week @ 2024-03-25 142682/week @ 2024-04-01 149259/week @ 2024-04-08 156271/week @ 2024-04-15 155026/week @ 2024-04-22 131899/week @ 2024-04-29 159824/week @ 2024-05-06 158125/week @ 2024-05-13 145611/week @ 2024-05-20 147436/week @ 2024-05-27 166594/week @ 2024-06-03 159836/week @ 2024-06-10 158172/week @ 2024-06-17

638,543 每月下载量
503 个 crate 中使用 (36 直接使用)

MIT/Apache

40KB
894

beef

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

比原始的 Cow 更快、更紧凑的实现。

变更日志 - 文档 - Cargo - 仓库

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!",
);

此 crate 公开了 Cow 的两个版本

  • beef::Cow 是 3 个字宽:指针、长度和容量。它将所有权标签存储在容量中。
  • beef::lean::Cow 是 2 个字宽,将长度、容量和所有权标签都存储在一个字中。

这两个版本都比 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);

它是如何工作的?

标准库中的 Cow 是一个包含两个变体的枚举

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

对于最常见的值对 - &strString,或 &[u8]Vec<u8> - 这意味着整个枚举是 4 个字宽

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

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

而不是使用带有标签的枚举,beef::Cow 使用容量来确定它所持有的值是拥有(容量大于 0)还是借用(容量为 0)。

beef::lean::Cow 甚至更进一步,将长度和容量放在一个 64 字中。

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

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

任何拥有0容量的VecString都被视为借用的值。因为没有容量意味着指针后面没有实际分配,所以这是安全的。

基准测试

cargo +nightly bench

获取&str引用的微基准测试非常不稳定,你可能会得到截然不同的结果。一般来说,以下情况似乎成立:

  • beef::Cowbeef::lean::Cow在获取引用&T方面比std::borrow::Cow更快。这是有意义的,因为我们避免了枚举标签分支。
  • 3字节的beef::Cow在创建借用变体时更快,但在创建所有者变体时比std::borrow::Cow慢。
  • 2字节的beef::lean::Cow在这两方面都更快。
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)

许可协议

此软件包根据MIT许可协议和Apache License(版本2.0)的条款进行分发。请选择最适合您的一个。

有关详细信息,请参阅LICENSE-APACHELICENSE-MIT

依赖项

~180KB