Click here to Skip to main content
Click here to Skip to main content

QuickLZ Pure C# Port

, 23 Dec 2006
Rate this:
Please Sign up or sign in to vote.
This article describes a C# port of the new QuickLZ compression algorithm


It seems there is no end to the porting of good C/C++ algorithms to .NET, and so here comes another one.  This algorithm comes courtesy of Lasse Mikkel Reinhold, and is called QuickLZ.

You can read more about QuickLZ at the website, however I will outline some of the aspects of QuickLZ as I go.

What IS QuickLZ?

It comes as no surprise if you haven't heard of QuickLZ, it is a new compression algorithm particularily well suited for psuedo streaming (packet compression).  It was originally released early November 2006, and updated to 1.10 later that month.  The porting is based on 1.10, which as of the writing of this article boasts an incredible 20-30% improvement over other well known algorithms such as LZO1X and LZF.  Complete benchmark information on the C implementation can be found at the above linked website, however here is an overall assessment:

QuickLZ 1.10 LZO 1X 2.02 LZP-1 LZF 1.6 ZLIB-1 1.2.3
Compressed Size 61.0% 60.2% 59.9% 60.7% 46.4%
Compression MB/Sec 148 81.8 60.4 60.9 7.45
Decompression MB/Sec 380 307 89.3 198 120

If you are reading this article, there is a chance you also read my article including a port of MiniLZO.  Based on the numbers here, it's easy to see why LZO was my previous choice.  However, QuickLZ is now 19.2% faster on average than LZO on decompression, and an astonishing 44.7% faster on compression.  And approximately 0.8% less efficient on final compression.  This large improvement by QuickLZ made it a prime candidate for porting to .NET and while it doesn't totally replace my minilzo port, it does give a better alternative for those who don't need the LZO format.

Things To Remember

While I was porting the code, which was incredibly clear and easy to port, I noticed a number of areas for improvement.  This specific iteration of the port is a first revision and is based on the optimizations for better ratio working with data > 100kb in size.  A more refined and "Minimalistic" version of the algorithm is possible, and may come as a complimentary article specifically regarding packet compression.  Meanwhile, this class serves as a general use class for both files and packets that should outperform other managed options.  I have not profiled this port to C# whatsoever, and I know that for simplicity of the public interface there is some additional overhead.  If you must make the Unsafe versions public and use them, make sure you understand the code before you cry to me about it not working Smile | :)

A comment made during the port of MiniLZO was how the original uncompressed size was not easy to attain from the compressed data, so prepending the size was requested but would ultimately break compatibility with the original LZO1X implementation.  Based on the standard implementation of QuickLZ, I have provided a public method to find the original uncompressed size quickly and painlessly.

Without Further Ado...

So let's look at how to use the safe(?) interface to the implementation.  All source examples are psuedo, and assume knowledge of basic C# operations.

byte[] data = File.ReadAllBytes("...");
byte[] compressed = QuickLZ.Compress(data, 0, (UInt32)data.Length);

This little snippet shows the basic idea of obtaining some data, in this case loading it from a file, and passing it into the compression method, which takes a Byte[] for the buffer to read from, a starting offset within the buffer to start at, and the length from the starting point to include in compression.  This is useful if you need to work with a packet, where packet headers may not be included in the compression/decompression routines.  The return value is an exact size Byte[] stripped of the extra scratch space allocated during compression.  It should be noted that QuickLZ imposes a requirement that during compression the destination buffer is required to be the length of the original data plus an additional 36000 bytes for temporary workspace.  This implementation copies the temporary destination buffer into an exact size buffer for final return.

UInt32 size = QuickLZ.GetDecompressedSize(data, 0);

This little snippet here shows how you can manually obtain the size of the compressed data out of the Byte[] directly.  The second argument, again, reflects where the actual compressed data headers begin.  It should be noted that this method is never really needed, but is provided for completion.

byte[] decompressed = QuickLZ.Decompress(compressed, 0);

This last snippet is fairly self explanitory by this point. It takes a Byte[] for the compressed data, and a starting point once again.  It returns an exact size buffer like Compress, however does not have the added overhead of copying from a temporary destination, as the exact uncompressed size is known ahead of time, which is why the GetDecompressedSize method is not required.


QuickLZ as a new alternative to the compression scene and seems to currently be the fastest within this category of compression.  I hope you will find this port useful, and as always if you find any bugs or bottlenecks that degrade performance please let me know.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Web Developer
Canada Canada
Short and simple, I'm a self contracted programmer, my strongest programming skills are in C/C++ and C#/.NET. I have a nack for porting C algorithms to C#.

Comments and Discussions

GeneralRe: Interesting PinmemberAstaelan25-Dec-06 6:42 
AnswerRe: Interesting PinmemberStanislav Panasik25-Dec-06 7:06 
GeneralRe: Interesting PinmemberAstaelan25-Dec-06 7:19 
GeneralRe: Interesting PinmemberStanislav Panasik25-Dec-06 23:22 
GeneralRe: Interesting PinmemberBehind The Scene13-Jan-07 18:20 
GeneralRe: Interesting Pinmemberrlasse25-Dec-06 9:36 
GeneralRe: Interesting PinmemberAstaelan25-Dec-06 17:21 
GeneralRe: Interesting PinmemberAstaelan25-Dec-06 6:39 
Okay, lacking any formal knowledge of the algorithm, yes, it is possible that the current implementation may not compress anything. To clarify, I spoke with the original author of the algorithm about downsides of the algorithm, and one of them is rather significant... And here's why:
Within the code, is an optimization to find sequences upto 2 >> 11 bytes. That's 4096 byte sequences, of course it's unlikely you will ever find a sequence this long. As a result of how the sequence matching performs so fast, is an obscure issue as to why some times files may not compress well. Based on the algorithm in it's current state, if you only had say, 5000 bytes of data to compress, the actual result worst case, could be that only 5000-4096 bytes get compressed, as the last sequence of bytes remains uncompressed for faster processing (talk to the author if you wish to know more).
Also, it should be noticed that yes, PKZIp and WinRAR are fully expected to get better compression ratio's, but they also take about 100 times longer to compress and decompress data. This algorithm is most suited to streaming compression. However, in it's current form, it isn't absolutely streamlined for packet compression and so there are some cases where QuickLZ may seem like it's doing nothing. The algorithm needs to be adjusted, but doing so would break compatibility with other QuickLZ implementations, so this needs to be realized before hacking it apart to write a more efficient class.
It shold be realized that any file already compressed is going to get little to no compression from QuickLZ (ie, divx files, and other previously compressed formats).
To give you an idea of the compression, I took a very simple, relatively small EXE (Putty.exe) which had an original size of: 412 KB (421,888 bytes)
Compressed with QuickLZ got this down to around: 292 KB (299,008 bytes)
It's a modest saving, considering the code is still optimized for larger files, but it's still looking at about a 43% savings.
Should also note, that with a file which, worst case, cannot be compressed by QuickLZ, the output will be slightly larger than the original size, due to the compression headers still existing on uncompressed results (more accurately, it marks one of the headers as compressed or not so you don't need to manage whether files are compressed or not before decompressing).
By slightly larger, read: 8 * 4 bytes (8 headers, a few unused and reserved). I have discussed modification of the algorithm to suit packet compression, and may be soon to follow, however I think I am going to port quick32.exe to profile the speed difference between .NET and the original C code to see how much is lost going from C to unsafe C#.
I appreciate that the result may not have been what you expected, please continue your testing and let me know if you find any actual malfunction of the code... You can use the existing quick32.exe to confirm both compression and decompression work whether the ported code made the compression or not.
As far as unsafe code goes, there are a few obscure limitations (IE, can't modify a fixed pointer directly, gotta make a new pointer and adjust the assignment). Otherwise, unsafe C# is a lot like working with pointers in C, with a little more control over bounds checking with checked/unchecked (which I have no reason to use in this implementation, so the code is pretty close to a 1:1 port of the original C).
Thanks to all for your interest in the algorithm, nice to get positive feedback.
GeneralRe: Interesting PinmemberAstaelan25-Dec-06 6:51 
GeneralRe: Interesting PinmemberBehind The Scene13-Jan-07 18:27 
GeneralRe: Interesting PinmemberA Nash3-Feb-07 2:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141022.2 | Last Updated 23 Dec 2006
Article Copyright 2006 by Astaelan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid