swoole / rfc

Swoole 提案
116 stars 3 forks source link

RFC-1030 可嵌套的线程数据容器 #86

Closed matyhtf closed 1 month ago

matyhtf commented 4 months ago

目标

1. 参数传递与线程数据共享的实现方式统一

目前向子线程传递参数的实现方式是 serialize 串化,在序列化前需要对数组遍历,提取其中的 streamcosocket 进行 dup(fd) 操作,而反序列化则需要根据 resource id 查询一个全局表获取资源。

这种实现存在诸多问题,应该将 thread arguments 改为 ArrayList 类型即可解决所有问题。


// 修改后 $threadArgs 将变为 Thread\ArrayList 对象
$threadArgs = Thread::getArguments();

$thread = new Thread(__FILE__, $fp, $array, $string);
// 线程参数将作为 ArrayList 的元素,逐个 append 到 ArrayList 中

2. 允许嵌套结构

$map = new Thread\Map;

$map['key1'] = new Thread\Map;
$map['key1']['key2'] = new Thread\ArrayList;
$map['key1']['key2'][] = 'hello world';

3. array 类型在存入线程数据容器中时自动转为 Map、ArrayList

对写入线程数据容器的元素使用 arary_is_list() 判断:

此数组中可以是多维的,也可以包含 streamcosocketMapArrayList 等线程资源。

4. Object 类型

保持序列化/反序列化的处理方式

5. String 类型

? 是否有必要实现跨线程的 zend_string (persistent) 封装

目前的考虑是暂时不改,依然使用深拷贝的方式,复制到线程数据容器。主要原因是 PHP 层面只能封装为一个对象 Thread\String,要对这个对象作为字符串操作时,依然要进行一次 toString() 的深拷贝,无法直接作为 string 类型。意义并不大。

不过在互相赋值时,Thread\String 可以节约内存拷贝的性能开销。例如:

$map = new Thread\Map;
$str = random_bytes(1024);
$str = new Thread\String(random_bytes(1024));

$map['key1'] = new Thread\Map;
$map['key1']['key2'] = $str;

$list = new Thread\ArrayList;
$list[] = $str;

例子中,$str 被插入了两个数据容器中,若使用原生 string 类型,需要拷贝 2 次,Thread\String 只需要 1 次。如果频繁在多个线程之间互相传递字符串内容,则 Thread\String 的方式性能会更好。