LINUX.ORG.RU

История изменений

Исправление zurg, (текущая версия) :

считать такие хеши надо максимально быстро,

Вот поэтому и надо брать раст, это ты чё там гадаешь по размеру ассемблерного выхлопа? Такое правильно так сравнивать:

const qspCRCTable: [u32; 256] =[ ... ];

fn qspCRC(data: &[u8]) -> i32 {
    data.iter().fold(0, |crc, b| {
            let tbl = qspCRCTable[(b ^ crc as u8) as usize];
            (tbl as i32^crc>>8) ^ 0xD202EF8Du32 as i32
        })
}

use std::time::*;
fn main() {
    let len = 1_000_000_000;
    let data: Vec<u8> = (0..len).map(|i| (i%256) as u8).collect();
    let t0 = Instant::now();
    let crc = qspCRC2(data.as_slice());
    println!("time {} s", (t0.elapsed().as_micros() as f64)/1e6f64 );
    println!("crc {}", crc);
}
time 2.112588 s
crc 2031280483

hyperfine ./crcr
Benchmark 1: ./crcr
  Time (mean ± σ):      2.640 s ±  0.007 s    [User: 2.163 s, System: 0.477 s]
  Range (min … max):    2.630 s …  2.654 s    10 runs
int qspCRCTable[256] = {...};
int qspCRC(void *data, int len)
{
    unsigned char *ptr;
    int crc = 0;
    ptr = (unsigned char *)data;
    while (len--)
        crc = (qspCRCTable[(crc & 0xFF) ^ *ptr++] ^ crc >> 8) ^ 0xD202EF8D;
    return crc;
}
int main(void) {
    int32_t len = 10000000;
    uint8_t* data = (uint8_t*)malloc(len);
    for(uint32_t i=0; i<len; i++) { data[i] = i%256; }

    clock_t start_time = clock();
    int crc = qspCRC(data, len);
    double elapsed_time = (double)(clock() - start_time) / CLOCKS_PER_SEC;
    
    printf("time %f s\n", elapsed_time);
    printf("crc %i\n", crc);
}
time 2.113202 s
crc 2031280483

hyperfine ./crctst
Benchmark 1: ./crctst
  Time (mean ± σ):      2.717 s ±  0.009 s    [User: 2.243 s, System: 0.474 s]
  Range (min … max):    2.705 s …  2.734 s    10 runs

hyperfine для оценки погрешности, короче разницы между llvm и gcc, и между раст и си для функции qspCRC в пределах погрешности нет.

Исходная версия zurg, :

считать такие хеши надо максимально быстро,

Вот поэтому и надо брать раст, это ты чё там гадаешь по размеру ассемблерного выхлопа?

const qspCRCTable: [u32; 256] =[ ... ];

fn qspCRC(data: &[u8]) -> i32 {
    data.iter().fold(0, |crc, b| {
            let tbl = qspCRCTable[(b ^ crc as u8) as usize];
            (tbl as i32^crc>>8) ^ 0xD202EF8Du32 as i32
        })
}

use std::time::*;
fn main() {
    let len = 1_000_000_000;
    let data: Vec<u8> = (0..len).map(|i| (i%256) as u8).collect();
    let t0 = Instant::now();
    let crc = qspCRC2(data.as_slice());
    println!("time {} s", (t0.elapsed().as_micros() as f64)/1e6f64 );
    println!("crc {}", crc);
}
time 2.112588 s
crc 2031280483

hyperfine ./crcr
Benchmark 1: ./crcr
  Time (mean ± σ):      2.640 s ±  0.007 s    [User: 2.163 s, System: 0.477 s]
  Range (min … max):    2.630 s …  2.654 s    10 runs
int qspCRCTable[256] = {...};
int qspCRC(void *data, int len)
{
    unsigned char *ptr;
    int crc = 0;
    ptr = (unsigned char *)data;
    while (len--)
        crc = (qspCRCTable[(crc & 0xFF) ^ *ptr++] ^ crc >> 8) ^ 0xD202EF8D;
    return crc;
}
int main(void) {
    int32_t len = 10000000;
    uint8_t* data = (uint8_t*)malloc(len);
    for(uint32_t i=0; i<len; i++) { data[i] = i%256; }

    clock_t start_time = clock();
    int crc = qspCRC(data, len);
    double elapsed_time = (double)(clock() - start_time) / CLOCKS_PER_SEC;
    
    printf("time %f s\n", elapsed_time);
    printf("crc %i\n", crc);
}
time 2.113202 s
crc 2031280483

hyperfine ./crctst
Benchmark 1: ./crctst
  Time (mean ± σ):      2.717 s ±  0.009 s    [User: 2.243 s, System: 0.474 s]
  Range (min … max):    2.705 s …  2.734 s    10 runs

hyperfine для оценки погрешности, короче разницы между llvm и gcc, и между раст и си для функции qspCRC в пределах погрешности нет.