Skip to content

Marshaling with compression#12006

Merged
gasche merged 6 commits intoocaml:trunkfrom
xavierleroy:compressed-marshaling
Feb 27, 2023
Merged

Marshaling with compression#12006
gasche merged 6 commits intoocaml:trunkfrom
xavierleroy:compressed-marshaling

Conversation

@xavierleroy
Copy link
Copy Markdown
Contributor

This is a proof-of-concept for ocaml/RFCs#23 .

It supports optional compression to marshaled data, with transparent decompression during unmarshaling.

It adds a Marshal.Compression flag to the Marshal.to_ functions, instructing them to produce compressed marshaled data.

Compressed marshaled data is identified with a new magic number and uses a new, compact format for its header, see runtime/caml/intext.h.

Unmarshaling functions (input_value, Marshal.from_*) recognize compressed marshaled data and transparently uncompress before unmarshaling.

The compression library currently used is Zlib (the one used by zip and gzip), at the default compression level of 7. It is autodetected in configure and can be turned off with configure --without-zlib.

If the Zlib library is not available or was turned off, the Marshal.Compression flag is silently ignored and uncompressed marshaled data is produced. The only failure case is if compressed marshaled data produced on another OCaml installation is read back in an installation that doesn't have Zlib.

When compression is on, the format of shared object references is changed from relative to absolute, as suggested in #4056. This does reduce the size of compressed data noticeably (e.g. -15% on a typical .cmt file).

Finally, the compiler was changed to use compression for data marshaled in .cmt and .cmti files. The resulting files are 35-40% the size of the uncompressed files. This comes at a slight increase in compilation times: on my machine, byte-compiling stdlib/camlinternalFormat.ml takes 10% longer; make world.opt takes 3% longer. I have not tried to compress other bulky marshaled data, such as debugging info in .cmo files, or persistent signatures in .cmi files.

@xavierleroy
Copy link
Copy Markdown
Contributor Author

Of course, the first reactions will be to question my choice of Zlib, instead of criticizing the overall design. I chose Zlib because it's available everywhere and I'm somewhat familiar with its API.

For unmarshaling, compressed data is inflated in one go (we know the sizes of the compressed and uncompressed blocks), so any compression library could fit there. A streaming API could be used when unmarshaling from an input channel, but I did not implement this to keep the code simple.

For marshaling, I use the streaming API of Zlib to compress block per block, freeing the input blocks as we go, so that memory requirements decrease during compression. I like this code :-)

@xavierleroy
Copy link
Copy Markdown
Contributor Author

xavierleroy commented Feb 12, 2023

If brave souls would like to experiment with this approach on the scale of a full OPAM installation, I think (but haven't checked) that this PR should apply mostly cleanly to OCaml 5.0.

@xavierleroy
Copy link
Copy Markdown
Contributor Author

Testing shows a rare segmentation fault in tests/lib-marshal/intext_par.ml, which I was able to trigger under debugger once, and was caused by unmarshaling of objects (in non-compressed mode) producing a wrong code pointer. I don't think this failure is related to this PR, but it may indicate something fishy in the management of code segments.

@gasche
Copy link
Copy Markdown
Member

gasche commented Feb 12, 2023

I suspect that the impact on .cmi size could also be an interesting data point. In particular, in codebases that suffer from too-large generated artifacts, disabling .cmt generation is an option, but disabling .cmi generation is not a possibility.

but slows down marshaling and, to a lesser extent, unmarshaling.
Compression is not supported on some platforms; in this case,
the [Marshal.Compression] flag is silently ignored and uncompressed
data is written to channel [chan].
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is good default behaviour. However for clients that want to warn or behave differently when compression is unsupported, it would be nice to have compression_supported, or compression_available or a better name with:

val Marshal.compression_supported : bool
(** [compression_supported] is [true] if and only if compressed (un)marshaling is
    supported on the platform. *)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no technical difficulties to provide such a compression_supported value. I still like the idea that compression is an implementation detail that we can hide (almost) completely from our users. But if there's consensus for compression_supported, I'm fine with it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still like the idea that compression is an implementation detail that we can hide (almost) completely from our users.

Your users will be happy to have a mean to understand or detect why they specified Compressed on marshal but the result isn't. Also since this new behaviour somehow breaks this promise:

The bytes can then be read back later, possibly in another process, and decoded back into a data structure. The format for the byte sequences is compatible across all machines for a given version of OCaml.

I think it's good to have a flag that allows to reconcile this view modulo the boolean.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the "read back on all machines" guarantees, my understanding is that the intent is to support configurations that do not support compression, but try hard to have all configurations support at least decompression. If we manage to get there, we can have the property that all machines can read each other's marshalled data at a given version.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the "read back on all machines" guarantees, my understanding is that the intent is to support configurations that do not support compression, but try hard to have all configurations support at least decompression.

That's great.

But as long as this remains an optional dependency for compression I'd really like to have a way to understand whether my program is going to compress or not.

The design of a system may rely on this, there's various third parties I don't control that may be in charge of installing and configuring the toolchain on a given machine, I'd like to be able to assert this information in my program and take appropriate actions (log a warning, bail out, etc.) if compression is not enabled.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Marshal.compression_supported in commit c41b4cb . It's a unit -> bool function instead of a plain Boolean because the implementation has a small but non-null cost.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PoC support for jsoo ocsigen/js_of_ocaml#1411

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you observe any negative performance impact of compression on the jsoo side?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't manage to build jsoo with trunk yet (opam switch + jsoo deps), I might try again later. Once this is resolved, we should be able measure the perf impact loading the in-browser toplevel, reading compressed cmis.

I've just tried to unmarshall some data marashaled using this PR in my 5.0.0 switch.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to run more test after pinning the right branch of ppxlib.
I didn't observe any negative perf impact while the size of the generated files was reduced by 25M (due to embedded cmi files)

@xavierleroy
Copy link
Copy Markdown
Contributor Author

I finally read the Zstd API documentation, and the API is actually quite reasonable. So I just pushed a commit that replaces Zlib by Zstd for compression and decompression of marshaled data. Compression is clearly faster, so much so that the time overhead of compressing .cmt files is now lost in measurement noise. More measurements are needed, of course.

@hhugo
Copy link
Copy Markdown
Contributor

hhugo commented Feb 13, 2023

I finally read the Zstd API documentation, and the API is actually quite reasonable. So I just pushed a commit that replaces Zlib by Zstd for compression and decompression of marshaled data. Compression is clearly faster, so much so that the time overhead of compressing .cmt files is now lost in measurement noise. More measurements are needed, of course.

For jsoo, I think we could support decompression (of zstd) only by relying on https://www.npmjs.com/package/fzstd.
This would allow to read compressed cmi files when using the online toplevel.

@kayceesrk
Copy link
Copy Markdown
Contributor

Testing shows a rare segmentation fault in tests/lib-marshal/intext_par.ml

We're observing the same failure in the CI in #12001 (comment). See https://github.com/ocaml/ocaml/actions/runs/4163285265/jobs/7203489175#step:6:5191.

@johnwhitington
Copy link
Copy Markdown
Contributor

johnwhitington commented Feb 14, 2023

Of course, the first reactions will be to question my choice of Zlib, instead of criticizing the overall design. I chose Zlib because it's available everywhere and I'm somewhat familiar with its API.

Another option is to vendor in to OCaml the MIT-licensed zlib replacement miniz.c https://github.com/richgel999/miniz which is a single C file, so compression would always be available. It has an optimised-for-speed compressor which is faster than zlib's.

(As an side-effect, this would allow CamlZip to be brought into the Standard Library for everyone to use, if that is considered desirable.)

@xavierleroy
Copy link
Copy Markdown
Contributor Author

Another option is to vendor in to OCaml the MIT-licensed zlib replacement miniz.c https://github.com/richgel999/miniz which is a single C file, so compression would always be available.

Good to know! Thanks for the pointer.

Speaking of license, the file miniz.c is weird: at the top there's a MIT license, and at the bottom it claims it's in the public domain ?

It has an optimised-for-speed compressor which is faster than zlib's.

Do you have an idea of it compares with zlib, speed-wise? I found https://code.google.com/archive/p/miniz/wikis/miniz_performance_comparison_v110.wiki but I cannot make sense of the numbers.

@xavierleroy
Copy link
Copy Markdown
Contributor Author

xavierleroy commented Feb 14, 2023

Concerning "vendoring" of C libraries inside the OCaml runtime system in general : it can be considered if the library is small enough, e.g. a single .c file and a single .h file are fine. However, there's still the question of maintenance and bug fixing, esp. when security holes are found in the original library.

@nojb
Copy link
Copy Markdown
Contributor

nojb commented Feb 14, 2023

Do you have an idea of it compares with zlib, speed-wise? I found https://code.google.com/archive/p/miniz/wikis/miniz_performance_comparison_v110.wiki but I cannot make sense of the numbers.

I think this page has lost some formatting; the version in https://web.archive.org/web/20150220064400/https://code.google.com/p/miniz/wiki/miniz_performance_comparison_v110 has the original formatting and is more understandable.

@johnwhitington
Copy link
Copy Markdown
Contributor

Another option is to vendor in to OCaml the MIT-licensed zlib replacement miniz.c https://github.com/richgel999/miniz which is a single C file, so compression would always be available.

Good to know! Thanks for the pointer.

Speaking of license, the file miniz.c is weird: at the top there's a MIT license, and at the bottom it claims it's in the public domain ?

That file is not the actual miniz.c. The actual built miniz.c is 7500 lines, not 650, and has only the MIT license at the top; nothing at the bottom. See the releases here: https://github.com/richgel999/miniz/releases

@adrien-n
Copy link
Copy Markdown
Contributor

Concerning "vendoring" of C libraries inside the OCaml runtime system in general : it can be considered if the library is small enough, e.g. a single .c file and a single .h file are fine. However, there's still the question of maintenance and bug fixing, esp. when security holes are found in the original library.

I consider that there are two intertwined questions: a) should this API be supported in a (much) wider scope than the original topic of compressing .cm* files? b) should an underlying C library be fully exposed?

I am in favor of making all of this as small as possible.

Marshal is unsafe. Reading untrusted marshaled data is a known security issue (I expect it can easily lead to code execution). As such, using a C library in that setting does not add any new concern. If this API is instead meant for general use, it adds all the known issues with C code. There is no middle-ground situation where some uses would introduce fewer concerns than others: limiting this to Marshal means no new issue and making it usable for anything else means the whole set of issues right away.

As for vendoring, I'm not sure which benefits it would bring. I don't think there are many places where zlib or another library can be used but cannot be obtained/installed. The main concerns we've had so far are mirage and jsoo but their issue is C code no matter where it is. Vendoring wouldn't help them. Moreover, and if I'm not mistaken, integrating such C libraries as static libraries will also pollute the symbol namespace, making it an additional concern.

By the way, exposing compression APIs is also a lot more work for relatively minor gains. Zstd is probably the compression library that we want the least to expose due to its frequent change and to the size of its API. This is better served by a dedicated library. If there are efficiency gains to be found with a more-integrated approach than what is available today (maybe by chaining libraries in C-land), this is probably better solved by adding the ability to do plumbing and data shuffling in a new way (that's really just an example) because sometime zstd is more appropriate but sometimes it's lz4, sometimes it's xz, sometimes an intermediate compression filter will do wonders (I've had a delta filter make everything ten times better). The list goes on.

NB: if you want to go the zlib route, you might want to look at zlib-ng (after checking that upstream is focused enough on API stability); for an idea of the performance changes, see https://www.megastormsystems.com/news/benchmarks-results-of-zlib-and-zlib-ng-running-on-some-amd-and-intel-cpus

I'm also wondering how this change will impact bootstrapping: without vendoring, the bootstrap compiler cannot support decompression but at the same time, I don't think we'd want to vendor zstd for that purpose because of how big it is (700KB for the .so on my machine). On a related note, zstd is C++ and this can have a noticeable effect on platform support and build requirements.

@xavierleroy
Copy link
Copy Markdown
Contributor Author

I just pushed a version of this PR where compression is also applied to .cmi files and to the debug info in .cmo and .cma files. All this data compresses well, and the impact on compilation times seems lost in the noise (it will need a better analysis later).

@xavierleroy
Copy link
Copy Markdown
Contributor Author

xavierleroy commented Feb 17, 2023

Replying to @adrien-n

I am in favor of making all of this as small as possible.

I generally agree! In particular, providing a compression API in the stdlib should be considered separately and later.

I'm also wondering how this change will impact bootstrapping

You really believe I didn't think of that? :-) The bootstrap bytecode executables boot/ocamlc and boot/ocamllex must not contain compressed marshaled data. That's the case in this PR and that's quite easy to ensure : the only marshaled data in these bytecode executables is the data segment (containing structured constants in particular), and I don't plan to apply compression to this data segment, as it is quite small in general.

If we wanted to compress bytecode data segments in the future, the stripdebug tool that is used to prepare the archival versions of boot/ocamlc and boot/ocamllex would then have to uncompress the data segments before archival, which is not particularly difficult.

The other marshaled data in bytecode executables is the debug information, which I have kept uncompressed so far. I now propose to compress debug info in .cmo / .cma files, but it may be preferable to keep bytecode executables 100% portable, including uncompressed debug info.

@xavierleroy
Copy link
Copy Markdown
Contributor Author

I think this page has lost some formatting; the version in https://web.archive.org/web/20150220064400/https://code.google.com/p/miniz/wiki/miniz_performance_comparison_v110 has the original formatting and is more understandable.

It is, indeed! Thanks! My quick reading is that miniz is slightly faster than zlib, but nothing like zstd (which is not on this page but is 10x faster for similar compression rate in my experience). Also, I'm getting bad vibes from the fact we have to go to archive.org to get readable documentation.

@xavierleroy xavierleroy marked this pull request as ready for review February 17, 2023 19:05
@xavierleroy
Copy link
Copy Markdown
Contributor Author

I just turned on the fasten seat belt sign marked this PR as ready for review, since I'm quite happy with the current design and overall performance. Thanks for the feedback received so far, and feel free to REVIEW !

Copy link
Copy Markdown
Member

@gasche gasche left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had a first quick look at the peripheral logic (not the main compression stuff).

5 and following
5 variable-length integers, in VLQ format (1 to 10 bytes each)
- length of compressed marshaled data
- length of uncompressed marshaled data
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: length of ..., in bytes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. Done in 507b0a9.

24 size in words when read on a 64-bit platform
The 3 numbers are 64 bits each, in big endian.

Header format for the "compressed" model:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it "10 to 55 bytes"? You give the size for the other formats; no big deal, but it's not completely obvious to compute it from the description.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is 10 to 55 bytes, indeed. Added as part of 507b0a9.

runtime/extern.c Outdated
len = storevlq(header + pos, s->obj_counter); pos += len;
len = storevlq(header + pos, s->size_32); pos += len;
len = storevlq(header + pos, s->size_64); pos += len;
CAMLassert(len < 64);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the assertion here, and I am uneasy about the overflow behavior of the storevlq function.

At this point len is the number of base-128 digits of the last field read. The check len < 64 on just this last length is odd.

At first I thought that maybe you meant to check that pos < MAX_INTEXT_HEADER_SIZE. But then this check would also be odd, because only runs that perform out-of-bound writes would fail the test -- so in particular the compiler may erase it.

I would feel more at ease if the storevlq and readvlq functions took as extra parameter the "end" of the input buffer, and abort if they reach the end while looking for the end of the digit.
(For storevlq this is arguably academic as we can statically bound the number of base-128 digits needed for an uintnat on today's machines.)

Copy link
Copy Markdown
Contributor Author

@xavierleroy xavierleroy Feb 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assertion was left over from an earlier design. Currently, it is wrong (it should be about pos, not len) and useless (as you noticed), so I removed it in 754b1a2.

For the foreseeable future, uintnat is at most 64 bits, so storevlq is guaranteed to write at most 10 bytes (since 9*7 < 64 <= 10*7). I don't think we need any more bounds checking.

readvlq can be abused by artificially-padded input 0x80 ... 0x80 <the actual number>. However, the whole unmarshaler can be abused a zillion different ways by malicious input, so what the heck...

Besides, if we were to do bounds checking in intern.c, we'd have checks in read8u first, and then readvlq would automatically be checked.

CAMLassert (ofs < s->obj_counter);
CAMLassert (s->intern_obj_table != NULL);
v = s->intern_obj_table[s->obj_counter - ofs];
v = s->intern_obj_table[ofs];
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this logic and found it correct, including the assert changes. (But confusing; I wish we could have a pos variable instead of changing the meaning of "offset" in the middle.)

/* #4056: using absolute references for shared objects improves
compressibility. */
uintnat d = s->extern_flags & COMPRESSED ? pos : s->obj_counter - pos;
extern_shared_reference(s, d);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have mixed feeling about using conditional logic here. It makes the code more complex, and we lose the property that the only difference between both payloads is compression. Are we sure that it is worth it? (Are the space saving in the uncompressed case substantial enough to justify relative offsets, and the space saving in the compressed case substantial enough to justify absolute offsets?)

Copy link
Copy Markdown
Contributor Author

@xavierleroy xavierleroy Feb 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned in 6f0b636, switching to absolute references reduced the size of a big .cmt file (probably camlinternalFormat.cmt) by 15% on top of the savings obtained by zlib compression. I haven't re-done the measurements since switching to zstd. But it's clear that the insight in #4056 is correct and that the compressed format must use absolute references.

On the other hand, you don't change the existing uncompressed formats lightly. Switching to absolute references there would mean new magic numbers, inability to read persistent data marshaled with older OCaml versions, and perhaps some "fun" in the bootstrapping process. Or, if you want backward compatibility, you'd need to support both absolute and relative references, with different magic numbers, and the "conditional logic" you dislike would be there again. I don't even want to know which of relative or absolute references perform better without compression, because switching to absolute references for the uncompressed formats is not on my roadmap.

configure.ac Outdated
## ZSTD compression library

AS_IF([test x"$with_zstd" = "xyes"],
AS_IF([pkg-config --atleast-version 1.4 libzstd 2>/dev/null],
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noting that I think this adds a new dependency on pkg-config for the OCaml compiler build, but that I think it's probably fine. Although, at a glance on most common distros zstd is pretty standalone, and so just using AC_SEARCH_LIBS might be sufficient and avoid this dependency.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. I'm not fixated on using pkg-config, and the quick-and-dirty test above just fails silently if pkg-config is not available. Moreover, the test will certainly have to be reworked to handle the Windows ports.

Although, at a glance on most common distros zstd is pretty standalone

Linux distros, yes. For macOS, zstd is in bizarre Homebrew or MacPorts locations, and I don't know of any better way to find those locations than pkg-config.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, because the zstd streaming API is in constant flux, we need to check for version >= 1.4, version 1.3 (as found in Ubuntu 18.04 LTS for instance) doesn't work. Again, pkg-config makes it trivial to do this check, but AC_SEARCH_LIBS will need a bit more work.

Copy link
Copy Markdown
Contributor Author

@xavierleroy xavierleroy Feb 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I pushed an improved zstd detection code: it tries pkg-config first, and if it fails it then uses AC_CHECK_LIBS and AC_CHECK_DECL to see if zlib is in the standard location and defines the functions we need. On our CI most of the machines have pkg-config, and those that don't have no zstd library or an outdated version, so the new code is not fully exercised.

@xavierleroy
Copy link
Copy Markdown
Contributor Author

there might be some low-hanging fruit in '.opam' as well, there is a lot duplicate or unnecessary data

It's quite likely, but this is not relevant to this PR. Can you move this comment to https://github.com/ocaml/opam/ ?

@xavierleroy
Copy link
Copy Markdown
Contributor Author

I'm still trying to gather performance data. For a build and installation of the core OCaml system (make world.opt && make install):

  • total build time increases by 1%
  • the size of the installed lib/ directory decreases by 36%
  • .cmi files decrease by 58%
  • .cmt / .cmti files decrease by 64%
  • .cmo / .cma files decrease by 51% (because of compressed debug info)

I think the benefits of compression are clear, and there are no major downsides so far. So, please REVIEW this PR. Thanks.

hhugo added a commit to ocsigen/js_of_ocaml that referenced this pull request Feb 27, 2023
@xavierleroy xavierleroy deleted the compressed-marshaling branch February 28, 2023 06:52
@hhugo
Copy link
Copy Markdown
Contributor

hhugo commented Feb 28, 2023

(FYI, zstd support (decompression only) has been merged into jsoo)

@poechsel
Copy link
Copy Markdown
Contributor

poechsel commented Feb 28, 2023

Some numbers from testing this PR on a substantial subset of Jane Street's code base using Flambda1.

Building while compression artifacts took 2h41min versus 2h37min for a build without compression. These numbers are within noise meaning that there wasn't any noticeable slowdown caused by this PR.

File type Compressed size Uncompressed size
cmt 21.5 GB 61.5 GB
cmx 5.2 GB 10.7 GB
cmi 6.4 GB 9.7 GB
cmo 0.6 GB 1.8 GB

@xavierleroy
Copy link
Copy Markdown
Contributor Author

Thanks for the measurements. I don't understand the second line of the table: .cmx files are not compressed in this PR, and they are generally not that big either.

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Feb 28, 2023 via email

@poechsel
Copy link
Copy Markdown
Contributor

I was curious about .cmx so I decided to slightly tweaked the PR and collect the corresponding sizes

@lthls
Copy link
Copy Markdown
Contributor

lthls commented Feb 28, 2023

Regarding the size of cmx files, I assume that Jane Street tends to use flambda with -O3, which can produce significantly bigger cmx files. For instance, on my 4.14 opam switches, the closure version of camlinternalFormat.cmx is 8509 bytes while the flambda version is 528565 bytes (the typical ratio seems to be lower, with a few cases where the flambda version is smaller).
Given the numbers reported by @poechsel, I think it would make sense to apply compression on cmx files too, at least on optimisation settings known to generate big cmx files.

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Feb 28, 2023 via email

@nojb
Copy link
Copy Markdown
Contributor

nojb commented Feb 28, 2023

Just to say, if you want to keep it in this PR, I'm fine.

Hello Sébastien, the PR has already been merged :) Cheers!

@shindere
Copy link
Copy Markdown
Contributor

shindere commented Mar 1, 2023 via email

xavierleroy pushed a commit that referenced this pull request Mar 4, 2023
This is a GC issue that was introduced along with support for compression (#12006).
It fixes most of the occurrences of issue #12056.
@UnixJunkie
Copy link
Copy Markdown
Contributor

Just a comment about the interface: it might be nice if users can specify the compression level they want.
level 0: no compression (the default)
1..9: the usual meaning for gzip and friends.

Last time I read about fast compressors/decompressors, lz4 and lzo came up.
Maybe they could be considered as alternative compressors, in case users want marshaling/unmarshalling to still be very fast.

@hhugo
Copy link
Copy Markdown
Contributor

hhugo commented Apr 12, 2023

Last time I read about fast compressors/decompressors, lz4 and lzo came up. Maybe they could be considered as alternative compressors, in case users want marshaling/unmarshalling to still be very fast.

The final implementation uses zstd

sim642 added a commit to sim642/lwt that referenced this pull request Jul 13, 2023
The Marshal header size was changed in ocaml/ocaml#12006.
raphael-proust pushed a commit to sim642/lwt that referenced this pull request Jul 17, 2023
The Marshal header size was changed in ocaml/ocaml#12006.
xavierleroy added a commit to xavierleroy/ocaml that referenced this pull request Oct 2, 2023
- Remove compressed marshaling support from runtime/{extern.c,intern.c}
- Remove the `Marshal.Compression` flag
- Remove its uses in the compiler

runtime/extern.c still accepts the old Compression flag and just ignores it.
This avoids a bootstrap at this point.  The support will be removed later.
xavierleroy added a commit to xavierleroy/ocaml that referenced this pull request Nov 4, 2023
- Remove compressed marshaling support from runtime/{extern.c,intern.c}
- Remove the `Marshal.Compression` flag
- Remove its uses in the compiler

runtime/extern.c still accepts the old Compression flag and just ignores it.
This avoids a bootstrap at this point.  The support will be removed later.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.