[ 
https://issues.apache.org/jira/browse/PARQUET-2414?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Antoine Pitrou updated PARQUET-2414:
------------------------------------
    Description: 
In PARQUET-1622 we added the BYTE_STREAM_SPLIT which, while simple to 
implement, allows to significantly improve compression efficiency on FLOAT and 
DOUBLE columns.

In PARQUET-758 we added the FLOAT16 logical type which annotates a 2-byte-wide 
FIXED_LEN_BYTE_ARRAY column to denote that it contains 16-bit IEEE binary 
floating-point (colloquially called "half float").

This issue proposed to widen the types supported by the BYTE_STREAM_SPLIT. By 
allowing the BYTE_STREAM_SPLIT on any FIXED_LEN_BYTE_ARRAY column, we can 
automatically improve compression efficiency on various column types including:

* half-float data
* fixed-width decimal data

I've run compression measurements on various pieces of sample data which I 
detail below.

h2. Float16 data

I've downloaded the sample datasets from
https://userweb.cs.txstate.edu/~burtscher/research/datasets/FPsingle/ , 
uncompressed them and converted them to half-float using NumPy. Two files had 
to be discarded because of overflow when converting to half-float.

I've then run three different compression algorithms (lz4, zstd, snappy), 
optionally preceded by a byte-stream-split encoded with 2 streams 
(corresponding to the byte width of the FLBA columns. Here are the results:

{code}
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| name           |   uncompressed |    lz4 |   bss_lz4 |   snappy |   
bss_snappy |   zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   
bss_ratio_zstd |
+================+================+========+===========+==========+==============+========+============+=================+====================+==================+
| msg_sp.sp      |    72526464.00 |   1.42 |      1.94 |     1.38 |         
1.78 |   2.28 |       2.71 |            1.37 |               1.30 |             
1.18 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| msg_sppm.sp    |    69748966.00 |  18.90 |     29.05 |    11.38 |        
14.39 |  45.81 |      71.49 |            1.54 |               1.26 |            
 1.56 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| msg_sweep3d.sp |    31432806.00 |   2.06 |      3.20 |     1.03 |         
1.94 |  11.77 |      17.00 |            1.55 |               1.89 |             
1.44 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_brain.sp   |    35460000.00 |   1.02 |      1.51 |     1.01 |         
1.49 |   1.26 |       1.81 |            1.49 |               1.48 |             
1.44 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_comet.sp   |    26836992.00 |   1.45 |      1.74 |     1.42 |         
1.69 |   1.64 |       2.07 |            1.20 |               1.19 |             
1.26 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_control.sp |    39876186.00 |   1.35 |      1.49 |     1.37 |         
1.53 |   1.70 |       1.93 |            1.11 |               1.12 |             
1.14 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_plasma.sp  |     8772400.00 | 123.88 |    152.12 |     1.00 |         
1.80 | 259.58 |     405.96 |            1.23 |               1.80 |             
1.56 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_error.sp   |    15540204.00 |   1.05 |      1.51 |     1.02 |         
1.46 |   2.06 |       3.55 |            1.44 |               1.43 |             
1.72 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_info.sp    |     4732632.00 |   1.08 |      1.74 |     1.00 |         
1.61 |   2.60 |       3.63 |            1.62 |               1.61 |             
1.40 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_spitzer.sp |    49545216.00 |   1.00 |      1.01 |     1.00 |         
1.01 |   1.22 |       1.35 |            1.01 |               1.01 |             
1.11 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_temp.sp    |     9983568.00 |   1.00 |      1.00 |     1.00 |         
1.00 |   1.08 |       1.17 |            1.00 |               1.00 |             
1.08 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
{code}

Explanation:

* the columns "lz4", "snappy", "zstd" show the compression ratio achieved with 
the respective compressors (i.e. uncompressed size divided by compressed size)
* the columns "bss_lz4", "bss_snappy", "bss_zstd" are similar, but with a 
byte-stream-split encoding applied first
* the columns "bss_ratio_lz4", "bss_ratio_snappy", "bss_ratio_zstd" show the 
additional compression ratio achieved by prepending the byte-stream-split 
encoding step (i.e. compressed size divided by encoded+compressed size).

h3. (reference) Float32 data

For reference, here are the measurements for the original single-precision 
floating-point data.

{code}
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| name           |   uncompressed |   lz4 |   bss_lz4 |   snappy |   bss_snappy 
|   zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   bss_ratio_zstd 
|
+================+================+=======+===========+==========+==============+========+============+=================+====================+==================+
| msg_sp.sp      |   145052928.00 |  1.00 |      1.45 |     1.00 |         1.39 
|   1.12 |       1.66 |            1.46 |               1.39 |             1.48 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| msg_sppm.sp    |   139497932.00 |  8.56 |      8.66 |     5.64 |         5.90 
|  12.51 |      11.16 |            1.01 |               1.05 |             0.89 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| msg_sweep3d.sp |    62865612.00 |  1.01 |      2.80 |     1.02 |         1.68 
|   5.50 |       9.41 |            2.76 |               1.66 |             1.71 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_brain.sp   |    70920000.00 |  1.00 |      1.31 |     1.00 |         1.30 
|   1.13 |       1.43 |            1.31 |               1.30 |             1.27 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_comet.sp   |    53673984.00 |  1.08 |      1.27 |     1.08 |         1.27 
|   1.15 |       1.36 |            1.17 |               1.18 |             1.18 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_control.sp |    79752372.00 |  1.01 |      1.12 |     1.01 |         1.13 
|   1.08 |       1.21 |            1.11 |               1.12 |             1.12 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_plasma.sp  |    17544800.00 |  1.00 |    140.74 |     1.01 |         1.30 
| 279.49 |     310.68 |          141.29 |               1.30 |             1.11 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_error.sp   |    31080408.00 |  1.12 |      1.37 |     1.16 |         1.29 
|   1.73 |       3.10 |            1.22 |               1.11 |             1.80 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_info.sp    |     9465264.00 |  1.07 |      1.42 |     1.00 |         1.29 
|   2.25 |       3.04 |            1.33 |               1.29 |             1.35 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_spitzer.sp |    99090432.00 |  1.02 |      1.11 |     1.01 |         1.12 
|   1.20 |       1.31 |            1.09 |               1.10 |             1.09 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_temp.sp    |    19967136.00 |  1.00 |      1.12 |     1.00 |         1.13 
|   1.08 |       1.19 |            1.12 |               1.13 |             1.10 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
{code}

h3. Comments

The additional efficiency of the byte-stream-split encoding step is very 
significant on most files (except {{obs_temp.sp}} which generally doesn't 
compress at all), with additional gains usually around 30%.

The byte-stream-split encoding test is, perhaps surprisingly, on average as 
beneficial on Float16 data as it is on Float32 data.

h2. Decimal data from OpenStreetMap changesets

I've downloaded one of the recent OSM changesets file 
{{changesets-231030.orc}}, and loaded the four decimal columns from the first 
stripe of that file. Those columns look like:
{code}
pyarrow.RecordBatch
min_lat: decimal128(9, 7)
max_lat: decimal128(9, 7)
min_lon: decimal128(10, 7)
max_lon: decimal128(10, 7)
----
min_lat: 
[51.5288506,51.0025063,51.5326805,51.5248871,51.5266800,51.5261841,51.5264130,51.5238914,59.9463692,59.9513092,...,50.8238277,52.1707376,44.2701598,53.1589748,43.5988333,37.7867167,45.5448822,null,50.7998334,50.5653478]
max_lat: 
[51.5288620,51.0047760,51.5333176,51.5289383,51.5291901,51.5300598,51.5264130,51.5238914,59.9525642,59.9561501,...,50.8480772,52.1714300,44.3790161,53.1616817,43.6001496,37.7867913,45.5532716,null,51.0188961,50.5691352]
min_lon: 
[-0.1465242,-1.0052705,-0.1566335,-0.1485492,-0.1418076,-0.1550623,-0.1539768,-0.1432930,10.7782278,10.7719727,...,10.6863813,13.2218676,19.8840738,8.9128186,1.4030591,-122.4212761,18.6789571,null,-4.2085209,8.6851671]
max_lon: 
[-0.1464925,-0.9943439,-0.1541054,-0.1413791,-0.1411505,-0.1453212,-0.1539768,-0.1432930,10.7898550,10.7994537,...,10.7393494,13.2298706,20.2262343,8.9183611,1.4159345,-122.4212503,18.6961594,null,-4.0496079,8.6879264]
{code}

Here are the compression measurements using the same methodology as above. The 
number of byte-stream-split streams is the respective byte width of each FLBA 
column (i.e., 4 for latitudes and 5 for longitudes).
{code}
+---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| name    |   uncompressed |   lz4 |   bss_lz4 |   snappy |   bss_snappy |   
zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   bss_ratio_zstd |
+=========+================+=======+===========+==========+==============+========+============+=================+====================+==================+
| min_lat |     4996652.00 |  1.00 |      1.01 |     1.00 |         1.03 |   
1.05 |       1.12 |            1.01 |               1.03 |             1.07 |
+---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| max_lat |     4996652.00 |  1.00 |      1.01 |     1.00 |         1.03 |   
1.05 |       1.13 |            1.01 |               1.03 |             1.07 |
+---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| min_lon |     6245825.00 |  1.00 |      1.14 |     1.00 |         1.16 |   
1.15 |       1.31 |            1.14 |               1.16 |             1.14 |
+---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| max_lon |     6245825.00 |  1.00 |      1.14 |     1.00 |         1.16 |   
1.15 |       1.31 |            1.14 |               1.16 |             1.14 |
+---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
{code}

h3. Comments

On this dataset, compression efficiency is generally quite poor and 
byte-stream-split encoding brings almost no additional efficiency to the table. 
It can be assumed that OSM changeset entries have geographical coordinates all 
over the place (literally!) and therefore do not offer many opportunities for 
compression.

h2. Decimal data from an OpenStreetMap region

I've chosen a small region of the world (Belgium) whose geographical 
coordinates presumably allow for better compression by being much more 
clustered. The file {{belgium-latest.osm.pbf}} was converted to ORC for easier 
handling, resulting in a 745 MB ORC file.

I've then loaded the decimal columns from the first stripe in that file:
{code}
pyarrow.RecordBatch
lat: decimal128(9, 7)
lon: decimal128(10, 7)
----
lat: 
[50.4443865,50.4469017,50.4487890,50.4499558,50.4523446,50.4536530,50.4571053,50.4601436,50.4631197,50.4678563,...,51.1055899,51.1106197,51.1049620,51.1047010,51.1104755,51.0997955,51.1058101,51.1010664,51.1014336,51.1055106]
lon: 
[3.6857362,3.6965046,3.7074481,3.7173626,3.8126033,3.9033178,3.9193678,3.9253319,3.9292409,3.9332670,...,4.6663214,4.6699997,4.6720536,4.6655159,4.6666372,4.6680394,4.6747172,4.6684242,4.6713693,4.6644899]
{code}

Here are the compression measurements for these columns:
{code}
+--------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| name   |   uncompressed |   lz4 |   bss_lz4 |   snappy |   bss_snappy |   
zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   bss_ratio_zstd |
+========+================+=======+===========+==========+==============+========+============+=================+====================+==================+
| lat    |    12103680.00 |  1.00 |      1.63 |     1.00 |         1.63 |   
1.18 |       1.73 |            1.63 |               1.63 |             1.47 |
+--------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| lon    |    15129600.00 |  1.00 |      1.93 |     1.00 |         1.90 |   
1.27 |       2.06 |            1.93 |               1.90 |             1.62 |
+--------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
{code}

h3. Comments

This dataset shows that a byte-stream-split encoding test before compression 
achieves a very significant additional efficiency compared to compression alone.

h2. Discussion

h3. Benefits

These examples show that extending the BYTE_STREAM_SPLIT encoding to 
FIXED_LEN_BYTE_ARRAY columns (even regardless of their logical types) can yield 
very significant compression efficiency improvements on two specific types of 
FIXED_LEN_BYTE_ARRAY data: FLOAT16 data and DECIMAL data.

h3. Implementation complexity

BYTE_STREAM_SPLIT, even byte width-agnostic, is almost trivial to implement. A 
simple implementation can yield good performance with a minimum of work.

For example, the non-SIMD-optimized BYTE_STREAM_SPLIT encoding and decoding 
routines in Parquet C++ amount to a mere total of ~200 lines of code, despite 
explicitly-unrolled loops:
https://github.com/apache/arrow/blob/4e58f7ca0016c2b2d8a859a0c5965df3b15523e0/cpp/src/arrow/util/byte_stream_split_internal.h#L593-L702

These routines achieve several GB/s on FLOAT and DOUBLE data, both for encoding 
and decoding.

h2. TODO

Try to make the tables above nicer :-)


  was:
In PARQUET-1622 we added the BYTE_STREAM_SPLIT which, while simple to
implement, allows to significantly improve compression efficiency on FLOAT and
DOUBLE columns.

In PARQUET-758 we added the FLOAT16 logical type which annotates a 2-byte-wide
FIXED_LEN_BYTE_ARRAY column to denote that it contains 16-bit IEEE binary
floating-point (colloquially called "half float").

This issue proposed to widen the types supported by the BYTE_STREAM_SPLIT. By
allowing the BYTE_STREAM_SPLIT on any FIXED_LEN_BYTE_ARRAY column, we can
automatically improve compression efficiency on various column types
including:

* half-float data
* fixed-width decimal data

I've run compression measurements on various pieces of sample data which I
detail below.

h2. Float16 data

I've downloaded the sample datasets from
https://userweb.cs.txstate.edu/~burtscher/research/datasets/FPsingle/ ,
uncompressed them and converted them to half-float using NumPy. Two files
had to be discarded because of overflow when converting to half-float.

I've then run three different compression algorithms (lz4, zstd, snappy),
optionally preceded by a byte-stream-split encoded with 2 streams
(corresponding to the byte width of the FLBA columns. Here are the results:

{code}
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| name           |   uncompressed |    lz4 |   bss_lz4 |   snappy |   
bss_snappy |   zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   
bss_ratio_zstd |
+================+================+========+===========+==========+==============+========+============+=================+====================+==================+
| msg_sp.sp      |    72526464.00 |   1.42 |      1.94 |     1.38 |         
1.78 |   2.28 |       2.71 |            1.37 |               1.30 |             
1.18 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| msg_sppm.sp    |    69748966.00 |  18.90 |     29.05 |    11.38 |        
14.39 |  45.81 |      71.49 |            1.54 |               1.26 |            
 1.56 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| msg_sweep3d.sp |    31432806.00 |   2.06 |      3.20 |     1.03 |         
1.94 |  11.77 |      17.00 |            1.55 |               1.89 |             
1.44 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_brain.sp   |    35460000.00 |   1.02 |      1.51 |     1.01 |         
1.49 |   1.26 |       1.81 |            1.49 |               1.48 |             
1.44 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_comet.sp   |    26836992.00 |   1.45 |      1.74 |     1.42 |         
1.69 |   1.64 |       2.07 |            1.20 |               1.19 |             
1.26 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_control.sp |    39876186.00 |   1.35 |      1.49 |     1.37 |         
1.53 |   1.70 |       1.93 |            1.11 |               1.12 |             
1.14 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_plasma.sp  |     8772400.00 | 123.88 |    152.12 |     1.00 |         
1.80 | 259.58 |     405.96 |            1.23 |               1.80 |             
1.56 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_error.sp   |    15540204.00 |   1.05 |      1.51 |     1.02 |         
1.46 |   2.06 |       3.55 |            1.44 |               1.43 |             
1.72 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_info.sp    |     4732632.00 |   1.08 |      1.74 |     1.00 |         
1.61 |   2.60 |       3.63 |            1.62 |               1.61 |             
1.40 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_spitzer.sp |    49545216.00 |   1.00 |      1.01 |     1.00 |         
1.01 |   1.22 |       1.35 |            1.01 |               1.01 |             
1.11 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_temp.sp    |     9983568.00 |   1.00 |      1.00 |     1.00 |         
1.00 |   1.08 |       1.17 |            1.00 |               1.00 |             
1.08 |
+----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
{code}

Explanation:

* the columns "lz4", "snappy", "zstd" shows the compression ratio achieved with
  the respective compressors (i.e. uncompressed size divided by compressed size)
* the columns "bss_lz4", "bss_snappy", "bss_zstd" are similar, but with a
  byte-stream-split encoding applied first
* the columns "bss_ratio_lz4", "bss_ratio_snappy", "bss_ratio_zstd" show
  the additional compression ratio achieved by prepending the byte-stream-split
  encoding step (i.e. compressed size divided by encoded+compressed size).

h3. (reference) Float32 data

For reference, here are the measurements for the same data without first 
converting
to half-float.

{code}
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| name           |   uncompressed |   lz4 |   bss_lz4 |   snappy |   bss_snappy 
|   zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   bss_ratio_zstd 
|
+================+================+=======+===========+==========+==============+========+============+=================+====================+==================+
| msg_sp.sp      |   145052928.00 |  1.00 |      1.45 |     1.00 |         1.39 
|   1.12 |       1.66 |            1.46 |               1.39 |             1.48 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| msg_sppm.sp    |   139497932.00 |  8.56 |      8.66 |     5.64 |         5.90 
|  12.51 |      11.16 |            1.01 |               1.05 |             0.89 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| msg_sweep3d.sp |    62865612.00 |  1.01 |      2.80 |     1.02 |         1.68 
|   5.50 |       9.41 |            2.76 |               1.66 |             1.71 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_brain.sp   |    70920000.00 |  1.00 |      1.31 |     1.00 |         1.30 
|   1.13 |       1.43 |            1.31 |               1.30 |             1.27 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_comet.sp   |    53673984.00 |  1.08 |      1.27 |     1.08 |         1.27 
|   1.15 |       1.36 |            1.17 |               1.18 |             1.18 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_control.sp |    79752372.00 |  1.01 |      1.12 |     1.01 |         1.13 
|   1.08 |       1.21 |            1.11 |               1.12 |             1.12 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| num_plasma.sp  |    17544800.00 |  1.00 |    140.74 |     1.01 |         1.30 
| 279.49 |     310.68 |          141.29 |               1.30 |             1.11 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_error.sp   |    31080408.00 |  1.12 |      1.37 |     1.16 |         1.29 
|   1.73 |       3.10 |            1.22 |               1.11 |             1.80 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_info.sp    |     9465264.00 |  1.07 |      1.42 |     1.00 |         1.29 
|   2.25 |       3.04 |            1.33 |               1.29 |             1.35 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_spitzer.sp |    99090432.00 |  1.02 |      1.11 |     1.01 |         1.12 
|   1.20 |       1.31 |            1.09 |               1.10 |             1.09 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| obs_temp.sp    |    19967136.00 |  1.00 |      1.12 |     1.00 |         1.13 
|   1.08 |       1.19 |            1.12 |               1.13 |             1.10 
|
+----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
{code}

h3. Comments

The additional efficiency of the byte-stream-split encoding step is very 
significant
on most files (except {code}obs_temp.sp{code} which generally doesn't compress 
at all),
with additional gains usually around 30%.

The byte-stream-split encoding test is, perhaps surprisingly, on average as 
beneficial
on Float16 data as it is on Float32 data.

h2. Decimal data from OpenStreetMap changesets

I've downloaded one of the recent OSM changesets file {{changesets-231030.orc}},
and loaded the four decimal columns from the first stripe of that file.
Those columns look like:
{code}
pyarrow.RecordBatch
min_lat: decimal128(9, 7)
max_lat: decimal128(9, 7)
min_lon: decimal128(10, 7)
max_lon: decimal128(10, 7)
----
min_lat: 
[51.5288506,51.0025063,51.5326805,51.5248871,51.5266800,51.5261841,51.5264130,51.5238914,59.9463692,59.9513092,...,50.8238277,52.1707376,44.2701598,53.1589748,43.5988333,37.7867167,45.5448822,null,50.7998334,50.5653478]
max_lat: 
[51.5288620,51.0047760,51.5333176,51.5289383,51.5291901,51.5300598,51.5264130,51.5238914,59.9525642,59.9561501,...,50.8480772,52.1714300,44.3790161,53.1616817,43.6001496,37.7867913,45.5532716,null,51.0188961,50.5691352]
min_lon: 
[-0.1465242,-1.0052705,-0.1566335,-0.1485492,-0.1418076,-0.1550623,-0.1539768,-0.1432930,10.7782278,10.7719727,...,10.6863813,13.2218676,19.8840738,8.9128186,1.4030591,-122.4212761,18.6789571,null,-4.2085209,8.6851671]
max_lon: 
[-0.1464925,-0.9943439,-0.1541054,-0.1413791,-0.1411505,-0.1453212,-0.1539768,-0.1432930,10.7898550,10.7994537,...,10.7393494,13.2298706,20.2262343,8.9183611,1.4159345,-122.4212503,18.6961594,null,-4.0496079,8.6879264]
{code}

Here are the compression measurements using the same methodology as above.
The number of byte-stream-split streams is the respective byte width of
each FLBA column (i.e., 4 for latitudes and 5 for longitudes).
{code}
+---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| name    |   uncompressed |   lz4 |   bss_lz4 |   snappy |   bss_snappy |   
zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   bss_ratio_zstd |
+=========+================+=======+===========+==========+==============+========+============+=================+====================+==================+
| min_lat |     4996652.00 |  1.00 |      1.01 |     1.00 |         1.03 |   
1.05 |       1.12 |            1.01 |               1.03 |             1.07 |
+---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| max_lat |     4996652.00 |  1.00 |      1.01 |     1.00 |         1.03 |   
1.05 |       1.13 |            1.01 |               1.03 |             1.07 |
+---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| min_lon |     6245825.00 |  1.00 |      1.14 |     1.00 |         1.16 |   
1.15 |       1.31 |            1.14 |               1.16 |             1.14 |
+---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| max_lon |     6245825.00 |  1.00 |      1.14 |     1.00 |         1.16 |   
1.15 |       1.31 |            1.14 |               1.16 |             1.14 |
+---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
{code}

h3. Comments

On this dataset, compression efficiency is generally quite poor and 
byte-stream-split
encoding brings almost no additional efficiency to the table. It can be assumed 
that
OSM changeset entries have geographical coordinates all over the place 
(literally!)
and therefore do not offer many opportunities for compression.

h2. Decimal data from an OpenStreetMap region

I've chosen a small region of the world (Belgium) whose geographical coordinates
presumably allow for better compression by being much more clustered. The file
{{belgium-latest.osm.pbf}} was converted to ORC for easier handling, resulting
in a 745 MB ORC file.

I've then loaded the decimal columns from the first stripe in that file:
{code}
pyarrow.RecordBatch
lat: decimal128(9, 7)
lon: decimal128(10, 7)
----
lat: 
[50.4443865,50.4469017,50.4487890,50.4499558,50.4523446,50.4536530,50.4571053,50.4601436,50.4631197,50.4678563,...,51.1055899,51.1106197,51.1049620,51.1047010,51.1104755,51.0997955,51.1058101,51.1010664,51.1014336,51.1055106]
lon: 
[3.6857362,3.6965046,3.7074481,3.7173626,3.8126033,3.9033178,3.9193678,3.9253319,3.9292409,3.9332670,...,4.6663214,4.6699997,4.6720536,4.6655159,4.6666372,4.6680394,4.6747172,4.6684242,4.6713693,4.6644899]
{code}

Here are the compression measurements for these columns:
{code}
+--------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| name   |   uncompressed |   lz4 |   bss_lz4 |   snappy |   bss_snappy |   
zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   bss_ratio_zstd |
+========+================+=======+===========+==========+==============+========+============+=================+====================+==================+
| lat    |    12103680.00 |  1.00 |      1.63 |     1.00 |         1.63 |   
1.18 |       1.73 |            1.63 |               1.63 |             1.47 |
+--------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
| lon    |    15129600.00 |  1.00 |      1.93 |     1.00 |         1.90 |   
1.27 |       2.06 |            1.93 |               1.90 |             1.62 |
+--------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
{code}

h3. Comments

This dataset shows that a byte-stream-split encoding test before compression
achieves a very significant additional efficiency compared to compression alone.

h2. Discussion

h3. Benefits

These examples show that extending the BYTE_STREAM_SPLIT encoding to
FIXED_LEN_BYTE_ARRAY columns (even regardless of their logical types) can
yield very significant compression efficiency improvements on two specific
types of FIXED_LEN_BYTE_ARRAY data: FLOAT16 data and DECIMAL data.

h3. Implementation complexity

BYTE_STREAM_SPLIT, even byte width-agnostic, is almost trivial to implement.
A simple implementation can yield good performance with a minimum of work.

For example, the non-SIMD-optimized BYTE_STREAM_SPLIT encoding and decoding
routines in Parquet C++ amount to a mere total of ~200 lines of code, despite
explicitly-unrolled loops:
https://github.com/apache/arrow/blob/4e58f7ca0016c2b2d8a859a0c5965df3b15523e0/cpp/src/arrow/util/byte_stream_split_internal.h#L593-L702

These routines achieve several GB/s on FLOAT and DOUBLE data, both for encoding
and decoding.

h2. TODO

Try to make the tables above nicer :-)



> [Format] Expand BYTE_STREAM_SPLIT to support FIXED_LEN_BYTE_ARRAY
> -----------------------------------------------------------------
>
>                 Key: PARQUET-2414
>                 URL: https://issues.apache.org/jira/browse/PARQUET-2414
>             Project: Parquet
>          Issue Type: Improvement
>          Components: parquet-format
>            Reporter: Antoine Pitrou
>            Priority: Minor
>
> In PARQUET-1622 we added the BYTE_STREAM_SPLIT which, while simple to 
> implement, allows to significantly improve compression efficiency on FLOAT 
> and DOUBLE columns.
> In PARQUET-758 we added the FLOAT16 logical type which annotates a 
> 2-byte-wide FIXED_LEN_BYTE_ARRAY column to denote that it contains 16-bit 
> IEEE binary floating-point (colloquially called "half float").
> This issue proposed to widen the types supported by the BYTE_STREAM_SPLIT. By 
> allowing the BYTE_STREAM_SPLIT on any FIXED_LEN_BYTE_ARRAY column, we can 
> automatically improve compression efficiency on various column types 
> including:
> * half-float data
> * fixed-width decimal data
> I've run compression measurements on various pieces of sample data which I 
> detail below.
> h2. Float16 data
> I've downloaded the sample datasets from
> https://userweb.cs.txstate.edu/~burtscher/research/datasets/FPsingle/ , 
> uncompressed them and converted them to half-float using NumPy. Two files had 
> to be discarded because of overflow when converting to half-float.
> I've then run three different compression algorithms (lz4, zstd, snappy), 
> optionally preceded by a byte-stream-split encoded with 2 streams 
> (corresponding to the byte width of the FLBA columns. Here are the results:
> {code}
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | name           |   uncompressed |    lz4 |   bss_lz4 |   snappy |   
> bss_snappy |   zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   
> bss_ratio_zstd |
> +================+================+========+===========+==========+==============+========+============+=================+====================+==================+
> | msg_sp.sp      |    72526464.00 |   1.42 |      1.94 |     1.38 |         
> 1.78 |   2.28 |       2.71 |            1.37 |               1.30 |           
>   1.18 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | msg_sppm.sp    |    69748966.00 |  18.90 |     29.05 |    11.38 |        
> 14.39 |  45.81 |      71.49 |            1.54 |               1.26 |          
>    1.56 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | msg_sweep3d.sp |    31432806.00 |   2.06 |      3.20 |     1.03 |         
> 1.94 |  11.77 |      17.00 |            1.55 |               1.89 |           
>   1.44 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | num_brain.sp   |    35460000.00 |   1.02 |      1.51 |     1.01 |         
> 1.49 |   1.26 |       1.81 |            1.49 |               1.48 |           
>   1.44 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | num_comet.sp   |    26836992.00 |   1.45 |      1.74 |     1.42 |         
> 1.69 |   1.64 |       2.07 |            1.20 |               1.19 |           
>   1.26 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | num_control.sp |    39876186.00 |   1.35 |      1.49 |     1.37 |         
> 1.53 |   1.70 |       1.93 |            1.11 |               1.12 |           
>   1.14 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | num_plasma.sp  |     8772400.00 | 123.88 |    152.12 |     1.00 |         
> 1.80 | 259.58 |     405.96 |            1.23 |               1.80 |           
>   1.56 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | obs_error.sp   |    15540204.00 |   1.05 |      1.51 |     1.02 |         
> 1.46 |   2.06 |       3.55 |            1.44 |               1.43 |           
>   1.72 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | obs_info.sp    |     4732632.00 |   1.08 |      1.74 |     1.00 |         
> 1.61 |   2.60 |       3.63 |            1.62 |               1.61 |           
>   1.40 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | obs_spitzer.sp |    49545216.00 |   1.00 |      1.01 |     1.00 |         
> 1.01 |   1.22 |       1.35 |            1.01 |               1.01 |           
>   1.11 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | obs_temp.sp    |     9983568.00 |   1.00 |      1.00 |     1.00 |         
> 1.00 |   1.08 |       1.17 |            1.00 |               1.00 |           
>   1.08 |
> +----------------+----------------+--------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> {code}
> Explanation:
> * the columns "lz4", "snappy", "zstd" show the compression ratio achieved 
> with the respective compressors (i.e. uncompressed size divided by compressed 
> size)
> * the columns "bss_lz4", "bss_snappy", "bss_zstd" are similar, but with a 
> byte-stream-split encoding applied first
> * the columns "bss_ratio_lz4", "bss_ratio_snappy", "bss_ratio_zstd" show the 
> additional compression ratio achieved by prepending the byte-stream-split 
> encoding step (i.e. compressed size divided by encoded+compressed size).
> h3. (reference) Float32 data
> For reference, here are the measurements for the original single-precision 
> floating-point data.
> {code}
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | name           |   uncompressed |   lz4 |   bss_lz4 |   snappy |   
> bss_snappy |   zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   
> bss_ratio_zstd |
> +================+================+=======+===========+==========+==============+========+============+=================+====================+==================+
> | msg_sp.sp      |   145052928.00 |  1.00 |      1.45 |     1.00 |         
> 1.39 |   1.12 |       1.66 |            1.46 |               1.39 |           
>   1.48 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | msg_sppm.sp    |   139497932.00 |  8.56 |      8.66 |     5.64 |         
> 5.90 |  12.51 |      11.16 |            1.01 |               1.05 |           
>   0.89 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | msg_sweep3d.sp |    62865612.00 |  1.01 |      2.80 |     1.02 |         
> 1.68 |   5.50 |       9.41 |            2.76 |               1.66 |           
>   1.71 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | num_brain.sp   |    70920000.00 |  1.00 |      1.31 |     1.00 |         
> 1.30 |   1.13 |       1.43 |            1.31 |               1.30 |           
>   1.27 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | num_comet.sp   |    53673984.00 |  1.08 |      1.27 |     1.08 |         
> 1.27 |   1.15 |       1.36 |            1.17 |               1.18 |           
>   1.18 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | num_control.sp |    79752372.00 |  1.01 |      1.12 |     1.01 |         
> 1.13 |   1.08 |       1.21 |            1.11 |               1.12 |           
>   1.12 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | num_plasma.sp  |    17544800.00 |  1.00 |    140.74 |     1.01 |         
> 1.30 | 279.49 |     310.68 |          141.29 |               1.30 |           
>   1.11 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | obs_error.sp   |    31080408.00 |  1.12 |      1.37 |     1.16 |         
> 1.29 |   1.73 |       3.10 |            1.22 |               1.11 |           
>   1.80 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | obs_info.sp    |     9465264.00 |  1.07 |      1.42 |     1.00 |         
> 1.29 |   2.25 |       3.04 |            1.33 |               1.29 |           
>   1.35 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | obs_spitzer.sp |    99090432.00 |  1.02 |      1.11 |     1.01 |         
> 1.12 |   1.20 |       1.31 |            1.09 |               1.10 |           
>   1.09 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | obs_temp.sp    |    19967136.00 |  1.00 |      1.12 |     1.00 |         
> 1.13 |   1.08 |       1.19 |            1.12 |               1.13 |           
>   1.10 |
> +----------------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> {code}
> h3. Comments
> The additional efficiency of the byte-stream-split encoding step is very 
> significant on most files (except {{obs_temp.sp}} which generally doesn't 
> compress at all), with additional gains usually around 30%.
> The byte-stream-split encoding test is, perhaps surprisingly, on average as 
> beneficial on Float16 data as it is on Float32 data.
> h2. Decimal data from OpenStreetMap changesets
> I've downloaded one of the recent OSM changesets file 
> {{changesets-231030.orc}}, and loaded the four decimal columns from the first 
> stripe of that file. Those columns look like:
> {code}
> pyarrow.RecordBatch
> min_lat: decimal128(9, 7)
> max_lat: decimal128(9, 7)
> min_lon: decimal128(10, 7)
> max_lon: decimal128(10, 7)
> ----
> min_lat: 
> [51.5288506,51.0025063,51.5326805,51.5248871,51.5266800,51.5261841,51.5264130,51.5238914,59.9463692,59.9513092,...,50.8238277,52.1707376,44.2701598,53.1589748,43.5988333,37.7867167,45.5448822,null,50.7998334,50.5653478]
> max_lat: 
> [51.5288620,51.0047760,51.5333176,51.5289383,51.5291901,51.5300598,51.5264130,51.5238914,59.9525642,59.9561501,...,50.8480772,52.1714300,44.3790161,53.1616817,43.6001496,37.7867913,45.5532716,null,51.0188961,50.5691352]
> min_lon: 
> [-0.1465242,-1.0052705,-0.1566335,-0.1485492,-0.1418076,-0.1550623,-0.1539768,-0.1432930,10.7782278,10.7719727,...,10.6863813,13.2218676,19.8840738,8.9128186,1.4030591,-122.4212761,18.6789571,null,-4.2085209,8.6851671]
> max_lon: 
> [-0.1464925,-0.9943439,-0.1541054,-0.1413791,-0.1411505,-0.1453212,-0.1539768,-0.1432930,10.7898550,10.7994537,...,10.7393494,13.2298706,20.2262343,8.9183611,1.4159345,-122.4212503,18.6961594,null,-4.0496079,8.6879264]
> {code}
> Here are the compression measurements using the same methodology as above. 
> The number of byte-stream-split streams is the respective byte width of each 
> FLBA column (i.e., 4 for latitudes and 5 for longitudes).
> {code}
> +---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | name    |   uncompressed |   lz4 |   bss_lz4 |   snappy |   bss_snappy |   
> zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   bss_ratio_zstd |
> +=========+================+=======+===========+==========+==============+========+============+=================+====================+==================+
> | min_lat |     4996652.00 |  1.00 |      1.01 |     1.00 |         1.03 |   
> 1.05 |       1.12 |            1.01 |               1.03 |             1.07 |
> +---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | max_lat |     4996652.00 |  1.00 |      1.01 |     1.00 |         1.03 |   
> 1.05 |       1.13 |            1.01 |               1.03 |             1.07 |
> +---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | min_lon |     6245825.00 |  1.00 |      1.14 |     1.00 |         1.16 |   
> 1.15 |       1.31 |            1.14 |               1.16 |             1.14 |
> +---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | max_lon |     6245825.00 |  1.00 |      1.14 |     1.00 |         1.16 |   
> 1.15 |       1.31 |            1.14 |               1.16 |             1.14 |
> +---------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> {code}
> h3. Comments
> On this dataset, compression efficiency is generally quite poor and 
> byte-stream-split encoding brings almost no additional efficiency to the 
> table. It can be assumed that OSM changeset entries have geographical 
> coordinates all over the place (literally!) and therefore do not offer many 
> opportunities for compression.
> h2. Decimal data from an OpenStreetMap region
> I've chosen a small region of the world (Belgium) whose geographical 
> coordinates presumably allow for better compression by being much more 
> clustered. The file {{belgium-latest.osm.pbf}} was converted to ORC for 
> easier handling, resulting in a 745 MB ORC file.
> I've then loaded the decimal columns from the first stripe in that file:
> {code}
> pyarrow.RecordBatch
> lat: decimal128(9, 7)
> lon: decimal128(10, 7)
> ----
> lat: 
> [50.4443865,50.4469017,50.4487890,50.4499558,50.4523446,50.4536530,50.4571053,50.4601436,50.4631197,50.4678563,...,51.1055899,51.1106197,51.1049620,51.1047010,51.1104755,51.0997955,51.1058101,51.1010664,51.1014336,51.1055106]
> lon: 
> [3.6857362,3.6965046,3.7074481,3.7173626,3.8126033,3.9033178,3.9193678,3.9253319,3.9292409,3.9332670,...,4.6663214,4.6699997,4.6720536,4.6655159,4.6666372,4.6680394,4.6747172,4.6684242,4.6713693,4.6644899]
> {code}
> Here are the compression measurements for these columns:
> {code}
> +--------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | name   |   uncompressed |   lz4 |   bss_lz4 |   snappy |   bss_snappy |   
> zstd |   bss_zstd |   bss_ratio_lz4 |   bss_ratio_snappy |   bss_ratio_zstd |
> +========+================+=======+===========+==========+==============+========+============+=================+====================+==================+
> | lat    |    12103680.00 |  1.00 |      1.63 |     1.00 |         1.63 |   
> 1.18 |       1.73 |            1.63 |               1.63 |             1.47 |
> +--------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> | lon    |    15129600.00 |  1.00 |      1.93 |     1.00 |         1.90 |   
> 1.27 |       2.06 |            1.93 |               1.90 |             1.62 |
> +--------+----------------+-------+-----------+----------+--------------+--------+------------+-----------------+--------------------+------------------+
> {code}
> h3. Comments
> This dataset shows that a byte-stream-split encoding test before compression 
> achieves a very significant additional efficiency compared to compression 
> alone.
> h2. Discussion
> h3. Benefits
> These examples show that extending the BYTE_STREAM_SPLIT encoding to 
> FIXED_LEN_BYTE_ARRAY columns (even regardless of their logical types) can 
> yield very significant compression efficiency improvements on two specific 
> types of FIXED_LEN_BYTE_ARRAY data: FLOAT16 data and DECIMAL data.
> h3. Implementation complexity
> BYTE_STREAM_SPLIT, even byte width-agnostic, is almost trivial to implement. 
> A simple implementation can yield good performance with a minimum of work.
> For example, the non-SIMD-optimized BYTE_STREAM_SPLIT encoding and decoding 
> routines in Parquet C++ amount to a mere total of ~200 lines of code, despite 
> explicitly-unrolled loops:
> https://github.com/apache/arrow/blob/4e58f7ca0016c2b2d8a859a0c5965df3b15523e0/cpp/src/arrow/util/byte_stream_split_internal.h#L593-L702
> These routines achieve several GB/s on FLOAT and DOUBLE data, both for 
> encoding and decoding.
> h2. TODO
> Try to make the tables above nicer :-)



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to