เบเบฒเบ™เบ–เปˆเบฒเบเบ—เบญเบ”เบ‚เปเป‰เบกเบนเบ™เบ–เบฑเบ™เบเบฑเบš Apache Arrow

เบเบฒเบ™เปเบ›เบžเบฒเบชเบฒเบ‚เบญเบ‡เบšเบปเบ”เบ„เบงเบฒเบกเป„เบ”เป‰เบ–เบทเบเบเบฐเบเบฝเบกเป‚เบ”เบเบชเบฐเป€เบžเบฒเบฐเบชเปเบฒเบฅเบฑเบšเบ™เบฑเบเบชเบถเบเบชเบฒเบ‚เบญเบ‡เบซเบผเบฑเบเบชเบนเบ” เบงเบดเบชเบฐเบงเบฐเบเบญเบ™เบ‚เปเป‰เบกเบนเบ™.

เบเบฒเบ™เบ–เปˆเบฒเบเบ—เบญเบ”เบ‚เปเป‰เบกเบนเบ™เบ–เบฑเบ™เบเบฑเบš Apache Arrow

เปƒเบ™เป„เบฅเบเบฐเบชเบญเบ‡เบชเบฒเบกเบญเบฒเบ—เบดเบ”เบœเปˆเบฒเบ™เบกเบฒ, เบžเบงเบเป€เบฎเบปเบฒ เปœเบญเบ‡เบฅเบต เป€เบžเบตเปˆเบกเปƒเบชเปˆ Apache Arrow เบฎเบนเบšโ€‹เปเบšเบšโ€‹เบชเบฐโ€‹เบ•โ€‹เบฃเบตเบกโ€‹เบ„เบนเปˆโ€‹, เป€เบชเบตเบกโ€‹เบเบฒเบ™โ€‹เป€เบ‚เบปเป‰เบฒโ€‹เป€เบ–เบดเบ‡โ€‹เปเบšเบšโ€‹เบชเบธเปˆเบกโ€‹เบ—เบตเปˆโ€‹เบกเบตโ€‹เบขเบนเปˆโ€‹เปเบฅเป‰เบง / เบฎเบนเบšโ€‹เปเบšเบšโ€‹เป„เบŸเบฅโ€‹เปŒ IPCโ€‹. เบžเบงเบเป€เบฎเบปเบฒเบกเบตเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ” Java เปเบฅเบฐ C++ เปเบฅเบฐเบเบฒเบ™เบœเบนเบเบกเบฑเบ” Python. เปƒเบ™เบšเบปเบ”เบ„เบงเบฒเบกเบ™เบตเป‰, เบ‚เป‰เบฒเบžเบฐเป€เบˆเบปเป‰เบฒเบˆเบฐเบญเบฐเบ—เบดเบšเบฒเบเบงเบดเบ—เบตเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบ‚เบญเบ‡เบฎเบนเบšเปเบšเบšเปเบฅเบฐเบชเบฐเปเบ”เบ‡เปƒเบซเป‰เป€เบซเบฑเบ™เบงเบดเบ—เบตเบ—เบตเปˆเบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เบšเบฑเบ™เบฅเบธเบเบฒเบ™เบชเบปเปˆเบ‡เบ‚เปเป‰เบกเบนเบ™เบชเบนเบ‡เบซเบผเบฒเบเบชเปเบฒเบฅเบฑเบš pandas DataFrame.

เบเบฒเบ™เบ–เปˆเบฒเบเบ—เบญเบ”เบ‚เปเป‰เบกเบนเบ™เบ–เบฑเบ™

เบ„เปเบฒเบ–เบฒเบกเบ—เบปเปˆเบงเป„เบ›เบ—เบตเปˆเบ‚เป‰เบญเบเป„เบ”เป‰เบฎเบฑเบšเบˆเบฒเบเบœเบนเป‰เปƒเบŠเป‰ Arrow เปเบกเปˆเบ™เบ„เปˆเบฒเปƒเบŠเป‰เบˆเปˆเบฒเบเบชเบนเบ‡เปƒเบ™เบเบฒเบ™เป€เบ„เบทเปˆเบญเบ™เบเป‰เบฒเบเบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ‚เบฐเบซเบ™เบฒเบ”เปƒเบซเบเปˆเบˆเบฒเบเปเบ–เบงเบซเบผเบทเบฎเบนเบšเปเบšเบšเบšเบฑเบ™เบ—เบถเบเป€เบ›เบฑเบ™เบฎเบนเบšเปเบšเบšเบ„เปเบฅเปเบฒ. เบชเบณเบฅเบฑเบšเบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบซเบผเบฒเบเบเบดเบเบฒเป„เบš, เบเบฒเบ™เบ–เปˆเบฒเบเบ—เบญเบ”เปƒเบ™เปœเปˆเบงเบเบ„เบงเบฒเบกเบˆเบณ เบซเบผเบทเปƒเบ™เบ”เบดเบชเบเปŒเบญเบฒเบ”เป€เบ›เบฑเบ™เป€เบฅเบทเปˆเบญเบ‡เบ—เบตเปˆเปœเบฑเบเปœเปˆเบงเบ‡.

เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบ–เปˆเบฒเบเบ—เบญเบ”เบ‚เปเป‰เบกเบนเบ™, เบšเปเปˆเบงเปˆเบฒเบˆเบฐเป€เบ›เบฑเบ™เบ‚เปเป‰เบกเบนเบ™เปเบซเบผเปˆเบ‡เปเบกเปˆเบ™เปเบ–เบงเบซเบผเบทเบ–เบฑเบ™, เบ—เบฒเบ‡เป€เบฅเบทเบญเบเบซเบ™เบถเปˆเบ‡เปเบกเปˆเบ™เป€เบžเบทเปˆเบญเบชเบปเปˆเบ‡ batch เบ‚เบฐเบซเบ™เบฒเบ”เบ™เป‰เบญเบเบ‚เบญเบ‡เปเบ–เบง, เปเบ•เปˆเบฅเบฐเบ›เบฐเบเบญเบšเบ”เป‰เบงเบเป‚เบ„เบ‡เบฎเปˆเบฒเบ‡เบ–เบฑเบ™เบžเบฒเบเปƒเบ™.

เปƒเบ™ Apache Arrow, เบ„เปเป€เบฅเบฑเบเบŠเบฑเบ™เบ‚เบญเบ‡เบ–เบฑเบ™เบ–เบฑเบ™เปƒเบ™เปœเปˆเบงเบเบ„เบงเบฒเบกเบˆเบณเบ—เบตเปˆเป€เบ›เบฑเบ™เบ•เบปเบงเปเบ—เบ™เบ‚เบญเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เปเบกเปˆเบ™เป€เบญเบตเป‰เบ™เบงเปˆเบฒเบŠเบธเบ”เบšเบฑเบ™เบ—เบถเบ. เป€เบžเบทเปˆเบญเป€เบ›เบฑเบ™เบ•เบปเบงเปเบ—เบ™เบ‚เบญเบ‡เป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ‚เปเป‰เบกเบนเบ™เบ”เบฝเบงเบ‚เบญเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบขเปˆเบฒเบ‡เบกเบตเป€เบซเบ”เบœเบปเบ™, เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบเบฑเบšเบเปเบฒเบซเบผเบฒเบเบŠเบธเบ”เบ‚เบญเบ‡เบšเบฑเบ™เบ—เบถเบ.

เปƒเบ™เบฎเบนเบšเปเบšเบšเป„เบŸเบฅเปŒ "เบเบฒเบ™เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เปเบšเบšเบชเบธเปˆเบก" เบ—เบตเปˆเบกเบตเบขเบนเปˆเปเบฅเป‰เบง, เบžเบงเบเป€เบฎเบปเบฒเบ‚เบฝเบ™ metadata เบ—เบตเปˆเบกเบตเบ•เบฒเบ•เบฐเบฅเบฒเบ‡เบ•เบฒเบ•เบฐเบฅเบฒเบ‡เปเบฅเบฐเบฎเบนเบšเปเบšเบšเบ•เบฑเบ™เบขเบนเปˆเปƒเบ™เบ•เบญเบ™เบ—เป‰เบฒเบเบ‚เบญเบ‡เป„เบŸเบฅเปŒ, เป€เบŠเบดเปˆเบ‡เบŠเปˆเบงเบเปƒเบซเป‰เบ—เปˆเบฒเบ™เบชเบฒเบกเบฒเบ”เป€เบฅเบทเบญเบเป€เบญเบปเบฒเบŠเบธเบ”เบšเบฑเบ™เบ—เบถเบเบซเบผเบทเบ„เปเบฅเปเบฒเปƒเบ”เป†เบˆเบฒเบเบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเบกเบตเบฅเบฒเบ„เบฒเบ–เบทเบเบซเบผเบฒเบ. เปƒเบ™โ€‹เบฎเบนเบšโ€‹เปเบšเบšโ€‹เบเบฒเบ™โ€‹เบชเบฐโ€‹เบ•โ€‹เบฃเบตเบกโ€‹, เบžเบงเบโ€‹เป€เบฎเบปเบฒโ€‹เบชเบปเปˆเบ‡โ€‹เบŠเบธเบ”โ€‹เบ‚เบญเบ‡โ€‹เบ‚เปเป‰โ€‹เบ„เบงเบฒเบกโ€‹: schemaโ€‹, เปเบฅเบฐโ€‹เบซเบผเบฑเบ‡โ€‹เบˆเบฒเบโ€‹เบ™เบฑเป‰เบ™โ€‹เบซเบ™เบถเปˆเบ‡โ€‹เบซเบผเบทโ€‹เบซเบผเบฒเบโ€‹เบŠเบธเบ”โ€‹เบ‚เบญเบ‡โ€‹เบเบฒเบ™โ€‹เบšเบฑเบ™โ€‹เบ—เบถเบโ€‹.

เบฎเบนเบšเปเบšเบšเบ—เบตเปˆเปเบ•เบเบ•เปˆเบฒเบ‡เบเบฑเบ™เป€เบšเบดเปˆเบ‡เบ„เบทเบฎเบนเบšเบ™เบตเป‰:

เบเบฒเบ™เบ–เปˆเบฒเบเบ—เบญเบ”เบ‚เปเป‰เบกเบนเบ™เบ–เบฑเบ™เบเบฑเบš 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 เปเบ•เปˆเบฅเบฐ chunks, เบชเปเบฒเบฅเบฑเบšเบ—เบฑเบ‡เบซเบกเบปเบ” 1024 chunks. เบเปˆเบญเบ™เบญเบทเปˆเบ™, เปƒเบซเป‰เบชเป‰เบฒเบ‡เบเบญเบšเบ‚เปเป‰เบกเบนเบ™ 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 chunks, เป€เบŠเบดเปˆเบ‡เปƒเบ™เบ—เบตเปˆเบชเบธเบ”เบˆเบฐเบ›เบฐเบเบญเบšเป€เบ›เบฑเบ™เบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™ 1GB:

for i in range(DATA_SIZE // MEGABYTE):
    stream_writer.write_batch(batch)

เบ™เบฑเบšเบ•เบฑเป‰เบ‡เปเบ•เปˆเบžเบงเบเป€เบฎเบปเบฒเบ‚เบฝเบ™เปƒเบ™ RAM, เบžเบงเบเป€เบฎเบปเบฒเบชเบฒเบกเบฒเบ”เป„เบ”เป‰เบฎเบฑเบšเบ™เป‰เปเบฒเบ—เบฑเบ‡เบซเบกเบปเบ”เปƒเบ™ buffer เบ”เบฝเบง:

In [13]: source = sink.get_result()

In [14]: source
Out[14]: <pyarrow.io.Buffer at 0x7f2df7118f80>

In [15]: source.size
Out[15]: 1074750744

เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบงเปˆเบฒเบ‚เปเป‰เบกเบนเบ™เบ™เบตเป‰เบขเบนเปˆเปƒเบ™เบซเบ™เปˆเบงเบเบ„เบงเบฒเบกเบˆเปเบฒ, เบเบฒเบ™เบญเปˆเบฒเบ™ batches เบ‚เบญเบ‡ Arrow records เปเบกเปˆเบ™เป„เบ”เป‰เบฎเบฑเบšเป‚เบ”เบเบเบฒเบ™เบ”เปเบฒเป€เบ™เบตเบ™เบเบฒเบ™เบชเบนเบ™เบชเปเบฒเป€เบ™เบปเบฒ. เบ‚เป‰เบญเบเป€เบ›เบตเบ” 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

เบ—เบฑเบ‡เบซเบกเบปเบ”เบ™เบตเป‰, เปเบ™เปˆเบ™เบญเบ™, เปเบกเปˆเบ™เบ”เบต, เปเบ•เปˆเบ—เปˆเบฒเบ™เบญเบฒเบ”เบˆเบฐเบกเบตเบ„เปเบฒเบ–เบฒเบก. เบกเบฑเบ™เป€เบเบตเบ”เบ‚เบถเป‰เบ™เป„เบงเป€เบ—เบปเปˆเบฒเปƒเบ”? เบ‚เบฐเบซเบ™เบฒเบ”เบ‚เบญเบ‡ chunk เบกเบตเบœเบปเบ™เบเบฐเบ—เบปเบšเบ•เปเปˆเบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เบเบฒเบ™เบ”เบถเบ‡เบ‚เปเป‰เบกเบนเบ™ pandas DataFrame เปเบ™เบงเปƒเบ”?

เบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบเบฒเบ™เบ–เปˆเบฒเบเบ—เบญเบ”

เป€เบกเบทเปˆเบญเบ‚เบฐเปœเบฒเบ”เบ‚เบญเบ‡เบŠเปˆเบญเบ‡เบชเบฐเบ•เบฃเบตเบกเบกเบดเบ‡เบซเบผเบธเบ”เบฅเบปเบ‡, เบ„เปˆเบฒเปƒเบŠเป‰เบˆเปˆเบฒเบเบ‚เบญเบ‡เบเบฒเบ™เบชเป‰เบฒเบ‡เบ„เปเบฅเบณ DataFrame เบ•เบดเบ”เบ•เปเปˆเบเบฑเบ™เปƒเบ™ pandas เป€เบžเบตเปˆเบกเบ‚เบถเป‰เบ™เป€เบ™เบทเปˆเบญเบ‡เบˆเบฒเบเบฅเบฐเบšเบปเบšเบเบฒเบ™เป€เบ‚เบปเป‰เบฒเป€เบ–เบดเบ‡เปเบ„เบ”เบšเปเปˆเบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบš. เบ™เบญเบเบˆเบฒเบเบ™เบตเป‰เบเบฑเบ‡เบกเบตเบšเบฒเบ‡เบชเปˆเบงเบ™เป€เบเบตเบ™เบˆเบฒเบเบเบฒเบ™เป€เบฎเบฑเบ”เบงเบฝเบเบเบฑเบšเป‚เบ„เบ‡เบชเป‰เบฒเบ‡เบ‚เปเป‰เบกเบนเบ™ C ++ เปเบฅเบฐ arrays เปเบฅเบฐ buffers เบ„เบงเบฒเบกเบŠเบปเบ‡เบˆเปเบฒเบ‚เบญเบ‡เบžเบงเบเป€เบ‚เบปเบฒ.

เบชเปเบฒเบฅเบฑเบš 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

เบกเบฑเบ™ turns เปƒเบซเป‰เป€เบซเบฑเบ™เบงเปˆเบฒ throughput เบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเปเบกเปˆเบ™ 7.75 Gb / s เบชเปเบฒเบฅเบฑเบšเบเบฒเบ™เบŸเบทเป‰เบ™เบŸเบน 1 GB DataFrame เบˆเบฒเบ 1024 1 MB chunks. เบˆเบฐเป€เบเบตเบ”เบซเบเบฑเบ‡เบ‚เบถเป‰เบ™เบ–เป‰เบฒเบžเบงเบเป€เบฎเบปเบฒเปƒเบŠเป‰เบ•เปˆเบญเบ™เปƒเบซเบเปˆ เบซเบผเบทเบ™เป‰เบญเบเบเบงเปˆเบฒ? เบ™เบตเป‰เปเบกเปˆเบ™เบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบšเบ—เบตเปˆเบ—เปˆเบฒเบ™เป„เบ”เป‰เบฎเบฑเบš:

เบเบฒเบ™เบ–เปˆเบฒเบเบ—เบญเบ”เบ‚เปเป‰เบกเบนเบ™เบ–เบฑเบ™เบเบฑเบš Apache Arrow

เบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเบซเบผเบธเบ”เบฅเบปเบ‡เบขเปˆเบฒเบ‡เบซเบผเบงเบ‡เบซเบผเบฒเบเบˆเบฒเบ 256K เบซเบฒ 64K chunks. เบ‚เป‰เบฒโ€‹เบžเบฐโ€‹เป€เบˆเบปเป‰เบฒโ€‹เบ•เบปเบโ€‹เบ•เบฐโ€‹เบฅเบถเบ‡โ€‹เบ—เบตเปˆ chunks 1MB เบ–เบทเบโ€‹เบ›เบธเบ‡โ€‹เปเบ•เปˆเบ‡โ€‹เป„เบงโ€‹เบโ€‹เปˆโ€‹เบงเบฒ 16MB chunksโ€‹. เบกเบฑเบ™เบ„เบธเป‰เบกเบ„เปˆเบฒเบ—เบตเปˆเบˆเบฐเป€เบฎเบฑเบ”เบเบฒเบ™เบชเบถเบเบชเบฒเบขเปˆเบฒเบ‡เบฅเบฐเบญเบฝเบ”เบเบงเปˆเบฒเปเบฅเบฐเป€เบ‚เบปเป‰เบฒเปƒเบˆเบงเปˆเบฒเบ™เบตเป‰เปเบกเปˆเบ™เบเบฒเบ™เปเบˆเบเบขเบฒเบเบ›เบปเบเบเบฐเบ•เบดเบซเบผเบทเบšเบฒเบ‡เบชเบดเปˆเบ‡เบšเบฒเบ‡เบขเปˆเบฒเบ‡เบ—เบตเปˆเบเปˆเบฝเบงเบ‚เป‰เบญเบ‡.

เปƒเบ™เบเบฒเบ™เบ›เบฐเบ•เบดเบšเบฑเบ”เปƒเบ™เบ›เบฐเบˆเบธเบšเบฑเบ™เบ‚เบญเบ‡เบฎเบนเบšเปเบšเบš, เบ‚เปเป‰เบกเบนเบ™เบšเปเปˆเป„เบ”เป‰เบ–เบทเบเบšเบตเบšเบญเบฑเบ”เปƒเบ™เบซเบผเบฑเบเบเบฒเบ™, เบ”เบฑเปˆเบ‡เบ™เบฑเป‰เบ™เบ‚เบฐเบซเบ™เบฒเบ”เปƒเบ™เบซเบ™เปˆเบงเบเบ„เบงเบฒเบกเบˆเปเบฒเปเบฅเบฐ "เบชเบฒเบ" เปเบกเปˆเบ™เบ›เบฐเบกเบฒเบ™เบ”เบฝเบงเบเบฑเบ™. เบเบฒเบ™เบšเบตเบšเบญเบฑเบ”เบญเบฒเบ”เบˆเบฐเบเบฒเบเป€เบ›เบฑเบ™เบ—เบฒเบ‡เป€เบฅเบทเบญเบเปƒเบ™เบญเบฐเบ™เบฒเบ„เบปเบ”.

เบœเบปเบ™เป„เบ”เป‰เบฎเบฑเบš

เบเบฒเบ™เบ–เปˆเบฒเบเบ—เบญเบ”เบ‚เปเป‰เบกเบนเบ™เบ–เบฑเบ™เบชเบฒเบกเบฒเบ”เป€เบ›เบฑเบ™เบงเบดเบ—เบตเบ—เบตเปˆเบกเบตเบ›เบฐเบชเบดเบ”เบ—เบดเบžเบฒเบšเปƒเบ™เบเบฒเบ™เป‚เบญเบ™เบŠเบธเบ”เบ‚เปเป‰เบกเบนเบ™เบ‚เบฐเปœเบฒเบ”เปƒเบซเบเปˆเป„เบ›เบซเบฒเป€เบ„เบทเปˆเบญเบ‡เบกเบทเบเบฒเบ™เบงเบดเป€เบ„เบฒเบฐเบ–เบฑเบ™เป€เบŠเบฑเปˆเบ™: pandas เปƒเบ™เบ•เปˆเบญเบ™เบ™เป‰เบญเบเป†. เบเบฒเบ™เบšเปเบฅเบดเบเบฒเบ™เบ‚เปเป‰เบกเบนเบ™เบ—เบตเปˆเปƒเบŠเป‰เบšเปˆเบญเบ™เป€เบเบฑเบšเบ‚เปเป‰เบกเบนเบ™เปเบšเบšเปเบ–เบงเบชเบฒเบกเบฒเบ”เป‚เบญเบ™ เปเบฅเบฐเบ–เปˆเบฒเบเบ—เบญเบ”เบ‚เปเป‰เบกเบนเบ™เบ™เป‰เบญเบเป†เบ—เบตเปˆเบชเบฐเบ”เบงเบเบเบงเปˆเบฒเบชเบณเบฅเบฑเบšเปเบ„เบ” 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

เป€เบžเบตเปˆเบกเบ„เบงเบฒเบกเบ„เบดเบ”เป€เบซเบฑเบ™