<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blosc Home Page  (Posts about blosc2 features performance)</title><link>https://blosc.org/</link><description></description><atom:link href="https://blosc.org/categories/blosc2-features-performance.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:blosc@blosc.org"&gt;The Blosc Developers&lt;/a&gt; </copyright><lastBuildDate>Sun, 19 Jul 2026 11:09:13 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>New features in Python-Blosc2</title><link>https://blosc.org/posts/python-blosc2-improvements/</link><dc:creator>Marta Iborra, Francesc Alted</dc:creator><description>&lt;p&gt;The Blosc Development Team is happy to announce that the latest version of &lt;a class="reference external" href="https://github.com/Blosc/python-blosc2"&gt;Python-Blosc2 0.4&lt;/a&gt;.  It comes with new and exciting features, like a handier way of setting, expanding and getting the data and metadata from a super-chunk (&lt;cite&gt;SChunk&lt;/cite&gt;) instance.  Contrarily to chunks, a super-chunk can update and resize the data that it containes, supports user metadata, and it does not have the 2 GB storage limitation.&lt;/p&gt;
&lt;p&gt;Additionally, you can now convert now a &lt;cite&gt;SChunk&lt;/cite&gt; into a contiguous, serialized buffer (aka &lt;a class="reference external" href="https://github.com/Blosc/c-blosc2/blob/main/README_CFRAME_FORMAT.rst"&gt;cframe&lt;/a&gt;) and vice-versa; as a bonus, this serialization process also works with a NumPy array at a blazing speed.&lt;/p&gt;
&lt;p&gt;Continue reading for knowing the new features a bit more in depth.&lt;/p&gt;
&lt;section id="retrieve-data-with-getitem-and-get-slice"&gt;
&lt;h2&gt;Retrieve data with &lt;cite&gt;__getitem__&lt;/cite&gt; and &lt;cite&gt;get_slice&lt;/cite&gt;&lt;/h2&gt;
&lt;p&gt;The most general way to store data in Python-Blosc2 is through a &lt;cite&gt;SChunk&lt;/cite&gt; (super-chunk) object. Here the data is split into chunks of the same size. So until now, the only way of working with it was chunk by chunk (see &lt;a class="reference external" href="https://www.blosc.org/python-blosc2/getting_started/tutorials/07.schunk-basics.html"&gt;tutorial&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;With the new version, you can get general data slices with the handy &lt;cite&gt;__getitem__()&lt;/cite&gt; method without having to mess with chunks manually.  The only inconvenience is that this returns a bytes object, which is difficult to read by humans.  To overcome this, we have also implemented the &lt;cite&gt;get_slice()&lt;/cite&gt; method; it comes with two optional params: &lt;cite&gt;start&lt;/cite&gt; and &lt;cite&gt;stop&lt;/cite&gt; for selecting the slice you are interested in.  Also, you can pass to &lt;cite&gt;out&lt;/cite&gt; any Python object supporting the &lt;a class="reference external" href="http://jakevdp.github.io/blog/2014/05/05/introduction-to-the-python-buffer-protocol/"&gt;Buffer Protocol&lt;/a&gt; and it will be filled with the data slice.  One common example is to pass a NumPy array in the &lt;cite&gt;out&lt;/cite&gt; argument:&lt;/p&gt;
&lt;pre class="literal-block"&gt;out_slice = numpy.empty(chunksize * nchunks, dtype=numpy.int32)
schunk.get_slice(out=out_slice)&lt;/pre&gt;
&lt;p&gt;We have now the &lt;cite&gt;out_slice&lt;/cite&gt; NumPy array filled with the &lt;cite&gt;schunk&lt;/cite&gt; data.  Easy and effective.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="set-data-with-setitem"&gt;
&lt;h2&gt;Set data with &lt;cite&gt;__setitem__&lt;/cite&gt;&lt;/h2&gt;
&lt;p&gt;Similarly, if we would like to set data, we had different ways of doing it, e.g. with the &lt;cite&gt;update_chunk()&lt;/cite&gt; or the &lt;cite&gt;update_data()&lt;/cite&gt; methods. But those work, again, chunk by chunk, which was a bummer. That's why we also implemented the convenient &lt;cite&gt;__setitem__()&lt;/cite&gt; method.  In a similar way to the &lt;cite&gt;get_slice()&lt;/cite&gt; method, the value to be set can be any Python object supporting the Buffer Protocol. In addition, this method is very flexible because it not only can set the data of an already existing slice of the SChunk, but it also can expand (and update at the same time) it.&lt;/p&gt;
&lt;p&gt;To do so, the &lt;cite&gt;stop&lt;/cite&gt; param will set the new number of items in SChunk:&lt;/p&gt;
&lt;pre class="literal-block"&gt;start = schunk_nelems - 123
stop = start + new_value.size   # new number of items
schunk[start:stop] = new_value&lt;/pre&gt;
&lt;p&gt;In the code above, the data between &lt;cite&gt;start&lt;/cite&gt; and the SChunk current size will be updated and then, the data between the previous SChunk &lt;cite&gt;size&lt;/cite&gt; and the new &lt;cite&gt;stop&lt;/cite&gt; will be appended automatically for you.  This is very handy indeed (note that the &lt;cite&gt;step&lt;/cite&gt; parameter is not yet supported though).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="serialize-schunk-from-to-a-contiguous-compressed-buffer"&gt;
&lt;h2&gt;Serialize SChunk from/to a contiguous compressed buffer&lt;/h2&gt;
&lt;p&gt;Super-chunks can be serialized in two slightly different format frames: contiguous and sparse.  A contiguous frame (aka &lt;a class="reference external" href="https://github.com/Blosc/c-blosc2/blob/main/README_CFRAME_FORMAT.rst"&gt;cframe&lt;/a&gt;) serializes the whole super-chunk data and metadata into a sequential buffer, whereas the sparse frame (aka &lt;a class="reference external" href="https://github.com/Blosc/c-blosc2/blob/main/README_SFRAME_FORMAT.rst"&gt;sframe&lt;/a&gt;) uses a contiguous frame for metadata and the data is stored separately in so-called &lt;a class="reference external" href="https://github.com/Blosc/c-blosc2/blob/main/README_CHUNK_FORMAT.rst"&gt;chunks&lt;/a&gt;. Here it is how they look like:&lt;/p&gt;
&lt;img alt="Contiguous and sparse frames" class="align-center" src="https://blosc.org/images/python-blosc2-improvements/frame-blosc2.png"&gt;
&lt;p&gt;The contiguous and sparse formats come with its own pros and cons.  A contiguous frame is ideal for transmitting / storing data as a whole buffer / file, while the sparse one is better suited to act as a store while a super-chunk is being built.&lt;/p&gt;
&lt;p&gt;In this new version of Python-Blosc2 we have added a method to convert from a SChunk to a contiguous, serialized buffer:&lt;/p&gt;
&lt;pre class="literal-block"&gt;buf = schunk.to_cframe()&lt;/pre&gt;
&lt;p&gt;as well as a function to build back a &lt;cite&gt;SChunk&lt;/cite&gt; instance from that buffer:&lt;/p&gt;
&lt;pre class="literal-block"&gt;schunk = schunk_from_cframe(buf)&lt;/pre&gt;
&lt;p&gt;This allows for a nice way to serialize / deserialize super-chunks for transmission / storage purposes.  Also, and for performance reasons, and for reducing memory usage to a maximum, these functions avoid copies as much as possible.  For example, the &lt;a class="reference external" href="https://www.blosc.org/python-blosc2/reference/autofiles/utils/blosc2.schunk_from_cframe.html"&gt;schunk_from_cframe&lt;/a&gt; function can build a &lt;cite&gt;SChunk&lt;/cite&gt; instance without copying the data in &lt;cite&gt;cframe&lt;/cite&gt;.  Such a capability makes the use of cframes very desirable whenever you have to transmit and re-create data from one machine to another in a very efficient way.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="serializing-numpy-arrays"&gt;
&lt;h2&gt;Serializing NumPy arrays&lt;/h2&gt;
&lt;p&gt;Last but not least, you can also serialize NumPy arrays with the new pair of functions &lt;a class="reference external" href="https://www.blosc.org/python-blosc2/reference/autofiles/top_level/blosc2.pack_array2.html"&gt;pack_array2()&lt;/a&gt; / &lt;a class="reference external" href="https://www.blosc.org/python-blosc2/reference/autofiles/top_level/blosc2.unpack_array2.html"&gt;unpack_array2()&lt;/a&gt;. Although you could already do this with the existing &lt;a class="reference external" href="https://www.blosc.org/python-blosc2/reference/autofiles/top_level/blosc2.pack_array.html"&gt;pack_array()&lt;/a&gt; / &lt;a class="reference external" href="https://www.blosc.org/python-blosc2/reference/autofiles/top_level/blosc2.unpack_array.html"&gt;unpack_array()&lt;/a&gt; functions, the new ones are much faster and do not have the 2 GB size limitation.
To prove this, let's see its performance by looking at some benchmark results obtained with an Intel box (i9-10940X CPU @ 3.30GHz, 14 cores) running Ubuntu 22.04.&lt;/p&gt;
&lt;p&gt;In this benchmark we are comparing a plain NumPy array copy against compression/decompression through different compressors and functions (&lt;cite&gt;compress() / decompress()&lt;/cite&gt;, &lt;cite&gt;pack_array() / unpack_array()&lt;/cite&gt; and &lt;cite&gt;pack_array2() / unpack_array2()&lt;/cite&gt;). The data distribution for the plots below is for 3 different data distributions: &lt;a class="reference external" href="https://github.com/Blosc/python-blosc2/blob/main/bench/pack_compress.py"&gt;arange, linspace and random&lt;/a&gt;:&lt;/p&gt;
&lt;img alt="Compression ratio for different codecs" class="align-center" src="https://blosc.org/images/python-blosc2-improvements/cratios.png" style="width: 50%;"&gt;
&lt;p&gt;As can be seen, different codecs offer different compression ratios for the different distributions.  Note in particular how linear distributions (arange for int64 and linspace for float64) can reach really high compression ratios (very low entropy).&lt;/p&gt;
&lt;p&gt;Let's see the speed for compression / decompression; in order to not show too many info in this blog, we will show just the plots for the linspace linear distribution:&lt;/p&gt;
&lt;img alt="Compression speed for different codecs" src="https://blosc.org/images/python-blosc2-improvements/linspace-compress.png" style="width: 45%;"&gt;
&lt;img alt="Decompression speed for different codecs" src="https://blosc.org/images/python-blosc2-improvements/linspace-decompress.png" style="width: 45%;"&gt;
&lt;p&gt;Here we can see that the pair &lt;cite&gt;pack_array2() / unpack_array2()&lt;/cite&gt; is consistently (much) faster than their previous version &lt;cite&gt;pack_array() / unpack_array()&lt;/cite&gt;. Despite that, the fastest is the &lt;cite&gt;compress() / decompress()&lt;/cite&gt; pair; however this is not serializing all the properties of a NumPy array, and has the limitation of not being able to compress data larger than 2 GB.&lt;/p&gt;
&lt;p&gt;You can test the speed in your box by running the &lt;a class="reference external" href="https://github.com/Blosc/python-blosc2/blob/main/bench/pack_compress.py"&gt;pack_compress bench&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Also, if you would like to store the contiguous buffer on-disk, you can directly use the pair of functions &lt;a class="reference external" href="https://www.blosc.org/python-blosc2/reference/autofiles/top_level/blosc2.save_array.html#blosc2.save_array"&gt;save_array()&lt;/a&gt;, &lt;a class="reference external" href="https://www.blosc.org/python-blosc2/reference/autofiles/top_level/blosc2.save_array.html#blosc2.load_array"&gt;load_array()&lt;/a&gt;.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="native-performance-on-apple-m1-processors"&gt;
&lt;h2&gt;Native performance on Apple M1 processors&lt;/h2&gt;
&lt;p&gt;Contrariliy to Blosc1, Blosc2 comes with native support for ARM processors (it leverages the NEON SIMD instruction set there), and that means that it runs very fast in this architecture.  As an example, let's see how the new &lt;cite&gt;pack_array2() / unpack_array2()&lt;/cite&gt; works in an Apple M1 laptop (Macbook Air).&lt;/p&gt;
&lt;img alt="Compression speed for different codecs" src="https://blosc.org/images/python-blosc2-improvements/M1-i386-vs-arm64-pack.png" style="width: 45%;"&gt;
&lt;img alt="Decompression speed for different codecs" src="https://blosc.org/images/python-blosc2-improvements/M1-i386-vs-arm64-unpack.png" style="width: 45%;"&gt;
&lt;p&gt;As can be seen, running Blosc2 in native arm64 mode on M1 offers quite a bit more performance (specially during compression) than using the i386 emulation.  If speed is important to you, and you have a M1/M2 processor, make sure that you are running Blosc2 in native mode (arm64).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="conclusions"&gt;
&lt;h2&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;The new features added to python-blosc2 offer an easy way of creating, getting, setting and expanding data by using a &lt;cite&gt;SChunk&lt;/cite&gt; instance. Furthermore, you can get a contiguous compressed representation (aka &lt;a class="reference external" href="https://github.com/Blosc/c-blosc2/blob/main/README_CFRAME_FORMAT.rst"&gt;cframe&lt;/a&gt;) of it and re-create it again latter. And you can do the same with NumPy arrays (either in-memory or on-disk) faster than with the former functions, and even faster than a plain &lt;cite&gt;memcpy()&lt;/cite&gt;.&lt;/p&gt;
&lt;p&gt;For more info on how to use these useful new features, see this &lt;a class="reference external" href="https://github.com/Blosc/python-blosc2/blob/main/examples/slicing_and_beyond.ipynb"&gt;Jupyter notebook tutorial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Finally, the complete documentation is at: &lt;a class="reference external" href="https://www.blosc.org/python-blosc2/python-blosc2.html"&gt;https://www.blosc.org/python-blosc2/python-blosc2.html&lt;/a&gt;.  Thanks to Marc Garcia (&lt;cite&gt;@datapythonista&lt;/cite&gt;) for his fine work and enthusiasm in helping us in providing a better structure to the Blosc documentation!&lt;/p&gt;
&lt;p&gt;This work has been possible thanks to a Small Development Grant from &lt;a class="reference external" href="https://numfocus.org"&gt;NumFOCUS&lt;/a&gt;.
NumFOCUS is a non-profit organization supporting open code for better science.  If you like the goal, consider giving a donation to NumFOCUS (you can optionally make it go to our project too, to which we would be very grateful indeed :-).&lt;/p&gt;
&lt;/section&gt;</description><category>blosc2 features performance</category><guid>https://blosc.org/posts/python-blosc2-improvements/</guid><pubDate>Thu, 06 Oct 2022 10:32:20 GMT</pubDate></item></channel></rss>