[GRASS-dev] [GRASS GIS] #2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by sprice):

I considered writing a more general function for compression but I held
off for two reasons:

1) There seems to be a lot of very specific code depending on exactly what
you're doing. For example, for read_data_fp_compressed() there was
functionality hidden in G_zlib_read to save a header for each compressed
row. Or the use of G_ZLIB_COMPRESSED_NO ('0') as a flag for FP
compression, vs various integers defining CELL compression. To keep
backwards compatibility, I delt with the different formats (CELL vs NULL
vs FCELL/DCELL) on a case-by-case basis.

2) I'm not familiar with the best practices for the code in GRASS GIS. I'd
encourage someone else to create new files (or libraries) as required. I
can help as required, but I'm concerned that as each edge case is
considered (as mentioned above) there won't be all that much common code
between the various compression uses.

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750#comment:15&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by wenzeslaus):

Replying to [comment:15 sprice]:
> I considered writing a more general function for compression but I held
off for two reasons:
>
> 1) There seems to be a lot of very specific code depending on exactly
what you're doing.

My point is to put these specific cases into one function. So for example,
whatever in the comment:13, should be in one function. What I suggest
should be simple to moving of the existing code unless I miss some
important part.

> For example, for read_data_fp_compressed() there was functionality
hidden in G_zlib_read to save a header for each compressed row.

Here I perhaps hit my limited understanding of the code in question. What
is doing this job now? Or it is not needed?

> Or the use of G_ZLIB_COMPRESSED_NO ('0') as a flag for FP compression,
vs various integers defining CELL compression.

This is the kind of things which I would like to have hidden in one place.
(In this way, we can keep the strange things at one place and e.g. easily
replace, literals by defines (which we should do anyway, BTW).

> To keep backwards compatibility, I delt with the different formats (CELL
vs NULL vs FCELL/DCELL) on a case-by-case basis.

You mean e.g. `read_data_compressed()` versus `read_data_fp_compressed()`?
I had no time to actually try to identify all the differences, but the
idea would be that these functions should deal with the differences among
CELL, NULL and FCELL/DCELL while the proposed "`G_compresslib_write()`"
function would deal with the differences between compression formats.

> I'm concerned that as each edge case is considered (as mentioned above)
there won't be all that much common code between the various compression
uses.

Another way to look at it is to think about, what do I have to replicate
in 3D raster library where only `G_zlib_*` is used now. The things I need
to replicate to enable other compressions should be in the
"`G_compresslib_*()`" functions.

I won't be able to give it attention it deserves in the following weeks,
so please don't expect any actual code from me now. But feel free to
oppose me or try it yourself in the mean time.

--
Ticket URL: <http://trac.osgeo.org/grass/ticket/2750#comment:16&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by sprice):

This makes sense, but requires work that neither of us has time for. My
main concern really is to get this merged & working before additional
changes such as those discussed in #2762 & #2349 make merging difficult.
What do you think about merging these changes now, and then upgrading
other I/O functions as you have time?

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750#comment:17&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by wenzeslaus):

Replying to [comment:17 sprice]:
> My main concern really is to get this merged & working before additional
changes such as those discussed in #2762 & #2349 make merging difficult.

That's right, but I would like to see some more testing before merging it.
Any chance somebody can do some? There are roughly three ways how to do
that after applying the patch:

  * Set the variables (see above) and run the automatic tests on NC SPM and
report the results back.
  * Run the benchmark Bash script attached to this ticket and compare with
results already reported.
  * Set the variables and go through some your workflow and check the
results.

It seems to be that #2349 has all issues solved and committed, but lacks
feedback/testing. Conflicts with #2762 would be probably solvable, but
yes, it would be better to avoid them.

> What do you think about merging these changes now, and then upgrading
other I/O functions as you have time?

This can work. The refactoring I'm suggesting shouldn't be difficult at
the end, although we should take some time to do it right.

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750#comment:18&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by mmetz):

Replying to [comment:14 glynn]:
> Replying to [comment:13 wenzeslaus]:
>
> > My question is if it wouldn't be more advantageous to create some
wrapper which would take the all necessary inputs including compression
type and do the necessary switches and format specific things.
>
> Agreed.
>
> In practical terms, there are only two distinct cases: uncompressed
(where the size of the data read or written matches the size of the data
stored in the file) and compressed (where the sizes differ). Everything
else is just options.

Without knowing about this ticket, I have implemented something like this
recently and added support for LZ4 (and BZIP2) compression to my local
copy of GRASS trunk. The motivation was to have a compressor that is
substantially faster than ZLIB but still better than RLE, and another
compressor that is substantially better (higher compression) than ZLIB but
not exceedingly slow. XZ with lzma2 is 1) too slow, 2) uses too much
memory, 3) does not compress binary raster data better than BZIP2.

In particular, I have added support for new compressors to gislib, not
rasterlib. As before gislib does the actual compression, not rasterlib. My
gislib now also handles LZ4 and BZIP2 compression. The actual change to
rasterlib is to replace `G_zlib_compress()` with `G_compress(..., int
compressor)` and `G_zlib_expand()` with `G_expand(..., int compressor)`.
`G_zlib_write()` and `G_zlib_read()` are now `G_write_compressed(..., int
compressor)` and `G_read_compressed(..., int compressor)`. Here, "..."
means same arguments as before. The new argument "compressor" is actually
"cellhd.compressed" with the same meaning as before. The internal function
`zlib_compress` is no longer needed.

As before, the compressor type is encoded in cellhd.compressed with
previously 0: no compression, 1: RLE, 2: ZLIB, now also 3: LZ4, 4: BZIP2.

r.univar results for CELL, FCELL, and DCELL maps are identical,
independent of the compressor. The new gislib interface to compress data
is generic and it is easy to add any other compressor, e.g. LZ4HC or ZSTD.

Generally, any new compression method should go into gislib and not into
rasterlib, just like ZLIB compression has been done by gislib. This keeps
changes to the rasterlib to a minimum and makes debugging easier.

For fast storage devices with plenty of space, LZ4 is by far the fastest,
at the same time providing some reasonable compression where possible.

For slow storage devices, e.g. accessed over network, BZIP2 compression is
the fastest (yes, faster than LZ4) because the amount of data is the least
(50% - 70% of ZLIB). That reduces network traffic and saves disk space.
For my work, it would be a big advantage to use LZ4 for actual processing
on fast local disks and BZIP2 for storing the final results on sometimes
very slow network attached storage.

The compressor type for new raster maps could be selected with one other
environment variable GRASS_COMPRESSOR, e.g. GRASS_COMPRESSOR=LZ4

I am not sure about the pro's and con's for using compressors other than
ZLIB. ZLIB is a good compromise of speed and compression. Adding other
compressors to G7.1 means that raster data compressed with a new method
can not be opened by G7.0 or earlier. New compression types should, if
added to G7.1, be clearly marked as "use it only if you really know what
you are doing". I would profit from the choice of other compressors, but
on a standard laptop/desktop system the current G7 default of ZLIB is
probably the best alround solution.

I am attaching a patch for trunk r66775 and an archive with new files to
go to lib/gis

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750#comment:19&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------
Changes (by mmetz):

* Attachment "compressors.patch" removed.

minimal modification to add more compressors

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by wenzeslaus):

Replying to [comment:19 mmetz]:
> I have implemented something like this recently and added support for
LZ4 (and BZIP2) compression to my local copy of GRASS trunk.
>
> I am attaching a patch for trunk r66775 and an archive with new files to
go to lib/gis

The design in the patch looks really good. I did tests and benchmark but
it was not as successful as I hoped for.

The benchmark was the same as [comment:10 before] but modified for this
patch. It is more for testing than benchmark anyway. It was on 30,000,000
cells but perhaps the previous one was on more and it is not completely
precise overall due to some other computations running at the same time
(although the result is from 10 runs aggregated by ''perf'').

|| type || write || read ||
|| NONE || 2.58 || 0.72 ||
|| ZLIB || 1.52 || 0.93 ||
|| LZ4 || 1.56 || 0.85 ||

RLE and BZIP2 are missing because I got and error when writing using
r.mapcalc with RLE:

{{{
*** Error in `r.mapcalc': free(): invalid next size (normal):
0x0000000000edacd0 ***
r.mapcalc: Aborted
}}}

The the commands are:

{{{
export GRASS_COMPRESSOR=RLE
r.mapcalc expression="test_rast_z_base = rand(double(-200.), 900)"
seed=100
r.mapcalc expression=test_rast_rle=double(test_rast_z_base)
}}}

I guess I'm missing something in configure because with BZIP2 it says
"ERROR: GRASS needs to be compiled with BZIP2 for BZIP2 compression".

The report from `r.compress`:

{{{
<test_rast_z_base> is compressed (level 2: DEFLATE). Data type: <DCELL>
<test_rast_none> is uncompressed (level 0: NONE). Data type: <DCELL>
<test_rast_zlib> is compressed (level 2: DEFLATE). Data type: <DCELL>
<test_rast_lz4> is compressed (level 3: DEFLATE). Data type: <DCELL>
}}}

When running the tests with

{{{
grass71 /grassdata/ncarolina_smp_base/practice1 --exec python -m
grass.gunittest.main--location ncarolina_smp_base --location-type nc
}}}

I get

{{{
ERROR: Error reading raster data for row 0 of <elevation>
}}}

from many raster-related tests. Sometimes it is a different row number.
The environmental variable `GRASS_COMPRESSOR` was not set. I didn't get if
you already meant it to be backwards compatible with existing maps.

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750#comment:20&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------
Changes (by wenzeslaus):

* Attachment "gislib_compressor_benchmark.sh" added.

Benchmark DCELL rasters with GRASS_COMPRESSOR

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------
Changes (by mmetz):

* Attachment "compressors.patch" removed.

minimal modification to add more compressors

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by mmetz):

Replying to [comment:20 wenzeslaus]:
> Replying to [comment:19 mmetz]:
> > I have implemented something like this recently and added support for
LZ4 (and BZIP2) compression to my local copy of GRASS trunk.
> >
> > I am attaching a patch for trunk r66775 and an archive with new files
to go to lib/gis
>
> The design in the patch looks really good. I did tests and benchmark but
it was not as successful as I hoped for.
>
> The benchmark was the same as [comment:10 before] but modified for this
patch. It is more for testing than benchmark anyway. It was on 30,000,000
cells

I tested on 552,000,000 cells

but perhaps the previous one was on more and it is not completely precise
overall due to some other computations running at the same time (although
the result is from 10 runs aggregated by ''perf'').
>
> || type || write || read ||
> || NONE || 2.58 || 0.72 ||
> || ZLIB || 1.52 || 0.93 ||
> || LZ4 || 1.56 || 0.85 ||
>
> RLE and BZIP2 are missing because I got and error when writing using
r.mapcalc with RLE:
>
{{{
> *** Error in `r.mapcalc': free(): invalid next size (normal):
0x0000000000edacd0 ***
> r.mapcalc: Aborted
}}}

Fixed in the updated patch "compressors.patch"
>
> The the commands are:
>
> {{{
> export GRASS_COMPRESSOR=RLE
> r.mapcalc expression="test_rast_z_base = rand(double(-200.), 900)"
seed=100
> r.mapcalc expression=test_rast_rle=double(test_rast_z_base)
> }}}

RLE compression is not and was never supported for fp maps. Also, if you
use r.mapcalc's rand() function, you test the rand() function and not the
compressor because all compressors are much faster than the rand()
function. (BTW, there are nice fast random number generators in gsl).

>
> I guess I'm missing something in configure because with BZIP2 it says
"ERROR: GRASS needs to be compiled with BZIP2 for BZIP2 compression".

You will need to hack in BZIP2 support, or make distclean, apply the patch
"bzipsupport.patch", configure --with-bzlib, make
>
> The report from `r.compress`:
I have not updated `r.compress`. For `r.compress`, and for meaningful
warning/error messages, something like `char *G_compressor_name(int
compressor)` that gives the compressor name could be useful.
>
> When running the tests with
>
> {{{
> grass71 /grassdata/ncarolina_smp_base/practice1 --exec python -m
grass.gunittest.main--location ncarolina_smp_base --location-type nc
> }}}
>
> I get
>
{{{
> ERROR: Error reading raster data for row 0 of <elevation>
}}}
>
> from many raster-related tests. Sometimes it is a different row number.
The environmental variable `GRASS_COMPRESSOR` was not set. I didn't get if
you already meant it to be backwards compatible with existing maps.

Fixed in the new patch "compressors.patch". I meant it to be backwards
compatible, but that one slipped through: old fp map compression is
sometimes 1, sometimes 2, but both 1 and 2 mean ZLIB.

Thanks for testing!

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750#comment:21&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------
Changes (by mmetz):

* Attachment "giscompress.tar.gz" removed.

new files for lib/gis to support different compressors

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by mmetz):

