PHP: <?php echo "start: ".date("Y-m-d H:i:s")."<br />"; for ($i=0;$i<60000;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values==""?$values.="[$event_time,{$value}]":$values.=",[$event_time,{$value}]"; } echo "end: ".date("Y-m-d H:i:s"); Результат: start: 2009-08-12 00:26:06 end: 2009-08-12 00:26:58 52 секунды Изменяем 6 строку PHP: <?php echo "start: ".date("Y-m-d H:i:s")."<br />"; for ($i=0;$i<60000;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values.= ($values=="") ? "[$event_time,$value]" :",[$event_time,$value]"; } echo "end: ".date("Y-m-d H:i:s"); Результат: start: 2009-08-12 00:27:50 end: 2009-08-12 00:27:57 7 секунд Объясните пожалуйста, откуда такая огромная разница?
вам лучше в цикле прибавлять "[$event_time,$value]," без проверок, а после цикла удалить лишнюю запятую.
iliavlad, а еще можно через массив значений и join(',' $array); в конце. но вопрос у афтора интересный — надо будет написать тестик.
Вообще задача пошла из следующей задачи: необходимо доставать из БД очень большие массивы данных, преобразовывать их в JavaScript структуры и передавать на клиента для отрисовки графика. Сейчас точек может быть 60000 легко. Однако нужно как-то продумать возможность быстрой передачи и большего (порядка 200000) количества точек. Нашел я эту особенность чисто случайно. У нас с коллегой разные стили написания кода . Он пишет по первому варианту, а по второму. Просто решил попробовать изменить эту строку и получил очень любопытные результаты. А вообще хочется услышать мнения тех, кто работал с большим количеством конкатенируемых строк и с выдачей их клиенту: как это дело можно максимально оптимизировать?
Кстати, вариант с JOIN PHP: <?php echo "start: ".date("Y-m-d H:i:s")."<br />"; $values = array(); for ($i=0;$i<60000;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; array_push($values,"[$event_time,$value]"); } $res = join(',',$values); echo "end: ".date("Y-m-d H:i:s"); Результат start: 2009-08-12 08:03:28 end: 2009-08-12 08:03:34 6 секунд (еще лучше)
Что-то мне больше никакие варианты конкатерации в голову не идут. Метод добавления элемента в массив не оказал влияния на быстродействие array_push($values,"[$event_time,$value]"); и $values[] = "[$event_time,$value]"; и $values[] = '['.$event_time.','.$value.']'; // чтобы двойные кавычки не парсились Варианты оказались идентичными по времени (с точностью до секунд). Пока что использование массива - самый оптимальный вариант.
Ради эксперимента сделал по совету iliavlad (не думал, что будет лучше) PHP: <?php echo "start: ".date("Y-m-d H:i:s")."<br />"; for ($i=0;$i<60000;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values.=",[$event_time,$value]"; } $values = substr($values,1); echo "end: ".date("Y-m-d H:i:s"); Результат start: 2009-08-12 08:16:09 end: 2009-08-12 08:16:15 6 секунд (как с массивами) Был удивлен если честно. Теперь с точки зрения выделения памяти и прочей низкоуровневой ботвы, какая операция наиболее весомая: добавление элемента в массив или добавление строки к строке?
Если учесть, что после создания массива в JOIN опят идет перебор всех элементов и та же самая конкатенация строк, то более дешевым способом конечно же является последний. Думаю, что на этом и остановлюсь. Хотя конкурс на самый быстрый код продолжается . Да. И, конечно же, всем участвующим огромное спасибо.
по сути пофиг как. PHP: <?php $for = 100000; $sign = 5; function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } echo "COUNTER: $for\n"; ############################################################################### $start = microtime_float(); $values = array(); for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; array_push($values,"[$event_time,$value]"); } $res = implode(',',$values); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "ARRAY_PUSH: Working in $time seconds\n"; unset($values); unset($res); ############################################################################### $start = microtime_float(); $values = array(); for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values[] = '['.$event_time.','.$value.']'; } $res = implode(',',$values); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "[]: Working in $time seconds\n"; unset($values); unset($res); ############################################################################### $start = microtime_float(); $values = ''; for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values[] = $event_time.','.$value; } $res = '['.implode('],[',$values).']'; $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "[]2: Working in $time seconds\n"; unset($values); unset($res); ############################################################################### $start = microtime_float(); $values = ''; for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values[] = array($event_time => $value); } $res = json_encode($values); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "JSON: Working in $time seconds\n"; unset($values); unset($res); ############################################################################### $start = microtime_float(); $values = ''; for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values .= "[$event_time,$value],"; } $res = rtrim($values,','); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "DOUBLE: Working in $time seconds\n"; unset($values); unset($res); ############################################################################### $start = microtime_float(); $values = ''; for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values .= '['.$event_time.','.$value.'],'; } $res = rtrim($values,','); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "SINGLE: Working in $time seconds\n"; unset($values); unset($res); ############################################################################### $start = microtime_float(); ob_start(); $values = ''; for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; echo '['.$event_time.','.$value.'],'; } $res = ob_get_contents(); ob_end_clean(); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "OB: Working in $time seconds\n"; unset($values); unset($res); ?> Код (Text): c:\>php cat.php COUNTER: 100000 ARRAY_PUSH: Working in 2.84897 seconds []: Working in 2.81188 seconds []2: Working in 2.77077 seconds JSON: Working in 2.77757 seconds DOUBLE: Working in 2.76440 seconds SINGLE: Working in 2.75201 seconds OB: Working in 2.69384 seconds
что-то очень долго, у меня хмл на 10к товаров формировался за секунду если быстрее никак - а если сливать мускулом group_concat или еще как, быстрее не будет?
дятлы )) PHP: <?php $for = 100000; $sign = 5; function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } echo "COUNTER: $for\n"; ############################################################################### $start = microtime_float(); $values = array(); for ($i=0;$i<$for;$i++){ $event_time = " ".$i%($i+1); //strval(strtotime('2009-08-12 00:12:21')); $value = 5; array_push($values,"[$event_time,$value]"); } $res = implode(',',$values); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "ARRAY_PUSH: Working in $time seconds\n"; ?> Казалось бы, и причем тут [Лужков] конкатенация?
Вроде того, только за месяц . 2 armadillo: эти операции оставлены специально. Там еще преобразования есть. Нужно оценить для конкретной задачи, где идет дополнительная обработка результатов запроса. 2 440Hz: спасибо за OB. Думаю, что при больших объемах это более оптимальный вариант. У вас машинка уж очень шустрая. У меня 100000 итераций обрабатываются за 18 секунд. Вот, кстати, мой тест. Если руки дойдут, графики потом прикручу. PHP: <?php $for = (isset($_GET['cnt'])) ? $_GET['cnt'] : 10000; $sign = 5; function microtime_float() { list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } ############################################################################### if (isset($_GET['type']) && ($_GET['type'] == 1)) { $start = microtime_float(); $values = array(); for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; array_push($values,"[$event_time,$value]"); } $res = implode(',',$values); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "COUNTER: $for; ARRAY_PUSH: $time seconds<br />"; unset($values); unset($res); } ############################################################################### else if (isset($_GET['type']) && ($_GET['type'] == 2)) { $start = microtime_float(); $values = array(); for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values[] = '['.$event_time.','.$value.']'; } $res = implode(',',$values); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "COUNTER: $for; []: $time seconds<br />"; unset($values); unset($res); } ############################################################################### else if (isset($_GET['type']) && ($_GET['type'] == 3)) { $start = microtime_float(); $values = ''; for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values[] = $event_time.','.$value; } $res = '['.implode('],[',$values).']'; $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "COUNTER: $for; []2: $time seconds<br />"; unset($values); unset($res); } ############################################################################### else if (isset($_GET['type']) && ($_GET['type'] == 4)) { $start = microtime_float(); $values = ''; for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values[] = array($event_time => $value); } $res = json_encode($values); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "COUNTER: $for; JSON: $time seconds<br />"; unset($values); unset($res); } ############################################################################### else if (isset($_GET['type']) && ($_GET['type'] == 5)) { $start = microtime_float(); $values = ''; for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values .= "[$event_time,$value],"; } $res = rtrim($values,','); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "COUNTER: $for; DOUBLE: $time seconds<br />"; unset($values); unset($res); } ############################################################################### else if (isset($_GET['type']) && ($_GET['type'] == 6)) { $start = microtime_float(); $values = ''; for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; $values .= '['.$event_time.','.$value.'],'; } $res = rtrim($values,','); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "COUNTER: $for; SINGLE: $time seconds<br />"; unset($values); unset($res); } ############################################################################### else if (isset($_GET['type']) && ($_GET['type'] == 7)) { $start = microtime_float(); ob_start(); $values = ''; for ($i=0;$i<$for;$i++){ $event_time = strval(strtotime('2009-08-12 00:12:21')); $value = 5; echo '['.$event_time.','.$value.'],'; } $res = ob_get_contents(); ob_end_clean(); $stop = microtime_float(); $time = number_format($stop - $start,$sign); echo "COUNTER: $for; OB: $time seconds<br />"; unset($values); unset($res); } else { ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1251"> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js" type="text/javascript" language="javascript"></script> <script type="text/javascript" language="javascript"> function start() { for (k=10000;k<=100000;k+=10000) { for (i=1;i<=7;i++) { $.ajax({ url: '?type='+i+'&cnt='+k, async: false, success: function(data) { $('body').append(data); } }); } } } </script> </head> <body> <input type="button" value="Start" onClick="start();" /> </body> </html> <?php } ?>
+1. тесты же кажут, что разница мала, а вот при подготовке данных можно поколдовыать. посему вопросы: откуда беруться данные? может их там можно готовить уже сразу., т.е. при записи в базу сразу хранить JSON строку для пары. тогда время значительно уменьшится, т.к. не будет сборки, которая и отнимает время.
так положено дядьке иметь уже такой ноут в свои 43 года. =) ты еще не видел мой 8-ми процессорный сервачек под статистику.
Если посмотрите на самый первый пост, то увидите, что синтаксис на конкатенацию не просто очень, а ОЧЕНЬ-ОЧЕНЬ влияет. Собственно в этом вопрос и состоял. А вот среди приведенных позже методов действительно разница не велика. Там очень сложный механизм синхронизации одной базы с другой (рабочей с вебом). Синхронизацией занимаюсь не я, но вообще как вариант оптимизации это можно рассмотреть. Спасибо за подсказку. Задачи оптимизации обработки статистики нужно обсуждать уже не в этой ветке, мне так кажется. Кстати, если есть интересная ссылка по этой теме, то буду очень благодарен, ибо заказчик уже подошел к границам, когда оптимизация необходима .
Онекдот. Для извращенцев: Возникла реальная задача перебора строк по 3мил символов. не спрашивайте зачем. PHP: <?php $n = strlen($a); for($i=0;$i<$n;$i++){ $b.=$a[$i]; } полторы секунды. кстати внос strlen в условие цикла увеличивает до 2.5 сек. есть идеи как ускорить? )))
PHP: <?php $text = 'текстdbdfbdbdgbbdbdbddgfgggegegegerggggggggggggggljkkngselkgnselknelkwenblwelkbnbel'; $start = microtime(true); $i = 0; $b = ''; $n = strlen($text); for($i=0;$i<$n;$i++){ $b.=$text[$i]; } echo microtime(true) - $start; //0.00024509429931641 ?> PHP: <?php $text = 'текстdbdfbdbdgbbdbdbddgfgggegegegerggggggggggggggljkkngselkgnselknelkwenblwelkbnbel'; $start = microtime(true); $i = 0; $b = ''; while (isset($text[$i])) { $b .= $text[$i]; $i++; } echo microtime(true) - $start; //0.0001530647277832 ?>
Протестировал еще разные варианты (мой вариант, что выше, на домашнем компе - 0.00011897): PHP: <?php $len = strlen($text); $b = ''; while ($len--) $b = $text[$len].$b; //0.00011420249938965 Этот помедленнее: PHP: <?php $len = strlen($text); $i = 0; $b = ''; while ($i < $len) { $b .= $text[$i]; $i++; } //0.00012612342834473 Вот странно, если количество символов увеличить до 3 миллионов, то получается наоборот о_О. Первый скрипт вообще в запой уходит, а второй показывает где-то 2.29 с. Самый первый предложенный вариант 2.12 с, твой вариант - 2.32