Skip to main content

NPY file format with Tail

带小尾巴的NPY文件格式

项目特点

  1. 与Numpy的NPY文件格式兼容, 可以用原生的np.load函数加载
  2. 支持memmap模式, 可以跨进程一写多读。append
  3. 支持调整文件大小resize,但不移动数据
  4. 支持tell、seek、rewind、read等操作
  5. 支持无限写入NPY8

安装

pip install npyt

使用

import numpy as np

from npyt import NPYT

arr = np.array([1, 2, 3, 4, 5, 6])

file = "tmp.npy"
# 创建文件
nt1 = NPYT(file).save(arr, capacity=10, end=0).load(mmap_mode="r+")
# 只读加载文件
nt2 = NPYT(file).load(mmap_mode="r")
nt3 = NPYT(file).load(mmap_mode="r")

nt1.append(arr)
print(nt2.data())

nt1.append(arr[0:1])
print(nt3.data())

项目背景

本人需要一种准实时的行情存储方式,考虑arrow或np.memmap()

  1. arrow,列式存储,并不适合行情数据。因为要将新数据写入到不同的位置
  2. np.memmap(),内存映射,行式存储,适合行情数据。但还是有不足
    1. 需另行维护dtype,shape等信息
    2. 文件大小随数据量而增大,不能动态调整大小

所以如果初始时创建一个大文件,然后维护一个标记,用来记录数据的位置,就能实现数据增长了。

标记是放在同一文件,还是放在不同文件呢?

最开始是放在不同文件,这样代码实现方便,但是要维护两个文件。 后来发现np.load函数支持mmap_mode参数,可以直接加载内存映射文件,并且还是直接带了dtype和shape信息。为何不直接用呢? 只要把额外信息放在NPY文件的尾部就可以了。

额外信息

额外信息放在NPY文件的尾部,多加个5个uint64数字。

  1. start: 开始位置
  2. end: 结束位置
  3. update_timestamp: 更新时间。可处理end不变,但数据变化的情况
  4. offset: 数据区开始位置,方便其他语言快速定位并写入
  5. magic: 魔术数,用来判断是否NPYT格式文件

如何实现修改文件大小而不移动数据

NPY文件头有shape信息的字符串,例如;

(20, 3)
(200, 3)

很明显,这两个字符串的长度是不一样的。而NPYT项目修改了此部分,让字符串长度一致,例如;

(                    20, 3)
(                   200, 3)

这样就可以直接修改数据大小而不用移动数据区。

兼容性

  1. np.load可以打开NPYT.save保存的文件。NPYT.load可以打开np.save保存的文件, 取原始数据NPYT._raw()
  2. np.save保存的文件大小不可修改。NPYT.save保存的文件,可用NPYT.resize修改
  3. np.load后dtype缺失align属性。NPYT.load后dtype还原了align属性。(numpy 2.2.5)
    • 当array要传给numba.jit函数,函数中需要对array进行修改,由于align属性缺失,可能导致修改时出现数据复制,复制出来的对象是只读
    • https://github.com/numpy/numpy/issues/28973

无限写入模式NPY8

最开始提供了RingBuffer模式。但存在不足

  1. 编写过于复杂
    • c++版读写都是单行数据读取,可以用%算法来实现环形
    • numpy版。都是多行整体写入和读取,无法用%算法来实现,导致需要写大量判断语句,逻辑复杂
  2. 无法零拷贝
    • start<end,零拷贝
    • start>end,数据分成了两段,需要拷贝

所以,NPY8模式诞生了,可以7*24写入数据

它本质是创建一个文件夹和一个.lock文件,通过.lock来维护文件夹中最新的几个NPYT文件。

  1. 写入数据时,从.lock文件尾,读取最新的NPYT文件,如果文件已满,创建新的NPYT文件,并写入.lock文件
  2. .lock文件会限定文件数量,比如8个文件,多于8个文件时,文件移出队列不再维护
  3. read时,从.lock文件头开始,读取单个文件,已读完,切换下一个文件,直到.lock文件尾
  4. tail时,从.lock文件尾开始,读取单个文件,已读完,但数量不够,继续读取上一个文件,直到.lock文件头

优化建议

  1. NPY8.tail是跨文件的,如果能取的是单个文件,就能减少拷贝

    1. 返回的是np.ndarray列表,一个个按需使用比concat后使用更好
    2. capacity_per_file设置得大一些,越大越能减少跨文件的概率(tail-1)/capacity。例如:
      • capacity=100,tail=100,则99%的概率跨文件
      • capacity=100,tail=50,则49%的概率跨文件
      • capacity=50,tail=1,则0%的概率跨文件

    tail由自己的策略所决定,根据用户能接受的概率,文件大小,记录时长来设置capacity_per_file

  2. NPY8.read一次只读取一个文件,适合遍历场景。capacity很大时。可以认为与tail功能接近

    • read(n=1000, prefetch=100) 最多返回1000+100条数据
  3. NPY8是跨文件的,适合外汇、数字货币场景。股票、期货这类,一个大NPYT文件更好用

Metadata

Release files for npyt 0.4.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for npyt 0.4.3
File Size Uploaded
npyt-0.4.3.tar.gz 12.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for npyt 0.4.3
File Interpreter ABI Platform
npyt-0.4.3-py3-none-any.whl Python 3 none any Details

Total release size: 26.9 kB

Release files / npyt-0.4.3.tar.gz

Download URL npyt-0.4.3.tar.gz
Size 12.9 kB
Tags Source
SHA-256 checksum
How to use checksums
678ddfb7d524aaa302d5c00c54730b9900c8e80dc126c5b0c211068771b9f186
BLAKE2b-256 checksum
How to use checksums
4365e8f675a31fa49c6b030825c09ff13b787858735aa2189071aa7ec6f2c819
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Release files / npyt-0.4.3-py3-none-any.whl

Download URL npyt-0.4.3-py3-none-any.whl
Size 14.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
94785d9988126086f68bbb42c2d2604bd3c573507f12101de0209a8d29635a8b
BLAKE2b-256 checksum
How to use checksums
1822bcf2c040de8a1c0fd1df597560bea7322e8f91a61b23a1840e42ca6f988f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Release history Release notifications | RSS feed

This release

0.4.3 This release

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page