7 pontos por GN⁺ 3 시간 전 | 1 comentários | Compartilhar no WhatsApp
  • libzstd-rs-sys é o terceiro projeto de compressão da fundação Trifecta, depois de zlib e bzip2, e é a primeira release do zstd baseada em Rust
  • Zstd é um formato de compressão voltado para CPUs modernas, mais rápido que gzip e com melhor taxa de compressão, devendo substituir gradualmente o gzip no tráfego web
  • O crate zstd existente em Rust compila código C a partir do fonte, então exige uma toolchain C e suporte ao alvo, o que pode dificultar a configuração para Windows e WebAssembly
  • A implementação em Rust pode ser compilada como uma biblioteca C compatível como substituição direta, e está sendo validada como alternativa à implementação de referência em C com suíte de testes, fuzz testing e Miri
  • A descompressão padrão é alguns por cento mais lenta que em C, mas a queda de cerca de 3% no desempenho é o custo da segurança de memória, e uma flag experimental pode igualar o desempenho do C

Primeira release e o significado da implementação em Rust

  • A Trifecta Tech Foundation anunciou a primeira release do libzstd-rs-sys, que trabalha com zstd como o terceiro projeto de compressão da fundação, após zlib e bzip2
  • Zstd é um formato de compressão projetado pensando em CPUs modernas, capaz de ser muito mais rápido que o gzip e oferecer melhor taxa de compressão
  • O zstd já é amplamente usado e deve substituir gradualmente o gzip no tráfego web
  • Em Rust, já é possível usar zstd pelo crate zstd, mas o crate existente compila código C a partir do fonte, exigindo uma toolchain C e suporte ao alvo correspondente
  • Como configurar uma toolchain C para Windows ou WebAssembly pode ser difícil, uma implementação puramente em Rust oferece uma experiência melhor de uso de dependências para desenvolvedores Rust
  • O libzstd-rs-sys pode ser compilado como uma biblioteca C compatível como substituição direta, assim como os trabalhos com zlib e bzip2, e pretende ser uma alternativa à implementação de referência em C
  • A implementação de referência em C é mantida pela Meta e, para contribuir, é preciso assinar um acordo de contribuinte com a Meta; por isso, uma implementação independente, de bom desempenho e compatível pode fortalecer o ecossistema open source

Validação, desempenho e trabalho restante

  • A implementação de referência inicial foi convertida com c2rust, e depois foram concluídos os trabalhos de limpeza da descompressão e do construtor de dicionários
  • O código Rust é compilado como biblioteca estática em C e depois validado com a suíte de testes da implementação de referência
  • Fuzz testing e Miri também são usados para verificar a correção da implementação
  • A pré-release está disponível em libzstd-rs-sys v0.0.1-prerelease.2
  • O custo da segurança de memória

    • O desempenho padrão da descompressão é alguns por cento inferior ao da implementação de referência em C
    • Cada mudança mesclada em main é medida na suíte de benchmarks
    • Ao ativar a flag de recurso unsafe-performance-experimental, o desempenho se iguala ao do C
    • Essa flag desativa verificações de limite em 4 pontos onde os dados de entrada são usados na indexação de estruturas de dados
    • Para a maioria dos usuários, uma perda de desempenho de cerca de 3% provavelmente é um custo aceitável pela segurança de memória aprimorada
    • Se for necessário extrair até o último nível de desempenho, é possível assumir o risco e ativar essa flag; o comportamento nesses 4 pontos fica alinhado ao do C, que não faz verificações de limite
  • Implementação da compressão e integração com o ecossistema

    • A parte de compressão ainda está em busca de financiamento
    • Há compartilhamento de código entre compressão e descompressão, então parte do código de compressão também já foi analisada, mas a maior parte do trabalho de limpeza ainda resta
    • Foram configurados benchmarks para evitar regressões de desempenho na compressão, e a suíte de testes da implementação de referência está sendo usada para verificar se os resultados corretos estão sendo gerados
    • O trabalho restante está organizado em Milestone 4: Encoder implementation
    • Existe um fork de zstd que usa libzstd-rs-sys no lugar da biblioteca C, e a intenção é incorporá-lo upstream no futuro
    • Nas APIs mais usadas, a integração é relativamente simples
    • No recurso experimental, há uma incompatibilidade: zstd-safe usa enum, mas será preciso usar struct para garantir segurança de FFI
  • Patrocínio

1 comentários

 
GN⁺ 3 시간 전
Opiniões no Lobste.rs
  • Isso é realmente uma ótima notícia. Há alguns dias eu precisei puxar libc-dev só para fazer um build do zstd por causa de uma dependência, e fiquei me perguntando se alguém já tinha tentado uma reimplementação séria em Rust
    Espero que isso seja amplamente adotado pela comunidade

  • Estou criando um projeto baseado em WireGuard em Rust e trazendo várias bibliotecas criptográficas de Rust. Há a vantagem clara da segurança de memória, mas, ao contrário de bibliotecas C antigas, nem todas passaram por auditoria de segurança
    No fim, a questão que me interessa é se reescrever esses algoritmos em Rust vale mesmo o custo

    • Vale muito a pena. Criptografia costuma ser contornada com muito mais frequência por falhas de implementação do que porque o algoritmo em si foi quebrado
      O código “chato” não criptográfico, como parsing, estado do protocolo e gerenciamento de buffer, precisa funcionar direito para o sistema ser seguro. Se um atacante puder enviar um pacote mágico que permita execução arbitrária de código, ele não vai perder tempo com criptoanálise avançada ou canais laterais de timing para reduzir de milhares de anos para algumas décadas o tempo necessário para quebrar a cifra
    • Se os requisitos de desempenho do projeto não forem apertados demais e você puder tolerar um pouco de FFI, também dá para usar a stack criptográfica de Go a partir de Rust
      A vantagem é que ambos têm segurança de memória, e você só precisa manter uma fronteira estreita de FFI unsafe. As bibliotecas criptográficas de Go hoje são mais maduras do que as oferecidas por Rust, ou mais precisamente pelo ecossistema crates.io
  • Queria saber se alguém conhece alguma explicação documentada sobre quando usar os sufixos -sys e -rs-sys. Minha intuição era que -sys seria para crates que encapsulam bibliotecas de sistema não escritas em Rust
    Mas nesse caso o sufixo -rs-sys não faz muito sentido, então imagino que minha intuição estivesse errada. Alguém conhece uma fonte confiável sobre isso?

    • Esse nome de pacote foi escolhido de um jeito quase tão ruim quanto humanamente possível. Três das quatro partes do nome estão erradas ou são indesejáveis
      *-sys: é uma convenção antiga e amplamente usada, explicada em https://doc.rust-lang.org/cargo/reference/… . Mas não se aplica a este crate de forma alguma
      lib*: já sabemos que é uma biblioteca, esse prefixo não é convencional em Rust, e o link acima até indica de maneira meio indireta que ele deve ser evitado junto com *-sys. libzstd-sys poderia fazer alguém esperar que ele faça link com liblibzstd. E, aliás, já vi nomes duplos com lib na prática, mesmo fora de Rust
      *-rs: como diz https://rust-lang.github.io/api-guidelines/naming.html , “todo crate é Rust! Não há necessidade de lembrar isso aos usuários o tempo todo”
    • Crates -sys normalmente expõem uma interface estilo C bem crua, contêm bastante código unsafe internamente e em geral fazem build ou link com uma biblioteca externa
      Já vi o nome -rs-sys ser usado de forma menos consistente. Parece ser usado para bibliotecas que fazem build de código externo reempacotado dentro de um crate Rust, por exemplo uma implementação Rust incompleta que ainda mantém partes em C, ou código de suporte em Rust para um sys crate
    • Existe uma certa lógica
      libzstd é o nome original. Bibliotecas C tendem a incluir lib no nome, e ele foi mantido como referência em vez de ser adaptado à convenção de Rust/Cargo
      -rs marca que é uma reescrita em Rust, para diferenciar da implementação em C do Facebook. É um sufixo genérico bem comum em vários projetos Rust, parecido com bibliotecas Python que usam nomes como pysomething
      -sys porque essa implementação expõe uma API C unsafe como substituta direta. Do ponto de vista do usuário de Cargo, não é uma biblioteca Rust. Não há interface Rust; ela é chamada como código C com funções C
      Então não é -rs-sys, e sim a versão -sys de libzstd-rs
  • Por que escolher isso em vez de ruzstd? Não seria melhor investir no crate já existente?

    • O ruzstd ainda não implementa compressão por completo
      Um port 1:1 permite alcançar velocidade parecida e paridade de recursos com uma conversão de código relativamente direta, em vez de precisar descobrir de novo como fazer um compressor igualmente rápido e completo sobre outra base de código
  • “A implementação de referência em C é mantida pela Meta, e para contribuir é preciso assinar um acordo de contribuição com a Meta”
    Um fato curioso que descobri recentemente é que a implementação zstd de referência mantida pelo Facebook também está sendo codada com LLM, e como ela também é dependência do openssl, sou totalmente a favor de haver mais alternativas

  • “Nas configurações padrão, o desempenho de descompressão da nossa implementação é alguns pontos percentuais mais lento do que o da implementação de referência em C”
    Isso é tudo o que eu preciso saber sobre este projeto

    • Você poderia explicar um pouco mais o que essa frase te passou?
      Só para referência, logo depois da frase citada vem o seguinte
      “No entanto, consideramos essa perda de desempenho justificável, porque ativar a flag de funcionalidade unsafe-performance-experimental iguala o desempenho ao do C. Essa flag desativa 4 verificações de limite em quatro pontos onde os dados de entrada são usados para indexar estruturas de dados. Para a maioria dos usuários, uma perda de cerca de 3% de desempenho provavelmente é um custo aceitável em troca de maior segurança de memória. Se você realmente precisa extrair até o último ganho de desempenho, pode ativar essa flag por sua conta e risco. O comportamento nesses quatro pontos é idêntico ao do C sem verificações de limite, e isso aparentemente funciona sem problemas em muitos sistemas de produção”