ΠΡΠ΅Π²ΠΎΠ΄ΠΎΡ Π½Π° ΡΡΠ°ΡΠΈΡΠ°ΡΠ° Π΅ ΠΏΠΎΠ΄Π³ΠΎΡΠ²Π΅Π½ ΡΠΏΠ΅ΡΠΈΡΠ°Π»Π½ΠΎ Π·Π° ΡΡΡΠ΄Π΅Π½ΡΠΈΡΠ΅ Π½Π° ΠΊΡΡΡΠΎΡ
ΠΠΎ ΡΠ΅ΠΊΠΎΡ Π½Π° ΠΈΠ·ΠΌΠΈΠ½Π°ΡΠΈΡΠ΅ Π½Π΅ΠΊΠΎΠ»ΠΊΡ Π½Π΅Π΄Π΅Π»ΠΈ, Π½ΠΈΠ΅
ΠΡΠ΅Π½ΠΎΡ Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΎΠ΄ ΠΊΠΎΠ»ΠΎΠ½Π°
Π§Π΅ΡΡΠΎΡΠΎ ΠΏΡΠ°ΡΠ°ΡΠ΅ ΡΡΠΎ Π³ΠΎ Π΄ΠΎΠ±ΠΈΠ²Π°ΠΌ ΠΎΠ΄ ΠΊΠΎΡΠΈΡΠ½ΠΈΡΠΈΡΠ΅ Π½Π° Arrow Π΅ Π²ΠΈΡΠΎΠΊΠ°ΡΠ° ΡΠ΅Π½Π° Π·Π° ΠΌΠΈΠ³ΡΠΈΡΠ°ΡΠ΅ Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈ ΡΠ°Π±Π΅Π»Π°ΡΠ½ΠΈ Π·Π±ΠΈΡΠΊΠΈ Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΎΠ΄ ΡΠΎΡΠΌΠ°Ρ ΠΎΡΠΈΠ΅Π½ΡΠΈΡΠ°Π½ ΠΊΠΎΠ½ ΡΠ΅Π΄ ΠΈΠ»ΠΈ Π·Π°ΠΏΠΈΡ Π²ΠΎ ΡΠΎΡΠΌΠ°Ρ Π½Π° ΠΊΠΎΠ»ΠΎΠ½Π°. ΠΠ° Π·Π±ΠΈΡΠΊΠΈ Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΎΠ΄ ΠΏΠΎΠ²Π΅ΡΠ΅ Π³ΠΈΠ³Π°Π±Π°ΡΡΠΈ, ΡΡΠ°Π½ΡΠΏΠΎΠ½ΠΈΡΠ°ΡΠ΅ΡΠΎ Π²ΠΎ ΠΌΠ΅ΠΌΠΎΡΠΈΡΠ° ΠΈΠ»ΠΈ Π½Π° Π΄ΠΈΡΠΊ ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΠΈΠ΄Π΅ ΠΎΠ³ΡΠΎΠΌΠ½ΠΎ.
ΠΠ° ΠΏΡΠ΅Π½ΠΎΡ Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ, Π±Π΅Π· ΡΠ°Π·Π»ΠΈΠΊΠ° Π΄Π°Π»ΠΈ ΠΈΠ·Π²ΠΎΡΠ½ΠΈΡΠ΅ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΡΠ΅ ΡΠ΅Π΄ ΠΈΠ»ΠΈ ΠΊΠΎΠ»ΠΎΠ½Π°, Π΅Π΄Π½Π° ΠΎΠΏΡΠΈΡΠ° Π΅ Π΄Π° ΡΠ΅ ΠΈΡΠΏΡΠ°ΡΠ°Ρ ΠΌΠ°Π»ΠΈ ΡΠ΅ΡΠΈΠΈ ΠΎΠ΄ ΡΠ΅Π΄ΠΎΠ²ΠΈ, ΠΎΠ΄ ΠΊΠΎΠΈ ΡΠ΅ΠΊΠΎΡΠ° ΡΠ΅ ΡΠΎΠ΄ΡΠΆΠΈ ΡΠ°ΡΠΏΠΎΡΠ΅Π΄ Π½Π° ΠΊΠΎΠ»ΠΎΠ½Π° Π²Π½Π°ΡΡΠ΅.
ΠΠΎ Apache Arrow, Π·Π±ΠΈΡΠΊΠ°ΡΠ° ΠΎΠ΄ ΠΊΠΎΠ»ΠΎΠ½ΠΎΠΎΠ±ΡΠ°Π·Π½ΠΈ Π½ΠΈΠ·ΠΈ Π²ΠΎ ΠΌΠ΅ΠΌΠΎΡΠΈΡΠ°ΡΠ° ΡΡΠΎ ΠΏΡΠ΅ΡΡΡΠ°Π²ΡΠ²Π°Π°Ρ Π΄Π΅Π» ΠΎΠ΄ ΡΠ°Π±Π΅Π»Π°ΡΠ° ΡΠ΅ Π½Π°ΡΠ΅ΠΊΡΠ²Π° ΡΠ΅ΡΠΈΡΠ° Π½Π° Π·Π°ΠΏΠΈΡΠΈ. ΠΠ° Π΄Π° ΠΏΡΠ΅ΡΡΡΠ°Π²ΠΈΡΠ΅ Π΅Π΄Π½Π° ΡΡΡΡΠΊΡΡΡΠ° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ Π½Π° Π»ΠΎΠ³ΠΈΡΠΊΠ° ΡΠ°Π±Π΅Π»Π°, ΠΌΠΎΠΆΠ΅ΡΠ΅ Π΄Π° ΡΠΎΠ±Π΅ΡΠ΅ΡΠ΅ Π½Π΅ΠΊΠΎΠ»ΠΊΡ ΠΏΠ°ΠΊΠ΅ΡΠΈ Π·Π°ΠΏΠΈΡΠΈ.
ΠΠΎ ΠΏΠΎΡΡΠΎΠ΅ΡΠΊΠΈΠΎΡ ΡΠΎΡΠΌΠ°Ρ Π½Π° Π΄Π°ΡΠΎΡΠ΅ΠΊΠ° ΡΠΎ βΡΠ»ΡΡΠ°Π΅Π½ ΠΏΡΠΈΡΡΠ°ΠΏβ, ΠΏΠΈΡΡΠ²Π°ΠΌΠ΅ ΠΌΠ΅ΡΠ°ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΡΡΠΎ ΡΠ° ΡΠΎΠ΄ΡΠΆΠ°Ρ ΡΠ΅ΠΌΠ°ΡΠ° Π½Π° ΡΠ°Π±Π΅Π»Π°ΡΠ° ΠΈ ΡΠ°ΡΠΏΠΎΡΠ΅Π΄ΠΎΡ Π½Π° Π±Π»ΠΎΠΊΠΎΠ²ΠΈ Π½Π° ΠΊΡΠ°ΡΠΎΡ ΠΎΠ΄ Π΄Π°ΡΠΎΡΠ΅ΠΊΠ°ΡΠ°, ΡΡΠΎ Π²ΠΈ ΠΎΠ²ΠΎΠ·ΠΌΠΎΠΆΡΠ²Π° Π΄Π° ΠΈΠ·Π±Π΅ΡΠ΅ΡΠ΅ ΠΊΠΎΡΠ° Π±ΠΈΠ»ΠΎ ΡΠ΅ΡΠΈΡΠ° Π½Π° Π·Π°ΠΏΠΈΡΠΈ ΠΈΠ»ΠΈ ΠΊΠΎΡΠ° Π±ΠΈΠ»ΠΎ ΠΊΠΎΠ»ΠΎΠ½Π° ΠΎΠ΄ ΡΠ΅ΡΠΎΡ Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΌΠ½ΠΎΠ³Ρ Π΅Π²ΡΠΈΠ½ΠΎ. ΠΠΎ ΡΡΡΠΈΠΌΠΈΠ½Π³ ΡΠΎΡΠΌΠ°Ρ, ΠΈΡΠΏΡΠ°ΡΠ°ΠΌΠ΅ ΡΠ΅ΡΠΈΡΠ° ΠΏΠΎΡΠ°ΠΊΠΈ: ΡΠ΅ΠΌΠ°, Π° ΠΏΠΎΡΠΎΠ° Π΅Π΄Π½Π° ΠΈΠ»ΠΈ ΠΏΠΎΠ²Π΅ΡΠ΅ Π³ΡΡΠΏΠΈ Π·Π°ΠΏΠΈΡΠΈ.
Π Π°Π·Π»ΠΈΡΠ½ΠΈΡΠ΅ ΡΠΎΡΠΌΠ°ΡΠΈ ΠΈΠ·Π³Π»Π΅Π΄Π°Π°Ρ Π½Π΅ΡΡΠΎ ΠΊΠ°ΠΊΠΎ ΠΎΠ²Π°Π° ΡΠ»ΠΈΠΊΠ°:
Π‘ΡΡΠΈΠΌΠΈΠ½Π³ Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ Π²ΠΎ PyArrow: Π°ΠΏΠ»ΠΈΠΊΠ°ΡΠΈΡΠ°
ΠΠ° Π΄Π° Π²ΠΈ ΠΏΠΎΠΊΠ°ΠΆΠ°ΠΌ ΠΊΠ°ΠΊΠΎ ΡΡΠ½ΠΊΡΠΈΠΎΠ½ΠΈΡΠ°, ΡΠ΅ ΡΠΎΠ·Π΄Π°Π΄Π°ΠΌ ΠΏΡΠΈΠΌΠ΅Ρ Π½Π° Π±Π°Π·Π° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΡΡΠΎ ΠΏΡΠ΅ΡΡΡΠ°Π²ΡΠ²Π° Π΅Π΄ΠΈΠ½Π΅ΡΠ΅Π½ Π΄Π΅Π» ΠΎΠ΄ ΠΏΡΠ΅Π½ΠΎΡΠΎΡ:
import time
import numpy as np
import pandas as pd
import pyarrow as pa
def generate_data(total_size, ncols):
nrows = int(total_size / ncols / np.dtype('float64').itemsize)
return pd.DataFrame({
'c' + str(i): np.random.randn(nrows)
for i in range(ncols)
})
Π‘Π΅Π³Π°, Π΄Π° ΠΏΡΠ΅ΡΠΏΠΎΡΡΠ°Π²ΠΈΠΌΠ΅ Π΄Π΅ΠΊΠ° ΡΠ°ΠΊΠ°ΠΌΠ΅ Π΄Π° Π½Π°ΠΏΠΈΡΠ΅ΠΌΠ΅ 1 GB ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ, ΡΠΎΡΡΠ°Π²Π΅Π½ΠΈ ΠΎΠ΄ ΠΏΠΎ 1 MB ΠΏΠ°ΡΡΠΈΡΠ°, Π·Π° Π²ΠΊΡΠΏΠ½ΠΎ 1024 ΠΏΠ°ΡΡΠΈΡΠ°. ΠΡΠ²ΠΎ, Π΄Π° ΡΠ° ΡΠΎΠ·Π΄Π°Π΄Π΅ΠΌΠ΅ ΠΏΡΠ²Π°ΡΠ° ΠΏΠΎΠ΄Π°ΡΠΎΡΠ½Π° ΡΠ°ΠΌΠΊΠ° ΠΎΠ΄ 1MB ΡΠΎ 16 ΠΊΠΎΠ»ΠΎΠ½ΠΈ:
KILOBYTE = 1 << 10
MEGABYTE = KILOBYTE * KILOBYTE
DATA_SIZE = 1024 * MEGABYTE
NCOLS = 16
df = generate_data(MEGABYTE, NCOLS)
ΠΠΎΡΠΎΠ° Π³ΠΈ ΠΏΡΠ΅ΡΠ²ΠΎΡΠ°ΠΌ Π²ΠΎ pyarrow.RecordBatch
:
batch = pa.RecordBatch.from_pandas(df)
Π‘Π΅Π³Π° ΡΠ΅ ΡΠΎΠ·Π΄Π°Π΄Π°ΠΌ ΠΈΠ·Π»Π΅Π·Π΅Π½ ΠΏΠΎΡΠΎΠΊ ΡΡΠΎ ΡΠ΅ ΠΏΠΈΡΡΠ²Π° Π²ΠΎ RAM ΠΈ ΡΠ΅ ΠΊΡΠ΅ΠΈΡΠ° StreamWriter
:
sink = pa.InMemoryOutputStream()
stream_writer = pa.StreamWriter(sink, batch.schema)
ΠΠΎΡΠΎΠ° ΡΠ΅ Π½Π°ΠΏΠΈΡΠ΅ΠΌΠ΅ 1024 ΠΏΠ°ΡΡΠΈΡΠ°, ΠΊΠΎΠΈ Π½Π° ΠΊΡΠ°ΡΠΎΡ ΡΠ΅ ΡΠΎΡΠΈΠ½ΡΠ²Π°Π°Ρ Π±Π°Π·Π° Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΎΠ΄ 1 GB:
for i in range(DATA_SIZE // MEGABYTE):
stream_writer.write_batch(batch)
ΠΠΈΠ΄Π΅ΡΡΠΈ ΠΏΠΈΡΡΠ²Π°Π²ΠΌΠ΅ Π²ΠΎ RAM ΠΌΠ΅ΠΌΠΎΡΠΈΡΠ°, ΠΌΠΎΠΆΠ΅ΠΌΠ΅ Π΄Π° Π³ΠΎ Π΄ΠΎΠ±ΠΈΠ΅ΠΌΠ΅ ΡΠ΅Π»ΠΈΠΎΡ ΠΏΠΎΡΠΎΠΊ Π²ΠΎ Π΅Π΄Π΅Π½ Π±Π°ΡΠ΅Ρ:
In [13]: source = sink.get_result()
In [14]: source
Out[14]: <pyarrow.io.Buffer at 0x7f2df7118f80>
In [15]: source.size
Out[15]: 1074750744
ΠΠΈΠ΄Π΅ΡΡΠΈ ΠΎΠ²ΠΈΠ΅ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΡΠ΅ Π²ΠΎ ΠΌΠ΅ΠΌΠΎΡΠΈΡΠ°, ΡΠΈΡΠ°ΡΠ΅ΡΠΎ Π½Π° ΡΠ΅ΡΠΈΠΈ Π·Π°ΠΏΠΈΡΠΈ ΡΠΎ ΡΡΡΠ΅Π»ΠΊΠΈ ΡΠ΅ Π΄ΠΎΠ±ΠΈΠ²Π° ΡΠΎ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΡΠ° Π½Π° Π½ΡΠ»ΡΠ° ΠΊΠΎΠΏΠΈΡΠ°ΡΠ΅. ΠΠΎ ΠΎΡΠ²ΠΎΡΠ°ΠΌ StreamReader, ΡΠΈΡΠ°ΠΌ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ Π²ΠΎ pyarrow.Table
Π° ΠΏΠΎΡΠΎΠ° ΠΏΡΠ΅ΡΠ²ΠΎΡΠ΅ΡΠ΅ Π³ΠΈ Π²ΠΎ DataFrame pandas
:
In [16]: reader = pa.StreamReader(source)
In [17]: table = reader.read_all()
In [18]: table
Out[18]: <pyarrow.table.Table at 0x7fae8281f6f0>
In [19]: df = table.to_pandas()
In [20]: df.memory_usage().sum()
Out[20]: 1073741904
Π‘Π΅ΡΠΎ ΠΎΠ²Π°, ΡΠ΅ ΡΠ°Π·Π±ΠΈΡΠ°, Π΅ Π΄ΠΎΠ±ΡΠΎ, Π½ΠΎ ΠΌΠΎΠΆΠ΅Π±ΠΈ ΠΈΠΌΠ°ΡΠ΅ ΠΏΡΠ°ΡΠ°ΡΠ°. ΠΠΎΠ»ΠΊΡ Π±ΡΠ·ΠΎ ΡΠ΅ ΡΠ»ΡΡΡΠ²Π°? ΠΠ°ΠΊΠΎ Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°ΡΠ° Π½Π° Π΄Π΅Π»ΠΎΡ Π²Π»ΠΈΡΠ°Π΅ Π½Π° ΠΏΠ΅ΡΡΠΎΡΠΌΠ°Π½ΡΠΈΡΠ΅ Π½Π° ΠΏΠ°Π½Π΄ΠΈΡΠ΅ Π·Π° ΠΏΡΠ΅Π·Π΅ΠΌΠ°ΡΠ΅ DataFrame?
ΠΠ·Π²Π΅Π΄Π±Π° Π½Π° ΡΡΡΠΈΠΌΠΈΠ½Π³
ΠΠ°ΠΊΠΎ ΡΡΠΎ ΡΠ΅ Π½Π°ΠΌΠ°Π»ΡΠ²Π° Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°ΡΠ° Π½Π° ΡΡΡΠΈΠΌΠΈΠ½Π³ ΠΏΠ°ΡΡΠ΅ΡΠΎ, ΡΡΠΎΡΠΎΡΠΈΡΠ΅ Π·Π° ΡΠ΅ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΈΡΠ° Π½Π° ΡΠΎΡΠ΅Π΄Π½Π° ΠΊΠΎΠ»ΠΎΠ½ΠΎΠΎΠ±ΡΠ°Π·Π½Π° DataFrame ΠΊΠ°Ρ ΠΏΠ°Π½Π΄ΠΈΡΠ΅ ΡΠ΅ Π·Π³ΠΎΠ»Π΅ΠΌΡΠ²Π°Π°Ρ ΠΏΠΎΡΠ°Π΄ΠΈ Π½Π΅Π΅ΡΠΈΠΊΠ°ΡΠ½ΠΈΡΠ΅ ΡΠ΅ΠΌΠΈ Π·Π° ΠΏΡΠΈΡΡΠ°ΠΏ Π²ΠΎ ΠΊΠ΅ΡΠΎΡ. ΠΡΡΠΎ ΡΠ°ΠΊΠ°, ΠΈΠΌΠ° Π½Π΅ΠΊΠΎΠΈ ΡΡΠΎΡΠΎΡΠΈ Π·Π° ΡΠ°Π±ΠΎΡΠ° ΡΠΎ C++ ΠΏΠΎΠ΄Π°ΡΠΎΡΠ½ΠΈ ΡΡΡΡΠΊΡΡΡΠΈ ΠΈ Π½ΠΈΠ·ΠΈ ΠΈ Π½ΠΈΠ²Π½ΠΈΡΠ΅ ΠΌΠ΅ΠΌΠΎΡΠΈΡΠΊΠΈ Π±Π°ΡΠ΅ΡΠΈ.
ΠΠ° 1 MB ΠΊΠ°ΠΊΠΎ ΠΏΠΎΠ³ΠΎΡΠ΅, Π½Π° ΠΌΠΎΡΠΎΡ Π»Π°ΠΏΡΠΎΠΏ (Quad-core Xeon E3-1505M) ΠΈΠ·Π»Π΅Π³ΡΠ²Π°:
In [20]: %timeit pa.StreamReader(source).read_all().to_pandas()
10 loops, best of 3: 129 ms per loop
ΠΠ·Π»Π΅Π³ΡΠ²Π° Π΄Π΅ΠΊΠ° Π΅ΡΠ΅ΠΊΡΠΈΠ²Π½Π°ΡΠ° ΠΏΡΠΎΠΏΡΡΠ½ΠΎΡΡ Π΅ 7.75 Gb/s Π·Π° Π²ΡΠ°ΡΠ°ΡΠ΅ Π½Π° DataFrame ΠΎΠ΄ 1 GB ΠΎΠ΄ 1024 ΠΏΠ°ΡΡΠΈΡΠ° ΠΎΠ΄ 1 MB. Π¨ΡΠΎ ΡΠ΅ ΡΠ»ΡΡΡΠ²Π° Π°ΠΊΠΎ ΠΊΠΎΡΠΈΡΡΠΈΠΌΠ΅ ΠΏΠΎΠ³ΠΎΠ»Π΅ΠΌΠΈ ΠΈΠ»ΠΈ ΠΏΠΎΠΌΠ°Π»ΠΈ ΠΏΠ°ΡΡΠΈΡΠ°? ΠΠ²Π΅ Π³ΠΈ ΡΠ΅Π·ΡΠ»ΡΠ°ΡΠΈΡΠ΅ ΡΡΠΎ Π³ΠΈ Π΄ΠΎΠ±ΠΈΠ²Π°ΡΠ΅:
ΠΠ΅ΡΡΠΎΡΠΌΠ°Π½ΡΠΈΡΠ΅ Π·Π½Π°ΡΠΈΡΠ΅Π»Π½ΠΎ ΡΠ΅ Π½Π°ΠΌΠ°Π»ΡΠ²Π°Π°Ρ ΠΎΠ΄ 256K Π½Π° 64K ΠΏΠ°ΡΡΠΈΡΠ°. ΠΠ΅Π² ΠΈΠ·Π½Π΅Π½Π°Π΄Π΅Π½ ΡΡΠΎ Π΄Π΅Π»ΠΎΠ²ΠΈΡΠ΅ ΠΎΠ΄ 1MB Π±Π΅Π° ΠΎΠ±ΡΠ°Π±ΠΎΡΠ΅Π½ΠΈ ΠΏΠΎΠ±ΡΠ·ΠΎ ΠΎΠ΄ Π΄Π΅Π»ΠΎΠ²ΠΈΡΠ΅ ΠΎΠ΄ 16MB. ΠΡΠ΅Π΄ΠΈ Π΄Π° ΡΠ΅ Π½Π°ΠΏΡΠ°Π²ΠΈ ΠΏΠΎΡΠ΅ΠΌΠ΅Π»Π½Π° ΡΡΡΠ΄ΠΈΡΠ° ΠΈ Π΄Π° ΡΠ΅ ΡΠ°Π·Π±Π΅ΡΠ΅ Π΄Π°Π»ΠΈ ΠΎΠ²Π° Π΅ Π½ΠΎΡΠΌΠ°Π»Π½Π° Π΄ΠΈΡΡΡΠΈΠ±ΡΡΠΈΡΠ° ΠΈΠ»ΠΈ Π΅ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΎ Π½Π΅ΡΡΠΎ Π΄ΡΡΠ³ΠΎ.
ΠΠΎ ΡΠ΅ΠΊΠΎΠ²Π½Π°ΡΠ° ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ° Π½Π° ΡΠΎΡΠΌΠ°ΡΠΎΡ, ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈΡΠ΅ Π²ΠΎ ΠΏΡΠΈΠ½ΡΠΈΠΏ Π½Π΅ ΡΠ΅ ΠΊΠΎΠΌΠΏΡΠ΅ΡΠΈΡΠ°Π½ΠΈ, ΡΠ°ΠΊΠ° ΡΡΠΎ Π³ΠΎΠ»Π΅ΠΌΠΈΠ½Π°ΡΠ° Π²ΠΎ ΠΌΠ΅ΠΌΠΎΡΠΈΡΠ°ΡΠ° ΠΈ βΠ½Π° ΠΆΠΈΡΠ°β Π΅ ΠΏΡΠΈΠ±Π»ΠΈΠΆΠ½ΠΎ ΠΈΡΡΠ°. ΠΠΎΠΌΠΏΡΠ΅ΡΠΈΡΠ°ΡΠ° ΠΌΠΎΠΆΠ΅ Π΄Π° ΡΡΠ°Π½Π΅ ΠΎΠΏΡΠΈΡΠ° Π²ΠΎ ΠΈΠ΄Π½ΠΈΠ½Π°.
ΠΠΊΡΠΏΠ½ΠΎ
ΠΡΠ΅Π½Π΅ΡΡΠ²Π°ΡΠ΅ΡΠΎ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΠΎΠ΄ ΠΊΠΎΠ»ΠΎΠ½ΠΈ ΠΌΠΎΠΆΠ΅ Π΄Π° Π±ΠΈΠ΄Π΅ Π΅ΡΠΈΠΊΠ°ΡΠ΅Π½ Π½Π°ΡΠΈΠ½ Π·Π° ΠΏΡΠ΅Π½ΠΎΡ Π½Π° Π³ΠΎΠ»Π΅ΠΌΠΈ Π·Π±ΠΈΡΠΊΠΈ Π½Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ Π²ΠΎ Π°Π»Π°ΡΠΊΠΈ Π·Π° Π°Π½Π°Π»ΠΈΠ·Π° Π½Π° ΠΊΠΎΠ»ΠΎΠ½ΠΈ, ΠΊΠ°ΠΊΠΎ ΡΡΠΎ ΡΠ΅ ΠΏΠ°Π½Π΄ΠΈΡΠ΅ Π²ΠΎ ΠΌΠ°Π»ΠΈ Π΄Π΅Π»ΠΎΠ²ΠΈ. Π£ΡΠ»ΡΠ³ΠΈΡΠ΅ Π·Π° ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΡΡΠΎ ΠΊΠΎΡΠΈΡΡΠ°Ρ ΡΠΊΠ»Π°Π΄ΠΈΡΠ°ΡΠ΅ ΠΎΡΠΈΠ΅Π½ΡΠΈΡΠ°Π½ΠΈ ΠΊΠΎΠ½ ΡΠ΅Π΄ ΠΌΠΎΠΆΠ΅ Π΄Π° ΠΏΡΠ΅ΡΡΠ»Π°Π°Ρ ΠΈ ΡΡΠ°Π½ΡΠΏΠΎΠ½ΠΈΡΠ°Π°Ρ ΠΌΠ°Π»ΠΈ Π΄Π΅Π»ΠΎΠ²ΠΈ ΠΎΠ΄ ΠΏΠΎΠ΄Π°ΡΠΎΡΠΈ ΡΡΠΎ ΡΠ΅ ΠΏΠΎΠΏΠΎΠ³ΠΎΠ΄Π½ΠΈ Π·Π° ΠΊΠ΅ΡΠΎΡ L2 ΠΈ L3 Π½Π° Π²Π°ΡΠΈΠΎΡ ΠΏΡΠΎΡΠ΅ΡΠΎΡ.
Π¦Π΅Π»ΠΎΡΠ΅Π½ ΠΊΠΎΠ΄
import time
import numpy as np
import pandas as pd
import pyarrow as pa
def generate_data(total_size, ncols):
nrows = total_size / ncols / np.dtype('float64').itemsize
return pd.DataFrame({
'c' + str(i): np.random.randn(nrows)
for i in range(ncols)
})
KILOBYTE = 1 << 10
MEGABYTE = KILOBYTE * KILOBYTE
DATA_SIZE = 1024 * MEGABYTE
NCOLS = 16
def get_timing(f, niter):
start = time.clock_gettime(time.CLOCK_REALTIME)
for i in range(niter):
f()
return (time.clock_gettime(time.CLOCK_REALTIME) - start) / NITER
def read_as_dataframe(klass, source):
reader = klass(source)
table = reader.read_all()
return table.to_pandas()
NITER = 5
results = []
CHUNKSIZES = [16 * KILOBYTE, 64 * KILOBYTE, 256 * KILOBYTE, MEGABYTE, 16 * MEGABYTE]
for chunksize in CHUNKSIZES:
nchunks = DATA_SIZE // chunksize
batch = pa.RecordBatch.from_pandas(generate_data(chunksize, NCOLS))
sink = pa.InMemoryOutputStream()
stream_writer = pa.StreamWriter(sink, batch.schema)
for i in range(nchunks):
stream_writer.write_batch(batch)
source = sink.get_result()
elapsed = get_timing(lambda: read_as_dataframe(pa.StreamReader, source), NITER)
result = (chunksize, elapsed)
print(result)
results.append(result)
ΠΠ·Π²ΠΎΡ: www.habr.com