资讯动态

面试官问500万玩家成就解锁标记怎么存:list、numpy、bitarray和bool-hybrid-array我压了一遍(2026真机)

发布时间:2026/10/27 12:39:46 来源:尧图企业网站定制
先声明这是我在自己机器上对 bool-hybrid-array9.13.11 当版做的可复现实测手记不是跨机构独立基准。下面每个字节、每个耗时都给了环境和口径你应该在自己机器上复跑而不是信我一面之词。一个面试题背后是一类真实需求前阵子被问了一道很朴素的题一款在线游戏全服 500 万玩家每个玩家对每个成就要有一个布尔位——解锁了是True没解锁是False。新成就一上线开局几乎全是 False接下来几个月解锁率从 0 慢慢爬到 0.5%、5%热门成就甚至过半。运营还会随时查这个人解锁没、后台要随时翻某几个位。这个标记表怎么存我没有急着背答案而是回去把几种常见存法在同一台机器上压了一遍。结论比我想的有意思这个开局极稀疏、随时间变稠密、还要随时动态翻转的曲线恰好是普通定长位图最尴尬、而自动混合存储最舒服的场景。先看一张真机表N 5,000,000环境CPython 3.12.11 / numpy 2.5.3 / bool-hybrid-array 9.13.11版本号、依赖与许可证一律以当时 PyPI 元数据为准CPU 为/proc/cpuinfo实测 model name「AMD EPYC 9Y24 96-Core Processor」云实例定制 SKU公开零售型号查不到同名只当本环境标注看4 核 / 8GB。每种方案在独立冷进程里测、喂构造器一律用生成器、耗时用time.perf_counter()多次重复取中位、内存统一看稳态memory_usage()。极小的构造耗时亚毫秒级受 CPU 频率与缓存影响较大这类只看数量级、不纠结末位有效数字。方案稳态内存约合构造耗时中位[False]*Nlist[bool]40,000,056 B38.15 MiB13.8 msnumpy.zeros(N, bool)5,000,000 B4.77 MiB0.1 ms中位 0.02bytearray(N)5,000,057 B4.77 MiB1.5 msnumpy.packbits位图625,000 B610 KiB0.87 msbitarray(N)625,000 B610 KiB0.17 msBHA全 False 起点FalsesArray(N)415 B—0.12 msBHA0.5% 解锁25,000 个 True100,132 B97.8 KiB1.58 sBHA5% 解锁250,000625,133 B610 KiB2.16 sBHA50% 解锁250 万625,135 B610 KiB2.30 s几个一眼能看出的点开局FalsesArray(5_000_000)这个对象自身只有415 字节memory_usage()口径而 list 要 38 MiB新成就上线那一瞬间几百个成就同时铺出来也不占地方。注意 415B 只是容器自身记账不含 import numpy 后解释器约 30 MiB 的常驻 RSS——比内存要看同一口径本文横评统一用各容器的稳态memory_usage()。极稀疏0.5%同一 N、同一稳态口径下BHA 用约 100 KB是定长位图 610 KB 的约 1/6.2、numpy 布尔数组np.zeros(N, dtypebool)1 字节/元素的约 1/50、list 的约 1/400。它内部这时候走的是array.array(I)升序存已解锁下标 二分查找只记那 2.5 万个 True而不是给 500 万人各开一个位。顺带一提numpy 布尔类型现在的规范写法是numpy.bool/dtypebool老写法np.bool_在 NumPy 2.x 里仍保留为np.bool的别名2.0 起 canonical 名是np.bool/dtypebool并未被移除我在本机 numpy 2.5.3 实测np.bool_ is np.bool为 True。变稠密实测 5% 已在位图态0.5% 时它还在稀疏下标态到 5%25 万个 True实测就已经位于按位打包的位图、625 KB——因为 25 万个下标光用 4 字节整型存就要约 1 MB已经超过 N/8 的 625 KB于是库在这之间自己切到了位图到 50% 仍是 625 KB和bitarray/packbits基本打平。表里 5%625,133B和 50%625,135B只差 2 字节这点差异来自对象头部/计数等常数记账与密度无关理论交叉点约在 25 万下标×4B1MB 反超 625KB 位图处约 3.1%。具体切换点以库当版行为为准我这里只报告实测现象不背固定阈值。这也是这个库hybrid的字面意思你不用自己手写何时从下标表换位图。三步上手安装运行期硬依赖 numpy ≥ 1.19不是零依赖这点先讲清楚pipinstallbool-hybrid-array游戏成就表最自然的用法是从全服未解锁起步、再动态翻位frombool_hybrid_arrayimportFalsesArray N5_000_000unlockedFalsesArray(N)# 全 False约 415Bunlocked[100042]True# 玩家 100042 解锁unlocked[88]Trueprint(unlocked[100042])# Trueprint(unlocked.count(True))# 2print(unlocked.memory_usage())# 稀疏阶段约 100KB 量级2.5 万 True 时 100,367B我实测从FalsesArray起逐个点亮 25,000 个分散成就2.5 万次翻位合计约 0.0135 s单次约 0.5 微秒全程停在稀疏态、内存 100 KB 出头——这正是日常解锁事件在干的事。如果你手里已经有一份解锁名单、要一次性建表记得用生成器喂别用列表推导列表推导会先建一个满载的临时 list把峰值内存抬上去frombool_hybrid_arrayimportBoolHybridArr rareset(range(0,N,N//25000))unlockedBoolHybridArr((iinrare)foriinrange(N))# 0.5% 稀疏它的边界我也一起摆桌上不想把它写成银弹三个真实代价你得知道从零一次性灌一个稠密大表并不快上面 500 万元素用生成器逐个喂BHA 要 1.5~2.3 s而numpy.zeros靠 calloc 近乎 0。所以它的甜区是稀疏起点 长期动态维护不是开机就把一个全满稠密数组灌进去——那种活直接用 numpy。稠密之后它就是一张位图单点读取实测约 700~880 nstimeit式对同一索引重复 200 次取中位含 Python 下标包装数值受 CPU 频率/缓存影响会有浮动看数量级即可纯定长位图 向量化批量统计场景numpy/bitarray 更直接。从源码层面看9.13.11 安装包PyPI 元数据只暴露裸numpy依赖以下内部实现以源码为准稠密侧省内存来自按位打包 N/8位图缓冲由 numpy 的 uint8 承载运行需要 numpy ≥ 1.19稀疏侧是array.array(I)升序下标 二分下标超过 2³² 才升到 8 字节的Q。顺带澄清一个常见误传9.13.11 全程没有 RLE 行程编码全 True/全 False 的极性塌缩也不是 RLE。怎么选一句话纯稠密、还要做向量化批量统计 → 老实用numpy就要一张极简定长位图、逻辑越简单越好 →bitarray / bytearray / packbits像成就、签到、标签、风控名单这种稀疏度大起大落、要随时动态增删、还想要 list 一样的下标接口→ bool-hybrid-array 对味。项目信息名称bool-hybrid-arrayPyPI 当前版本9.13.11许可证Apache-2.0 OR MulanPSL-2.0双许可注意 MulanPSL 是 2.0Python ≥ 3.8硬依赖 numpy ≥ 1.19。主页https://github.com/BKsell/bool-hybrid-array 安装pip install bool-hybrid-array核心类是BoolHybridArr单数 Arr另有TruesArray/FalsesArray快速极性构造。面试那道题我最后没有背哪个库最强而是把这张表摆出来成就解锁的曲线不是一条直线存储也不该是。别信我信你自己机器上的测量。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