【发布时间】:2015-05-11 00:20:14
【问题描述】:
我正在做科学研究,通过数百万个兆字节数组的组合进行处理。
为了能够回答这个问题,您需要具备以下所有知识/经验
- HHVM 如何在请求之间将数据结构缓存到 RAM 中
- 如何判断 HHVM 数据结构将保持不变
- 如何声明数组索引和值类型
我需要处理整个数组,因此需要加载和处理大量数据。 (局域网上数分钟内的数百万个请求)。我越快完成请求,我就能越快完成我的工作。如果 HHVM 必须在每个请求上加载这些数据,它会占用很大一部分时间来完成请求(有时超过一半,这取决于我当时正在做的分析的复杂性)。
我找到了一种方法,可以让我将这些数据结构缓存在 RAM 中(不从文件加载、解释代码、无缘无故地向数组推送数十万次、没有毫无意义的重复反序列化等),并且因此我已经消除了这个巨大的可测量延迟。
我有 3 个关于如何使这更快的问题:
- 我现在的做法是否会造成全局范围损失?
- 如何将我的数组声明为常量并告诉 HHVM 期望什么数据类型? 如果我将我的数组声明为常量,是否甚至需要声明 HHVM 的类型?
- 不使用嵌套数组,如果我使用 3 个独立的数据结构 ImmVector、PackedArray,或者定义一个类会更快吗?
请记住,任何阻止 HHVM 在请求之间将数据结构缓存到 RAM 中的行为都应该被视为不可接受的。
Lookuptable35543.php
<?php
$data = [
["uuid (20 chars)", 5336, 7373],
["uuid (20 chars)", 5336, 7373],
#more lines as above
];
?>
其中一些文件有很多 MB 大小,而且数量很多 主.php
<?php
function main() {
require /path/to/Lookuptable35543.php;
#(Do stuff with $data)
}
?>
这很好用,因为 Main.php 收到了数千个请求,在很短的时间内,HHVM 将 Lookuptable.php 的数据结构保存在内存中。避免无意义的处理和 IO,因为它只是位于 RAM 中,可供使用。 (我有足够的内存)
不幸的是,我知道如何让 HHVM 将查找表保存在 RAM 中的唯一方法是,我在我的查找####.php 文件中的全局范围内设置了 $data(然后将查找文件要求为数据处理文件:Main.php)?这样 HHVM 就不用费心加载文件或重新执行代码来创建 $data,因为它可以看到 $data 可以在编译时确定,并且在运行时它永远不会改变。这可行,但我不知道在查找###.php 文件的全局范围中存在 $data 是否会受到惩罚。 (或者它可能根本不是全局的,因为它是 required 进入 main.php 的函数?)
-
如果我从 Lookup.php 中的函数返回 $data 并像这样从 Main.php 调用该函数怎么办 主.php
HHVM JIT 会是 RAM 中 getData() 的结果吗? 不知何故,我将函数与不可预测性联系起来......但也许 HHVM 足够聪明,知道函数结果可以在编译时确定,并且永远不会改变?
我无法将查找表放在 Main.php 中,因为我 require 根据请求类型使用不同的查找表。
- 有没有一种方法可以告诉 HHVM 我的外部数组将始终具有一个永不改变的整数索引,并且外部数组的值将始终是一个数组? 也许我需要使用 ImmVector? 那么有没有办法告诉HHVM我的内部数组将永远是一个固定长度的字符串,后跟2个整数,永远,没有额外的元素,内容永远不会改变?
我不希望使用 OO 或创建类。如何声明类型、程序风格? 如果一个类是绝对必要的,你能给出适合我上面要求的示例代码吗?
- 如果我不嵌套数组会更快吗? 我刚刚意识到我可以拥有一个具有整数索引和固定长度字符串值的数组。然后是具有整数索引和整数值的第二个数组,以及具有整数索引和整数值的第三个数组。
如果您不熟悉这种 HHVM 缓存技术,请不要浪费时间建议数据库、redis、APC、反序列化等。最快的是 HHVM 将我的各种 $data 变量保存在 RAM 中。即使从 ramdisk 文件中反序列化 $data 也很慢,因为必须将整个数据结构解析为字符串,并针对每个请求将其转换为内存中的数据结构。据我所知,APC 也有同样的问题。我什至不想复制 $data。查找表是不可变的,只读的。它们必须在 RAM 中保持完全结构化。我目前的缓存解决方案(在这个问题的顶部)已经给我带来了巨大的收益,但是根据我的 3 个问题,我认为可能会有更多的收益?
如果您想知道,我已经测量了各种数据加载或缓存方法的延迟。 现在我基本上想保留我所拥有的缓存情况,但要让 HHVM JIT 对如何键入我的数据有最大的信心,这样它就可以节省不运行类型甚至绑定(数组大小)检查的时间。
编辑 好的,所以还没有人能给我任何代码示例,所以我只是在尝试。
这是我目前发现的。
const 数组在 HHVM 中还不能工作。
const foo = ['uuid1',43,43];抛出关于 HHVM 仅支持具有标量值的常量的错误。-
带有数组值的向量:我还不知道它会如何执行......我希望它会比普通数组更好。这是有效的 HH 代码。
这是进步,因为 HHVM 应该能够以相同的方式缓存它,HHVM 知道整个结构是恒定的,并且 HHVM 知道索引都是整数。
我对这种结构仍然不太满意的是: 考虑这段代码
for ($n=0;$n<count($iv);++$n) if ($x > $iv[$n][1]) dosomething();
HHVM 会在每次循环迭代时对$if[$n][2] 执行类型检查吗?
在我上面对$iv 的定义中,并没有说内部数组的第二个元素是整数。
我该如何改进呢?
disabling the type checker 有什么用吗?这只是隐藏了外部类型检查器的错误,还是阻止了 HHVM 不断地进行类型检查? (我认为这是第一件事)
也许我可以创建自己的用户定义类型来解决问题?
<?hh
#I don't know what mechanisms for UDT's exist, so this code is made-up
CreateUDT foo = <string,int,int>;
$iv = ImmVector<foo> {
['uuid1',425,244],
['uuid2',658,836]
};
print_r($iv);
我在 Hack Collections Literal Syntax Vector<Foo> 找到了对此的参考,很遗憾它可能还不能使用。
【问题讨论】: