我有一个数组(嗯,一个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
是慢/破/马车吗?我应该使用其他方法吗?滚我自己?
答案 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快得多。