使用带有hack(HHVM)的多线程(异步)“遍历”PHP数组

时间:2015-10-04 04:54:00

标签: php multithreading asynchronous hhvm hacklang

不确定为什么还没有“hack”标签(抱歉在PHP中列出),但是......

我想知道是否/如何使用hack的多线程/异步功能使用多个线程来运行数组。我真的不需要这个,但这是一种好奇心,可能会有用。

我查看了“Hack”的异步功能

的文档

http://docs.hhvm.com/manual/en/hack.async.php

并且有点困难。

以下是我想做(或看完)的基本想法:

a)将数组拆分为x个部分并在x“线程”上处理 或者b)创建x个线程并且每个线程处理最新的可用项目,即。当线程处理该项时,它会要求父线程处理一个新线程。 Hack不执行“线程”,但同样由asyc函数表示

基本上,最终目标是快速优化标准foreach块以在多个线程上运行,因此需要最少的代码更改,同时还要查看hack可以执行的操作及其工作原理。

我已经提出了一些代码作为样本,但我认为我的想法完全错了。

class ArrayWalkAsync
{
    protected $array;
    protected $threads = Array();
    protected $current_index = 0;
    protected $max_index;
    protected $threads = 4;

    public function array_walk($array)
    {
        $this->array = $array;
        $this->max_index = count($array) - 1;
        $result = Array();
        for ($i=0;$i<$this->threads;$i++)
        {
            $this->threads[] = new ArrayWalkThread();
        }
        $continue = true;
        while($continue)
        {
            $awaitables = Array();
            for ($i=0;$i<$this->threads;$i++)
            {
                $a = $this->proccesNextItem($i);
                if ($a)
                {
                    $this->threads[] = $a;
                } else {
                    $continue = false;
                }
            }
            // wait for each
            foreach ($awaitables as $awaitable_i)
            {
                await awaitable_i;
                // do something with the result
            }
        }
    }

    protected function proccesNextItem($thread_id)
    {
        if ($this->current_index > $this->max_index)
        {
            return false;
        }
        $a = new ArrayWalkItem();
        $a->value = $this->array[$this->current_index];
        $a->index = $this->current_index;
        $this->current_index++;
        return $this->threads[$thread_id]->process($a,$this);
    }

    public function processArrayItem($item)
    {
        $value = $item->value;
        sleep(1);
        $item->result = 1;
    }

}


class ArrayWalkThread
{
     async function process($value,$parent): Awaitable<?ArrayWalkItem>
     {
        $parent->processArrayItem($a);
     }

}

class ArrayWalkItem
{
    public $value;
    public $result;
}

1 个答案:

答案 0 :(得分:2)

Hack的异步功能无法满足您的需求。在Hack中,异步函数不是线程。这是一种隐藏IO延迟和数据获取的机制,而不是一次执行多个计算。 (这与使用Hack功能的C#中的相同。)

This blog post on async functions有一个很好的解释:

  

几个月以来,Hack已经有了一个名为async的功能,可以编写协同多任务的代码。这有点类似于线程,因为多个代码路径是并行执行的,但它通过在任何给定时刻实际执行一个部分来避免多线程代码常见的锁争用问题。

     

“这有什么用?”,我听到你问。你仍然绑定了一个CPU,所以它应该花费相同的时间来执行你的代码,对吧?嗯,这在技术上是正确的,但脚本代码执行并不是导致应用程序延迟的唯一因素。其中最大的一部分可能来自等待后端数据库响应查询。

     

[...]

     

虽然[http]电话正忙着等待响应,但没有理由你不能做其他事情,甚至可能会发出更多请求。数据库查询也是如此,这可能需要同样长的,甚至文件系统访问速度比网络快,但仍然会引入几毫秒的滞后时间,而这些都会加起来!

对于这一点的困惑感到抱歉 - 你不是唯一一个试图以这种方式错误地使用异步的人。当前的文档做了解释这个问题的可怕的工作。我们正在对文档进行改进; current draft做得稍微好一点,但是我要在发布新文档之前先确定一个任务,以确保它清晰明了。