# \[ANN\] Decompress 0.7

**URL:** <https://discuss.ocaml.org/t/ann-decompress-0-7/995>\
**Category:** Community\
**Tags:** zlib, decompress, mirageos, announce\
**Created:** [October 21, 2017, 10:11pm UTC](https://discuss.ocaml.org/t/ann-decompress-0-7/995 "2017-10-21T22:11:30Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![dinosaure](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dinosaure/32/16_2.png) [@dinosaure](https://discuss.ocaml.org/u/dinosaure)\
**Post date:** [October 21, 2017, 10:11pm UTC](https://discuss.ocaml.org/t/ann-decompress-0-7/995/1 "2017-10-21T22:11:30Z")

</div>

Hi all,

I’m happy to announce a new release of [`decompress.0.7`](https://github.com/mirage/decompress/releases/tag/v0.7) available for installation via OPAM.

Decompress is a library which provide an implementation of [zlib](https://zlib.net/) in pure OCaml. This library provides the _same_ functions as [`camlzip`](https://github.com/xavierleroy/camlzip) (which is a binding with the official implementation of `zlib`) and a more [low-level API](https://mirage.github.io/decompress/api.docdir/Decompress.html) to keep the control about the memory allocation.

A little example with an explanation is provided [here](https://github.com/mirage/decompress/blob/master/bin/easy.ml) to understand how to use `decompress`.

The goal of `decompress` is to provide a good `zlib` implementation which can be compiled (by the ocaml compiler way) to some exotic back-end and keep the same behaviour. In this way, `decompress` is one key on the Mirage OS project. Obviously, `decompress` can be compiled by `js_of_ocaml` (tested on the last ICFP to simulate a Git repository in your web browser).

This release is much more about fixed bug and a good example of [how to use AFL](https://github.com/mirage/decompress/blob/master/fuzz/fuzz.ml). We fixed 2 bugs:

- [eaeb1de](https://github.com/mirage/decompress/commit/eaeb1ded4ecf61cca07ccb2196a2d3de2d1f178d) the first deflate algorithm (which uses the CPS style but appears only when the input is less than 12 bytes)
- [a6f6b2b](https://github.com/mirage/decompress/commit/a6f6b2ba0a3ba6dadf2ea13ef9a85aa71b106aca) a variable name overlap in the dictionary inflate algorithm

About performance, we already did some works with @yallop and @samoht (_defuntorization_, immutable state, etc.) in the [0.5](https://github.com/mirage/decompress/releases/tag/0.5) release. And, with [`landmarks`](https://github.com/LexiFi/landmarks), the ADLER-32 checksum seems to be the biggest bottle-neck.

Finally, `decompress` is used by some projects like [datakit](https://github.com/moby/datakit) or [ocaml-git](https://github.com/mirage/ocaml-git) and we can consider (from the [0.4](https://github.com/mirage/decompress/releases/tag/0.4) release) a stable API - this new version exports the ADLER-32 implementation only. A package for [npm](https://www.npmjs.com/) is in the pipe with this current version.

The next plan now is to focus `decompress` on the performance. Then, a plan to implement `gzip` could be interesting.

---

<div class="post-metadata">

**Author:** ![anon72795300](https://avatars.discourse-cdn.com/v4/letter/a/8e7dd6/32.png) [@anon72795300](https://discuss.ocaml.org/u/anon72795300)\
**Post date:** [October 22, 2017, 10:16am UTC](https://discuss.ocaml.org/t/ann-decompress-0-7/995/2 "2017-10-22T10:16:25Z")

</div>

When saying about _“performance … immutable state”_, did you have to introduce immutable state or remove it to increase performance?

---

<div class="post-metadata">

**Author:** ![dinosaure](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dinosaure/32/16_2.png) [@dinosaure](https://discuss.ocaml.org/u/dinosaure)\
**Post date:** [October 22, 2017, 11:08am UTC](https://discuss.ocaml.org/t/ann-decompress-0-7/995/3 "2017-10-22T11:08:01Z")

</div>

With some benchmarks (available in some PR, [#20](https://github.com/mirage/decompress/pull/20), [#18](https://github.com/mirage/decompress/pull/18), [#17](https://github.com/mirage/decompress/pull/17), [#16](https://github.com/mirage/decompress/pull/16), [#15](https://github.com/mirage/decompress/pull/15), [#13](https://github.com/mirage/decompress/pull/13) and [#11](https://github.com/mirage/decompress/pull/11)), we decided to switch the state `Decompress.{Inflate,Deflate}.t` to an immutable state (which does not contain any _mutable_ field).

This change is come from the implementation way of [`ocaml-tls`](https://github.com/mirleft/ocaml-tls) which uses an immutable state too and a great explanation of @yallop about _mutable_ value, `caml_modify` and benchmarking - however, I did not find the explanation link, my bad.

So, `decompress` uses the CPS style with an immutable state to inflate or deflate a stream. However, for a large input (and this is an advise of @samoht), we switch to an imperative algorithm (a big loop which is optimized nicely by the OCaml compiler) and in the end, come back to the CPS style (cf. [inffast](https://github.com/mirage/decompress/blob/master/lib/decompress.ml#L2822)).

So, it’s an hybrid implementation (like OCaml is an hybrid language between functionnal and imperative way). I think, we can do something better but we need to describe precisely a good benchmark first (to compare with `zlib`) - indeed, try to compare `zlib` and `decompress` in a naive way could be a non-sense by the weight of the caml runtime.

Then, before, `decompress` was a functor to describe buffers but in the real world, we have only 2 kinds of buffer (`bigstring` and `bytes`), so we prefer to use an [(G)ADT](https://github.com/mirage/decompress/blob/master/lib/decompress_b.ml#L216) to allow the compiler to specialize the output code. Again, it’s an empirical choice and, with benchmarking, we need to look precisely the generated assembler code.

Obviously, all of these plans (and the optimizations things in general) is not easy when you want to keep a common implementation - a deep specialization of the code could break the behaviour for some specific back-end.

---

<div class="post-metadata">

**Author:** ![pirbo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/pirbo/32/771_2.png) [@pirbo](https://discuss.ocaml.org/u/pirbo)\
**Post date:** [October 27, 2017, 2:30am UTC](https://discuss.ocaml.org/t/ann-decompress-0-7/995/4 "2017-10-27T02:30:57Z")

</div>

Sorry if it is the wrong place but as the announce talks about `js_of_ocaml`, I’ll ask my question here.

I have an application fully running in a web browser thanks to `js_of_ocaml` that generates several stuff users may want to “save on disk” as files. They can do so file by file but, of course, they always ask for a “download all” option. I cannot think about any better way to do so than generating an archive and offering to download it. Is there a better way?

Seeking for an OCaml library to generate archive (I don’t really care about compression, generated files are small) that compiles in javascript, `decompress` looked indeed to be my best hope but, if I’m not mistaken, it only provides the `Zlib` module of `camlzip` whereas I would need the `Zip` module. Have I seen correctly and do you know where I could find what I’m looking for?

---

<div class="post-metadata">

**Author:** ![dinosaure](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dinosaure/32/16_2.png) [@dinosaure](https://discuss.ocaml.org/u/dinosaure)\
**Post date:** [October 27, 2017, 7:58am UTC](https://discuss.ocaml.org/t/ann-decompress-0-7/995/5 "2017-10-27T07:58:43Z")

</div>

You are right. `decompress` provides only the `zlib` implementation (which deflate/inflate a flow). `gzip` could be a solution but it’s not my plan for the next release (as I said, it’s benchmarking). However, someone implemented the `gzip` layer (because it’s just a layer in top of `zlib`) but on a previous (not recommended) version of `decompress`.

So, my best advise is to wait my implementation of `gzip` in `decompress` 😊 if you want a fully implementation of `gzip` in OCaml available in the javascript world by `js_of_ocaml`. In other side, the JavaScript world should provide a `gzip` implementation with bindings but I’m not an expert of JavaScript.

---

<div class="post-metadata">

**Author:** ![pirbo](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/pirbo/32/771_2.png) [@pirbo](https://discuss.ocaml.org/u/pirbo)\
**Post date:** [October 27, 2017, 7:37pm UTC](https://discuss.ocaml.org/t/ann-decompress-0-7/995/6 "2017-10-27T19:37:42Z")

</div>

🙂 Thank you for your answer. I indeed started to create a binding of [jszip](https://github.com/Stuk/jszip/) but I never could understood how to write correctly js bindings so I gave up for now…

I’m not an expert on the subject but as far as I understood, Gzip won’t save me (at least `Gzip` module of `camlzip` doesn’t) as gzip still deals with one file (that’s why we do tar.gz when we need an archive)… I looked at [ocaml-tar](https://github.com/mirage/ocaml-tar) by the way during my search but it still rely on an `IO.input_channel` that can I don’t know how to provide in javascript!
