bitmap,统计业务中一个不得不考虑的数据结构

AI摘要
本文介绍了PHP中操作Bitmap的多种方案及其局限性。原生GMP扩展功能有限,Redis Bitmap存在内存浪费问题。推荐使用Roaring Bitmaps方案,并提供了基于FFI的PHP封装包,支持高效的交集、并集等操作,解决了内存与功能瓶颈。

bitmap是什么

点击了解:什么是Bitmap算法?

php操作bitmap

PHP实现Bitmap的探索 - GMP扩展使用 | Orlion的博客 (fanscore.cn)

redis中的bitmap

php操作redis的bitmap,请自行学习,这里我提一点,redis中的bitmap缺陷:不能存储太大的int,原因和上面博客中提到的内存浪费示例类似,redis的bitmap会占用太大内存导致redis崩溃。

更多的操作bitmap的方式

php的GMP扩展提供的操作bitmap的方式十分有限,只提供了以下操作方法,远不能满足需求:

  • gmp_or — Bitwise OR
  • gmp_and — Bitwise AND
  • gmp_xor — Bitwise XOR

而且,即便自己基于该扩展去实现各种bitmap操作,比如:交集、并集、差集、对称差集、迭代,也十分麻烦,内存浪费的情况不好处理。
这里我介绍一个高效、通用的bitmap方案:
Roaring Bitmaps
目前Java、Go、Rust、Swift、C、C++,都有实现,它们之间可以互通。
如果有大神给php也搞个这样的C扩展,那简直是给php做出了巨大贡献。
我基于Go版的实现,用进程间通信的方式进行封装得到了一个php版的composer包:php的bitmap操作类,该包封装了大部分的bitmap操作,可堪一用,缺点是进程间通信会牺牲效率,部署的时候还得部署对应的bitmap服务端。

————–分割线—————–

最近用php的ffi方式,重新写了一版:composer require buexplain/roaring,如有需求,请使用这个版本。
示例:

require "vendor/autoload.php";
use Roaring\Bitmap;

//求并集
$a = new Bitmap();
$b = new Bitmap();
$a->addMany([1, 2]);
$b->addMany([2, 3]);
$c = $a->or($b);
print_r($c->toArray()); //[1, 2, 3]

//求交集
$a = new Bitmap();
$b = new Bitmap();
$a->addMany([1, 2, 3]);
$b->addMany([2, 3, 4]);
$c = $a->and($b);
print_r($c->toArray()); //[2, 3]

//求差集
$a = new Bitmap();
$b = new Bitmap();
$a->addMany([1, 2, 3]);
$b->addMany([1, 3, 4]);
$c = $a->andNot($b);
print_r($c->toArray()); //[2]

//求对称差集
$a = new Bitmap();
$b = new Bitmap();
$a->addMany([1, 2, 3]);
$b->addMany([3, 4, 5]);
$c = $a->xOr($b);
print_r($c->toArray()); //[1, 2, 4, 5]

//批量迭代整个bitmap
$a = new Bitmap();
$a->addRange(0, 100);
$generator = $a->iterate(10);
foreach ($generator as $v) {
    print_r($v); //每次循环最多获取10个值
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
梦想星辰大海
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!