Replying to [comment:21 mmetz]:
> Replying to [comment:20 wenzeslaus]:
> > Replying to [comment:19 mmetz]:
> > > I have implemented something like this recently and added support
for LZ4 (and BZIP2) compression to my local copy of GRASS trunk.
> > >
> > > I am attaching a patch for trunk r66775 and an archive with new
files to go to lib/gis
> >

> >
> > I guess I'm missing something in configure because with BZIP2 it says
"ERROR: GRASS needs to be compiled with BZIP2 for BZIP2 compression".
>
> You will need to hack in BZIP2 support, or make distclean, apply the
patch "bzipsupport.patch", configure --with-bzlib, make

..and use the updated files in "giscompress.tar.gz"

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750#comment:22&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by mmetz):

Replying to [comment:20 wenzeslaus]:
> Replying to [comment:19 mmetz]:
> > I have implemented something like this recently and added support for
LZ4 (and BZIP2) compression to my local copy of GRASS trunk.
> >
> > I am attaching a patch for trunk r66775 and an archive with new files
to go to lib/gis
>
> The design in the patch looks really good. I did tests and benchmark but
it was not as successful as I hoped for.
>
> The benchmark was the same as [comment:10 before] but modified for this
patch. It is more for testing than benchmark anyway. It was on 30,000,000
cells but perhaps the previous one was on more and it is not completely
precise overall due to some other computations running at the same time
(although the result is from 10 runs aggregated by ''perf'').
>
> || type || write || read ||
> || NONE || 2.58 || 0.72 ||
> || ZLIB || 1.52 || 0.93 ||
> || LZ4 || 1.56 || 0.85 ||
>

Some more explanation about the proposed new mechanism:

The proposed `G_compress()` interface provides a generic mechanism to data
compression in libgis, not restricted to raster data but generic. Built-in
compression methods would be no compression, RLE, ZLIB, ZL4. BZIP2
compression would be available if GRASS is configured --with-bzlib. Other
compression methods could be added by cloning lib/gis/flate.c and adding
new `G_*_compress()` and `G_*_expand()` functions to
lib/gis/compress.[h|c]. The raster lib does not need to be modified any
more.

As before, the rasterlib makes only partial use of the generic compression
methods: no compression and RLE is handled by the rasterlib internally,
and RLE is not supported for fp maps. Creating uncompressed raster maps
has been and should be only possible with `Rast_open_new_uncompressed()`.

That means that the behaviour of the rasterlib with using
GRASS_COMPRESSOR=NONE needs to be defined: really use no compression or
use default compression instead? Using GRASS_COMPRESSOR=RLE affects only
new CELL maps. For fp maps, compression_type = 1 (RLE) is as before
interpreted as ZLIB compression.

If you want to know the original amount of data passed to any compressor,
you need to use

{{{
GRASS_COMPRESSOR=ZLIB
GRASS_ZLIB_LEVEL=0
}}}

ZLIB level = 0 tells ZLIB to copy the data as is from source to
destination. With CELL maps, the rasterlib will then still trim high zero
bytes with trim_bytes() which can already reduce the data size
considerably, but ZLIB will not compress the data.

I modified gislib_compressor_benchmark.sh to use
{{{
GRASS_COMPRESSOR=ZLIB
GRASS_ZLIB_LEVEL=0
}}}
for no compression and discarded RLE because it is inefficient for CELL
maps and not supported for fp maps. I tested also ZLIB levels 1 (fastest)
and 6 (ZLIB default).

I used the nc_basic_spm_grass7 location and set the region with
{{{
g.region -p rast=elevation res=2.5
}}}
resulting in 32,000,000 cells

The test raster was generated with
{{{
r.mapcalc expression="test_rast_z_base = rand(double(-200.), 900)"
seed=100
}}}
random numbers very difficult to compress.

The write and read columns in the tables below have seconds as unit.

|| compressor || size MB || size % || write || read ||
|| NONE || 259.2 || 100 || 5.2 || 1.4 ||
|| ZLIB 1 || 247.9 || 95.6 || 14.3 || 2.5 ||
|| ZLIB 6 || 246.9 || 95.3 || 16.3 || 2.4 ||
|| LZ4 || 259.2 || 100 || 4.5 || 1.1 ||
|| BZIP2 || 249.4 || 96.2 || 63.4 || 19.9 ||
LZ4 is the fastest method, no method is really the best because these
random numbers could not be compressed to less than 95% of the original
size.

