繁体   English   中英

将字节转换为 u64

[英]Convert bytes to u64

我需要将 Rust 中字符串的前 8 个字节转换为 u64,大端。 这段代码几乎可以工作:

fn main() {
    let s = String::from("01234567");
    let mut buf = [0u8; 8];
    buf.copy_from_slice(s.as_bytes());
    let num = u64::from_be_bytes(buf);
    println!("{:X}", num);
}

此代码存在多个问题。 首先,它仅在字符串恰好为 8 个字节长时才有效。 .copy_from_slice()要求源和目标的长度相同。 如果 String 太长,这很容易处理,因为我可以只抓取一段合适的长度,但如果 String 很短,那就不行了。

另一个问题是这段代码是 function 的一部分,它对性能非常敏感。 它在大型数据集上紧密循环运行。

在 C 中,我只是将 buf、memcpy 归零到正确的字节数,然后转换为无符号长整型。

有没有办法在 Rust 中执行此操作,运行速度一样快?

您可以只修改现有代码以在复制时考虑长度:

    let len = 8.min(s.len());
    buf[..len].copy_from_slice(&s.as_bytes()[..len]);

如果字符串很短,这当然会将字节复制到将成为u64的最高有效位的位置。

至于性能:在这个简单的测试main()中,转换被完全优化为常量 integer。因此,我们需要一个明确的 function 或循环:

pub fn convert(s: &str) -> u64 {
    let mut buf = [0u8; 8];
    let len = 8.min(s.len());
    buf[..len].copy_from_slice(&s.as_bytes()[..len]);
    u64::from_be_bytes(buf)
}

这(在 Rust 游乐场上)生成程序集:

playground::convert:
    pushq   %rax
    movq    %rdi, %rax
    movq    $0, (%rsp)
    cmpq    $8, %rsi
    movl    $8, %edx
    cmovbq  %rsi, %rdx
    movq    %rsp, %rdi
    movq    %rax, %rsi
    callq   *memcpy@GOTPCREL(%rip)
    movq    (%rsp), %rax
    bswapq  %rax
    popq    %rcx
    retq

我有点怀疑与仅发出复制字节的指令相比, memcpy调用实际上是一个好主意,但我不是指令级性能方面的专家,并且大概它至少等于您的 C 代码显式调用memcpy() 我们确实看到编译后的代码中没有分支,只有一个条件移动,大概是为了处理8 vs. len()选择——并且没有边界检查恐慌。

(当这个 function 或代码片段被内联到一个更大的循环中时,生成的程序集当然会有所不同——希望更好。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM