Recent submissions

Comment · 1 month ago
Hi Ivan,

Please send me an e-mail! Perhaps we can figure something out.

Comment · 1 month ago
Tool author here. Sure, out of all bait in this thread I will bite this one. Curiously, it seems like Konstantinos has opened this ticket, i.e. https://github.com/iczelia/bzip3/issues/177, and open-sourced his algorithm here -- https://codeberg.org/kagiannis/gdcc-2021. As the allegation is very serious, I will also copy the edited version of this response to my website.

I have not seen his tool before, or even was aware of it. However, once you take a closer look, you notice that these two tools could not be more dissimilar. Agiannis' compressor uses a compact context representation to group bytes, followed by RLE and prefix coding. Bzip3 combines repetition removal (here via a run-length code -- prior to the BWT -- and LZP of Charles Bloom), a full Burrows–Wheeler transform, and a richer (thus slower) statistical arithmetic coder. The use of RLE for post-coding the BWT output dates as far back to Julian Seward, perhaps even further. The RLE and LZP are applied before the Burrows-Wheeler transform (as opposed to the implementation in `text', which makes a big difference). Bzip3 uses a proper SAIS library for the forward and backward transforms. Konstantinos' entropy coder seems to use FPC (bytewise prefix codes over adaptively selected subblocks), bzip3 uses an idea similar to this of bcm, which itself descends from Mahoney and ancient work of JS Vitter on arihtmetic coding, where a bitwise arihtmetic coder is input mixed probability estimates from exponential-moving averages with probability refinement.

You are welcome to conduct your own analysis, but this is the gist of it -- perhaps Konstantinos has convinced himself that he had invented run-length coding?

Comment · 1 month ago
Tool author here. bzip2 also has this clause, in fact it has been lifted from its dist tarball README verbatim. So does lzma, xz, or in practice any open source program that you use.
Comment · 1 month ago
I use the PAQ terminology as it is likely to be familiar to other compression experts. However, the lineage to PAQ is very, very limited, and many other compressors also re-use its common ideas.
Comment · 1 year ago
Hi, tool author here.

Huffman coding is a static minimum-redundancy code. What this means is that it finds an optimal assignment of bit sequences to letters in the input alphabet (commonly US-ASCII or extensions). This however means that Huffman coding can not exploit redundancies that stem from the concrete sequence of characters. For example, you could easily predict that an `e` comes after `Th`, but Huffman coding can not know that.

Hence after applying the Burrows-Wheeler transform you need to have some sort of a higher-order transform (i.e. a transform that considers more than just individual bytes) which somehow reaps from the changed distribution of the result of the algorithm. But we will get to that in a second.

The joke here is that the Burrows-Wheeler transform is closely related to suffix trees and suffix arrays, which are often used in bioinformatics and HPC for full-text search. If you wanted to find a pattern of length `p` in a text of length `n`, if you already have a suffix tree of the original text, the search is linear in the length /of the pattern/ - i.e. O(p). The suffix tree stores all suffixes of a string in a compressed manner (i.e. it has a linear space overhead, approximately O(20n) as given by Gusfield, D. (1997). Algorithms on Strings, Trees and Sequences: Computer Science and Computational Biology. Cambridge University Press), so you can search for a word in it by simply traversing from the root node to an internal or leaf node by following a sequence of bytes that comprise the word.

As such, a suffix tree (and equivalently suffix array and the BWT, which is trivially computed from a suffix array) form something which can be thought of as a static PPM model. Notably real world implementations of PPM use suffix trees as a part of their main storage data structure (e.g. PPMd). What this all means is that given a suffix tree, we can very cheaply give the probability distribution for the next byte that follows a given fixed-order sequence of bytes. This is nice, because then e.g. an order-2 predictor would be able to tell that `Th` is followed by `e` once enough data has been gathered.

As you can probably guess, the more preceding bytes you know, the better will be your estimate for what is the most likely next byte. But the larger your context, the more expensive the searches and computations become due to pointer chasing in the suffix tree.

So how do we remedy this? We notice that the Burrows-Wheeler transform essentially clusters similar contexts together, meaning that a low order predictor (= faster, simpler) on BWT compresses as well as a high order predictor (= slow, complicated) on the original data, at the cost of an extra transformation. This is viable, because the Burrows-Wheeler transform can be quickly computed and there have been recent advancements in running it on the GPU. So what this means is that bzip3 uses BWT + a low order predictor with an arithmetic coder to encode the bytes, meaning that it can make use of high order statistics for compression and performs comparably at a faster speed.

Comment · 1 year ago
Hi, tool author here!

Thank you for your benchmark!

As you may be aware, different compression tools fill in different data type niches. In particular, less specialised statistical methods (bzip2, bzip3, PPMd) generally perform poorly on vaguely defined binary data due to unnatural distribution of the underlying data that at least in bzip3's case does not lend well to suffix sorting.

Conversely, Lempel-Ziv methods usually perform suboptimally on vaguely defined "textual data" due to the fact that the future stages of compression that involve entropy coding can not make good use of the information encoded by match offsets while maintaining fast decompression performance - it's a long story that I could definitely go into detail about if you'd like, but I want to keep this reply short.

All things considered, data compression is more of an art than science, trying to fit in an acceptable spot on the time to compression ratio curve. I created bzip2 as an improvement to the original algorithm, hoping that we can replace some uses of it with a more modern and worthwhile technology as of 2022. I have included benchmarks against LZMA, zstandard, etc. mostly as a formality; in reality if you were to choose a compression method it'd be very dependent on what exactly you're trying to compress, but my personal stance is that bzip3 would likely be strictly better than bzip2 in all of them.

bzip3 usually operates on bigger block sizes, up to 16 times bigger than bzip2. additionally, bzip3 supports parallel compression/decompression out of the box. for fairness, the benchmarks have been performed using single thread mode, but they aren't quite as fair towards bzip3 itself, as it uses a way bigger block size. what bzip3 aims to be is a replacement for bzip2 on modern hardware. what used to not be viable decades ago (arithmetic coding, context mixing, SAIS algorithms for BWT construction) became viable nowadays, as CPU Frequencies don't tend to change, while cache and RAM keep getting bigger and faster.

Comment · 1 year ago
Comment · 1 year ago
Hi! Tool author here.

Almost every single open source compression tool contains a clause like this. For example, the one in the README that you see has been directly lifted from the bzip2 README. Almost all open source projects come with such a no-warranty scheme. 7-Zip, zstandard, xz-utils, etc; as exemplified by a quote from the license text of the MIT license:

> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

If you were willing to sign a commercial support contract with me on terms that we negotiated, I would be willing to provide you warranty.

If you were not aware, this is essentially the business model of WinRAR. The reason why tools like 7-Zip are not used by the public sector or companies (at least here) is that they provide no warranty in case of data loss. However, if you actually buy WinRAR, then you can hold them liable for damage to your archives. The "infinite 40 day trial" of WinRAR does not entitle you to compensation for damages and thus corporate entities and public entities have to buy WinRAR licenses. WinRAR has never cared about personal customers.

In general, having to cope with mild reliability of software is what you have to live with - you already get more than you paid for. Not to say that my tool is unreliable - I put a lot of effort into it, but it would put you in bad light to complain about something that you generously received for free :).

Comment · 2 years ago
they're looking for a compressor that can do more than 200MB/s on a 10mW machine (that's including radio, so it has to run on a CPU clocked like original 8086) and yield 200x size improvement. speaking from the perspective of a data compression person, this is completely unrealistic. the best statistical models that i have on hand yield ~7x compression ratio after some tweaking, but they won't run under these constraints.
Comment · 2 years ago
Yeah, I can kind of relate, actually! Now I am 19, have a job and attend a somewhat demanding university, outside of (more useful?) real world research I am currently doing. I wrote the code when i was c.a. 15 - 16, I could definitely improve upon my Lisp - it's within my range of current capabilities, but I would not have the motivation to :-).
Comment · 2 years ago
Thank you for the kind comments! Unfortunately, the BLC interpreter is much slower than MalbolgeLISP, even when using fast20 (with a lot of optimisations coined by dzaima). My memory is a bit hazy, but one of the main roadblocks that made BLC barely feasible was the (comparably...) large ROM that it requires. Executing simple instructions in Malbolge generally incurs similar kind of latency as the more complicated ones, hence to slightly improve performance (not nearly enough - notice that the Lisp still has a "loading bar"!), I have decided that a complicated set of primitives for a language to run on top of Malbolge would be a necessity. This is further supported by some issues with Malbolge regarding the code placement and loading a code image, previously solved by e.g. Matthias Lutter (and subsequently used in my Malbolge code) in his very simple (and if I remember correctly, slower than the LISP) brainfuck interpreter. Another venue to explore is University of Nagoya's Malbolge toolchain, which is functional and probably a very good starting point - https://www.trs.css.i.nagoya-u.ac.jp/projects/Malbolge/. Once you jump this hoop, you can now start synthesizing basic operations using Nop/MovD;Jmp flags and Malbolge instructions - e.g. have the interpreter code set a flag, jump to a single routine which does a complex operation; based on the state of all flags the routine can then decide where to return. The more complex the instruction set, the more complex the primitive operations, and hence the better is the performance you may get. Assuming that you do not exactly want to write an optimising compiler in Malbolge which does something akin to mop-fusion of RISC CPUs, of course :-). Most of MalbolgeLisp was written when I was 16, then I have moved onto KamilaLisp (Java), as the codebase written in Malbolge grew in size and became more annoying to add interesting features to. Unfortunately due to job and university requirements I no longer have the time (and motivation) for these kinds of amusement.

As for the compression: probably an artifact of a bigger block size and a closer-to-optimal entropy coding stage in bzip3 (simple model + binary arithmetic coding; fast suffix sorting due to research of Ilya Grebnov) vs bzip2's suboptimal implementation of what could have been Package-Merge that currently assigns excessively long Huffman codes (as I discovered while doing research for my data compression book); also probably the RLEs everywhere that Seward considers a mistake, small BWT blocks, etc. You could try the tool https://pastebin.com/6DUKs4q9, which eliminates the redundancy associated with the Malbolge encoding (which bzip3 kind of catches on without any preprocessing, while bzip2 not entirely) and drastically improves performance of all other compressors:

    % ./a d <blc.mb >blc.n
    % bzip3 -vfb50 blc.n
      blc.n:  48175489 -> 647179 bytes, 1.34%, 0.11 bpb
    % bzip3 -vfb50 blc.mb
      blc.mb: 48175489 -> 1025582 bytes, 2.13%, 0.17 bpb
Comment · 3 years ago
hi, most of the code in my repository has to work around various C problems (e.g. no generics), so match32 and match64 are the same functions that work on differently sized buffers - if I had generics and RAII, the diffing and patching source code would have been comparable in size to your project.

I also don't see robust error handling in your code, which usually costs lines of code (especially in C) too.

The difference in delta technique is certainly not negligible, as my code still uses Colin Percival's algorithm, while you seem to have settled on something else. It's also important to point out that being "better than xdelta" means pretty much the same as "having more than nothing", because xdelta has already been superseded 20 years ago by bsdiff[1], which in turn would ideally be superseded by my project.

  [1]: https://www.daemonology.net/bsdiff/
Comment · 3 years ago
I'm sharing a tool that I have been working on in hopes that someone finds it useful. The tool serves the purpose of binary patching in game updates and personal incremental backups. Thanks to a different SA-IS algorithm and parallel compression of blocks, the diffing and patching is considerably faster compared to bsdiff or alternatives. This makes binary patching, in many cases, a viable option.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton