返回资讯中心
外部精选
软件工程
#开发者实时流

Python 新库 fastsimdjson 实现 277 GB/s 的 JSON 解析速度

来源标题:Reading JSON at 277 GB/s in Python

fastsimdjson 库在 Python 3.14 无 GIL 版本下实现 277 GB/s 的 NDJSON 解析速度。它通过多线程并行解析记录,远超标准 json 模块的 0.28 GB/s 和 orjson、msgspec 等方案。

Hacker News 最新mfiguiere2026/11/14 · 今天14 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

很多系统把数据记录成 JSON,每行一条(NDJSON)。例如 GitHub 通过 GH Archive 以这种方式发布其站点上的每一个公开事件:大约每小时 1 GB。假设你想知道八小时内哪些仓库获得的 star 最多,那就是 7.6 GB 的 JSON、220 万个事件。 在 Python 里,最直白的写法是用 json 模块逐行读取:

for line in open("events.ndjson", "rb"):
    event = json.loads(line)
    if event["type"] == "WatchEvent":
        stars[event["repo"]["name"]] += 1

它的速度是 0.28 GB/s:处理这个文件要 27 秒。orjson 包快一倍。msgspec 包只解码你声明的字段,快八倍。 服务器有很多核,但带 GIL 的 Python 进程一次只能在一个核上运行 Python 代码。通常的解法是进程池:把文件切成几块,每块交给一个进程,再把各自的计数加起来。每个进程只返回一张小表,所以回传的数据很少。 Python 3.14 有一个去掉 GIL 的自由线程构建(python3.14t):多个线程可以同时运行 Python 代码。fastsimdjson 库是多线程的。你把数据和函数交给它,它在多个线程上解析记录,并在解析该记录的那个线程上调用你的函数。你指定想要的字段,它只读取通往这些字段所需的部分,你的函数收到的是这些值,而不是整条记录。

import collections
import fastsimdjson
def starred(event):
    kind, repo = event
    if kind == "WatchEvent":
        return repo
names = fastsimdjson.map_many(
    starred, data, threads=192,
    fields=["/type", "/repo/name"], drop_none=True)
stars = collections.Counter(names)

变量 data 是映射到内存中的文件。两个路径分别是事件类型和仓库名。drop_none 参数会跳过不是 star 的记录。 我在一台 AWS 实例(c8a.metal-48xl)上跑了这个测试,它有两颗 AMD EPYC 9R45 处理器、192 个核,使用 Python 3.14.10、orjson 3.13 和 msgspec 0.22。计时开始前文件已经映射好。在单核上,fastsimdjson 的读取速度是 8 GB/s,是 msgspec 的三倍半。 用 192 个线程时,fastsimdjson 在 55 毫秒内完成对这 7.6 GB 数据的 star 统计:138 GB/s。最好的 msgspec 进程池达到 116 GB/s,用了 96 个进程。进程再多反而更慢。 无论 worker 数量多少,fastsimdjson 都领先。领先幅度从单核时的三倍半缩小到约 20%。 计数是进程池最擅长的场景,因为回传的数据很少。但你往往想要的是值本身。我从一个已有的基准测试(Pison)中取了六个约 1 GB 的文件,从每条记录里抽取一两个字段。在 twitter 文件上,fastsimdjson 达到 277 GB/s。六个文件中有四个超过 100 GB/s。另外两个较慢:一个停留在 20 GB/s 左右,但仍约为 msgspec 的四倍;另一个则打平。 Daniel Lemire, "Reading JSON at 277 GB/s in Python," in Daniel Lemire's blog, November 14, 2026, https://lemire.me/blog/2026/11/14/reading-json-at-277-gb-s-in-python/. https://lemire.me/blog/2026/11/14/reading-json-at-277-gb-s-in-python/'> [BibTeX] Copy

 modal.addEventListener('click', function(e) {
 if (e.target === modal) modal.close();
 });
 modal.querySelector('#bibtex-copy-btn').addEventListener('click', function() {
 const text = modal.querySelector('#bibtex-target').textContent;
 navigator.clipboard.writeText(text).then(() => {
 const origText = this.innerText;
 this.innerText = "Copied!";
 setTimeout(() => this.innerText = origText, 1500);
 });
 });
 document.body.appendChild(modal);
 const style = document.createElement('style');
 style.innerHTML = `dialog::backdrop { background: rgba(0, 0, 0, 0.5); }`;
 document.head.appendChild(style);
            // 1. Extract the URL
            const fullLinkHtml = el.dataset.fullLink; 
            const tempDiv = document.createElement('div');
            tempDiv.innerHTML = fullLinkHtml; 
            const linkElement = tempDiv.querySelector('a');
            const rawUrl = linkElement ? linkElement.href : ''; 
            // 2. Compute the current access date
            const accessedDate = this.getCurrentAccessedDate(); 
            // 3. --- NEW LOGIC: Extract ONLY the year (YYYY) ---
            // Gets the full date string, e.g., "November 23, 2025"
            const fullDateString = el.dataset.year; 
            // Use regex to find the four-digit year at the end of the string
            const match = fullDateString.match(/(\d{4})$/);
            const publicationYear = match ? match[0] : '????'; // e.g., '2025'
            // 4. Generate BibTeX Data with the corrected year
            const safeTitle = el.dataset.title.replace(/[^a-zA-Z0-9]/g, '').substring(0, 15);
            // Use the clean year for the BibKey
            const bibKey = (publicationYear + safeTitle); 
            const content = `@misc{${bibKey},
author = {${el.dataset.author}},
title = {{${el.dataset.title}}},
year = {${publicationYear}}, 
howpublished = {\\url{${rawUrl}}},
note = {Accessed: ${accessedDate}} }`;
            // 5. Show Modal
            document.getElementById('bibtex-target').textContent = content;
            modal.showModal();
    };
})();

Published by Daniel Lemire A computer science professor at the University of Quebec (TELUQ). View all posts by Daniel Lemire

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →