Skip to content

Big performance difference between python-zstd and zstd-rs speeds #303

@scrottty

Description

@scrottty

Hey! I'm getting a 6x processing speed difference between the python package python-zstd and this package when compressing a single image that is ~13MB in size. The python variant compresses in ~0.38 seconds whilst rust is taking ~2.4 seonds. This same issue occurs when comparing the zstd-cli tool with rust

We have tried to implement this package in all of the different ways we can. And we have also tried to match the python implementation as close as possible but are continuing to get the same result. Both are using the same version of zstd under the hood.

Is there any chance you can see where we have gone wrong to be getting such a big performance lose compared to python and the cli? Please let me know if you need any other information!

Here are our testing scripts and results. Our test device is an embedded system running Yocto linux.

Rust

main.rs:

use std::{fs, path::Path, time::Instant};

use zstd::zstd_safe::CCtx;
use zstd::zstd_safe::CParameter;

fn main() {
    let img_path = Path::new("./img_raw");
    let img_data = fs::read(img_path).unwrap();

    println!("Input size: {:?} bytes", img_data.len());

    for _ in 0..=20 {
        let t0 = Instant::now();
        let mut cctx = CCtx::create();
        cctx.init(1).unwrap();
        let cparam = CParameter::NbWorkers(1);
        cctx.set_parameter(cparam).unwrap();

        let mut output = Vec::new();
        output.reserve(img_data.len());
        let data_size = cctx.compress2(&mut output, &img_data).unwrap();
        println!(
            "Compression time: {:?} | Compression size: {:?}",
            t0.elapsed(),
            data_size
        );
    }
}

cargo.toml:

[package]
name = "zstd_test"
version = "0.1.0"

[dependencies]
zstd = { version = "0.13.2", features = ["zstdmt"] }

console output

sh-5.2# ./zstd_test
Input size: 13120000 bytes
Compression time: 2.424943091s | Compression size: 4141879
Compression time: 2.425405005s | Compression size: 4141879
Compression time: 2.420405395s | Compression size: 4141879
Compression time: 2.418717218s | Compression size: 4141879
Compression time: 2.419599167s | Compression size: 4141879
Compression time: 2.418817959s | Compression size: 4141879
Compression time: 2.419841419s | Compression size: 4141879
Compression time: 2.419766838s | Compression size: 4141879
Compression time: 2.423758679s | Compression size: 4141879
Compression time: 2.419085892s | Compression size: 4141879
Compression time: 2.423615787s | Compression size: 4141879
Compression time: 2.428020042s | Compression size: 4141879
Compression time: 2.419602857s | Compression size: 4141879
Compression time: 2.420533826s | Compression size: 4141879
Compression time: 2.421025891s | Compression size: 4141879
Compression time: 2.423241083s | Compression size: 4141879
Compression time: 2.420323494s | Compression size: 4141879
Compression time: 2.421580927s | Compression size: 4141879
Compression time: 2.424723099s | Compression size: 4141879
Compression time: 2.424607418s | Compression size: 4141879
Compression time: 2.420573007s | Compression size: 4141879

Python

zstd_tests.py

import zstd
import time

img_raw = open("./img_raw", "rb").read()

print(f"Input size: {len(img_raw)} bytes")

for i in range(20):
    t0 = time.time()
    comp = zstd.compress(img_raw, 1, 1)
    print(f"Compression time: {time.time() - t0}s | Compression size: {len(comp)}")

python packages

sh-5.2# python3 -m pip list
Package               Version
--------------------- ------------
...
zstd                  1.5.2.1

sh-5.2# python3 --version
Python 3.12.4

console output

sh-5.2# python3 zstd_tests.py
Input size: 13120000 bytes
Compression time: 0.3925755023956299s | Compression size: 4141879
Compression time: 0.3913264274597168s | Compression size: 4141879
Compression time: 0.38705897331237793s | Compression size: 4141879
Compression time: 0.38625478744506836s | Compression size: 4141879
Compression time: 0.38326406478881836s | Compression size: 4141879
Compression time: 0.3831746578216553s | Compression size: 4141879
Compression time: 0.3832221031188965s | Compression size: 4141879
Compression time: 0.38354063034057617s | Compression size: 4141879
Compression time: 0.3833439350128174s | Compression size: 4141879
Compression time: 0.383317232131958s | Compression size: 4141879
Compression time: 0.38402223587036133s | Compression size: 4141879
Compression time: 0.38319969177246094s | Compression size: 4141879
Compression time: 0.3832590579986572s | Compression size: 4141879
Compression time: 0.3833591938018799s | Compression size: 4141879
Compression time: 0.38364577293395996s | Compression size: 4141879
Compression time: 0.38327574729919434s | Compression size: 4141879
Compression time: 0.3832426071166992s | Compression size: 4141879
Compression time: 0.38323450088500977s | Compression size: 4141879
Compression time: 0.383345365524292s | Compression size: 4141879
Compression time: 0.3834688663482666s | Compression size: 4141879

zstd_cli

For good measure I also ran the benchmark on the cli tool
console output

sh-5.2# zstd -b1 ./img_raw -o cli_test_output
 1#img_raw           :  13120000 ->   4143404 (x3.166),   35.2 MB/s,  104.3 MB/s

35.2 MB/s for a 13.12MB image comes to ~0.37s. This is in line with the python results

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions