PHP是否真的如此缓慢或我做错了什么?

时间:2015-12-27 15:38:31

标签: php arrays sorting

我有一个数组(嗯,一个PHP数组......实际上不是一个数组。但是你明白了。)代表SMS的对象。这些对象中的一个字段是DateTime类型,我想按该字段对数组进行排序。 我无法对数据库中的数据进行排序,我是通过无法更改的网络服务接收的,所以请不要这样做。我使用以下代码片段对数组进行排序:

usort($smsMessages, function ($a, $b) { 
    if ($a->SendTime == $b->SendTime) {
        return 0;
    }

    return ($a->SendTime < $b->SendTime) ? -1 : 1;
});

这样可行,但需要 160秒才能对30.000个元素进行排序。

现在,我知道php很慢,但这很荒谬。我写这个的方式有问题吗?已知usort是慢/破/马车吗?我应该使用其他方法吗?滚我自己?

3 个答案:

答案 0 :(得分:3)

您可以尝试加速上面的代码,看看排序是否实际上是瓶颈,您可以尝试通过使用全局函数来加速它并缩短代码(免责声明:大规模微优化,可能是这个不是你的问题在哪里!)像这样:

function sort_function($a, $b){
 $a = $a->SendTime;
 $b = $b->SendTime;
 if ($a == $b) return 0;
 return ($a < $b) ? -1 : 1;
}

usort($smsMessages,'sort_function');

假设大多数SendTime都不相等,这实际上应该加快速度。

但是请理解以上只是一个非常轻微的加速。如果你真的看到东西喜欢140s =&gt;你可以责怪我们。尽管如此,上述建议对你的价值在于我认为事情的一部分不是你的问题。

在以下更多输入后添加:

在得知这完全是因为内存不足之后(你发布的使用数据是关于整个系统的,我无法推断出这些256MB的实际使用中有多少是在没有更多这些对象的知识的情况下:)) ,这段代码在运行时如何比较?

$dates = array();
foreach ($smsMessages as $key => $obj) {
    $dates[$key] = $obj->SendTime;
}

asort($dates);
$dates = array_keys($dates);
$sorted = array();
foreach ($dates as $key) {
    $sorted[] = &$smsMessages[$key];
}

这应该需要更少的内存,因为它不会在巨大的数组上使用隐式的foreach循环,而只是在数组键上使用。

答案 1 :(得分:2)

试试这个:

首先,将“{”添加到json_decode作为第二个参数,这样您将获得一个关联数组而不是对象数组。 (我还建议尝试这个来加速JSON:https://github.com/RustJason/php-rapidjson - 它需要PHP7但是

然后:

$sentTime = [];
foreach ($smsMessages as $key => $element) {
    $sentTime[$key] = strtotime($element['sent']);
}
array_multisort($sentTime, SORT_DESC, $smsMessages);

(在我的电脑上0.19秒)

您可以稍后使用$smsMessages或使用自己的/自定义方法将某些(object)$smsMessage转换为对象。

答案 2 :(得分:1)

我有同样的问题。我们需要整理2到1千万个阵列。每个数组包含大约30个字段(字符串,整数和NULL)。第一个字段是我们用于排序的唯一整数。

我们使用了PHP 7.1

在AWS EC2 r4.large上排序2,028,830个项目花费了4710秒(= 78.5分钟)。

我们的代码如下:

usort($this->rows, function ($item1, $item2) {
        return $item1[0] <=> $item2[0];
});

然后我发现将$this->rows替换为$rows使其速度提高了近4倍:

usort($rows, function ($item1, $item2) {
        return $item1[0] <=> $item2[0];
});

执行时间从4710减少到1195秒。

另一种方法是对$this->rows使用Min Heap而不是普通的PHP数组[]。它导致大约相同的性能改进。在这种情况下,您根本不需要usort。

底线:  1.但是,即使经过上述更改,它也确实需要花费大量时间。  2.对于已排序的数组,usort比MinHeap快得多。