The next test raster was generated with
{{{
r.mapcalc expression="test_rast2_z_base = elevation"
}}}
which had 4x4 blocks of identical raster values, should be easy to
compress

|| compressor || size MB || size % || write || read ||
|| NONE || 259.2 || 100 || 4.2 || 1.1 ||
|| ZLIB 1 || 41.8 || 16.1 || 4.7 || 1.6 ||
|| ZLIB 6 || 32.1 || 12.4 || 11.1 || 1.4 ||
|| LZ4 || 71.5 || 27.6 || 2.2 || 0.9 ||
|| BZIP2 || 49.8 || 19.2 || 28.0 || 7.1 ||

LZ4 was again the fastest, and the best was ZLIB level 6. Here, the
performance of BZIP2 was not convincing: by far the slowest and not as
good as ZLIB.

Then I tested with MODIS land surface temperature for Europe, a bit more
than 400,000,000 cells:

LST as CELL
|| compressor || size MB || size % || write || read ||
|| NONE || 829 || 100 || 28.5 || 14.8 ||
|| ZLIB 1 || 269 || 32.4 || 30.5 || 14.9 ||
|| ZLIB 6 || 261 || 31.5 || 36.7 || 16.5 ||
|| LZ4 || 366 || 44.1 || 20.0 || 13.0 ||
|| BZIP2 || 175 || 21.1 || 89.8 || 29.2 ||

LZ4 was the fastest, BZIP2 was the best.

LST as DCELL
|| compressor || size MB || size % || write || read ||
|| NONE || 3300 || 100 || 85.5 || 52.9 ||
|| ZLIB 1 || 503 || 15.2 || 62.7 || 23.9 ||
|| ZLIB 6 || 370 || 11.2 || 129.8 || 21.6 ||
|| LZ4 || 629 || 19.1 || 29.5 || 13.9 ||
|| BZIP2 || 196 || 5.9 || 221 || 51.1 ||

Again, LZ4 was the fastest, BZIP2 was the best.

I am interested in having BZIP2 because for these LST data it compresses
30 - 50% better than the second best (ZLIB level 6).

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750#comment:23&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by wenzeslaus):

I was not able to make BZIP2 work for me. I would say I miss something
like addition to `GISDEPS` but I was not able to fix it (getting undefined
reference to some BZ function).

I was able to run the tests successfully with LZ4 (on modified r66770):

{{{
GRASS_COMPRESSOR=LZ4 \
     ./bin.../grass71 /grassdata/nc_basic/practice1 --exec \
     python -m grass.gunittest.main --location nc_basic --location-type nc
}}}

The benchmarks look really good. I was getting quite good results before
even on the random data, perhaps pure luck. But I wrongly recorded the
region, it seems, so even with the seed I cannot reproduce; not important
anyway.

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750#comment:24&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------

Comment (by mmetz):

Replying to [comment:24 wenzeslaus]:
> I was not able to make BZIP2 work for me. I would say I miss something
like addition to `GISDEPS` but I was not able to fix it (getting undefined
reference to some BZ function).

You need to add $(BZLIB) to GISDEPS in include/Make/Grass.make. I will
update bzipsupport.patch accordingly.

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750#comment:25&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------
Changes (by mmetz):

* Attachment "bzipsupport.patch" added.

bzip2 support patch

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------
Changes (by mmetz):

* Attachment "bzipsupport.patch" removed.

bzip2 support patch

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------
Changes (by mmetz):

* Attachment "compressors.patch" added.

minimal modification to add more compressors

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------
Changes (by mmetz):

* Attachment "compressors.patch" removed.

minimal modification to add more compressors

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750&gt;
GRASS GIS <https://grass.osgeo.org>

#2750: LZ4 when writing raster rows; better than double I/O bound r.mapcalc speed
--------------------------+---------------------------
  Reporter: sprice | Owner: grass-dev@…
      Type: enhancement | Status: new
  Priority: normal | Milestone: 7.1.0
Component: Raster | Version: svn-trunk
Resolution: | Keywords: ZLIB LZ4 ZSTD
       CPU: OSX/Intel | Platform: MacOSX
--------------------------+---------------------------
Changes (by mmetz):

* Attachment "giscompress.tar.gz" removed.

new files for lib/gis to support different compressors

--
Ticket URL: <https://trac.osgeo.org/grass/ticket/2750&gt;
GRASS GIS <https://grass.osgeo.org>