--- Добавлено --- это профиль поиска 1 слова человек в готовом словаре. --- Добавлено --- Из долгого в порядке убывания, не считая времени открытия и загрузки словаря: node_get_children() - получение маски узла по его id, функция включает в себя расчет номера элемента в массиве где записана нужная часть словаря. тут используется деление и floor(). Потом идет substr() для чтения строки маски. Дальше unpack_48() - распаковывает 48 битную строку функцией для 64 битной, дополняя недостающие байты нулями. split_rus() - делит русское слово по буквам. Работает быстрее, чем preg_split(). Из элементарных функций самые затратные в порядке убывания: unpack() floor() str_pad() substr() bin2hex() --- Добавлено --- Вот что нашел вчера. https://github.com/php-ds
а если не гзипнутые? вопрос, а если отказаться от unpack? --- Добавлено --- и от floor --- Добавлено --- и от str_pad --- Добавлено --- и зачем тебе bin2hex?
Без gz 150мб. Отказаться от всего это - хорошая идея. Только как? Чем заменить floor(a/b) еще можно придумать. Но как обойтись без str_pad()? Там сейчас есть 2 ключевые функции, в которых str_pad() задействован. unpack_24() и unpack_48(). В обоих случаях принцип работы такой. Поскольку pack() unpack() понимает только 8, 16, 32, 64 и битные числа, то для распаковки числа 24 битной длины используется формат 32 битной. str_pad() тут заполняет недостающие байты нулями. Было бы здорово заменить. Все что мне попадалось для pack unpack 24 и 48 битных строк тоже было со str_pad(), но еще сложнее. bin2hex() используется в функции split_rus(), русские буквы бывают в utf8 2-мя байтами записаны, а бывают тремя, Вот там функция строку по 2 байта делит, и каждый кусочек с таблицей hex значений русских букв сравнивает, если не находит, то пытается 3 байта поискать. В сущности bin2hex() для наглядности сделано: Код (Text): $hex = bin2hex(substr($word, 0, 2)); можно отказаться от bin2hex() и всю таблицу символов, которая сейчас в hex записана, переписать в двоичном виде.
На коротких строчках substr() довольно быстро работает. Попытаюсь все таки сделать переменную длину узла, может не будет сильно тупить, а объём сократится в разы. Сейчас 75тыс. слов в секунду, если около 50 будет - успех.
попробуй ксорить или орить на нужное число нулей. может будет быстрее. я не про "0" а про байты, забитые нулями --- Добавлено --- ты же можешь на буквы как есть делать массив, без их конвертации в hex представление --- Добавлено --- что ты имеешь в виду под двоичным?
Как так сделать? Так и сделаю. На примере буквы 'а' Код (Text): $str = 'а'; $hex = chr(0xd0).chr(0xb0); $bin = chr(0b11010000).chr(0b10110000); print "str:$str hex:$hex bin:$bin \n"; --- Добавлено --- Все таки придется делать тесты. По полчаса ковыряюсь с такой ерундой, что даже обидно. Начал запиливать тесты.
мне не понятно, что ты делаешь зачем тебе превращать во что-то букву а если это просто буква а и она может быть ключем в массиве или частью строки как есть, безо всяких превращений
Все таки придется делать тесты. По полчаса ковыряюсь с Все преобразования были лишними. Исправил, спасибо. Ты сказал, что можно как-то обойтись без str_pad(). Как это можно сделать?
Выжал чуть больше попугаев из unpack. Число длиной 6 байт. 4.1861s на 1 млн. операций Код (Text): function unpack_mod(string $str) { return hexdec(strrev(unpack('h*', $str)[1])); } 4.2747s на 1 млн. операций Код (Text): function unpack_48(string $str) { return unpack('P', str_pad($str, 8, "\0"))[1]; } Прирост скорости 2.07% Можно ли еще быстрее? --- Добавлено --- Я что-то такое пробовал уже. Тогда не получилось. --- Добавлено --- Термин даже есть у этой процедуры. https://en.wikipedia.org/wiki/Sign_extension
Термин даже есть у этой проценд Саму сдвижку и переключение битов я сделал вроде бы правильно, т.е. побитовыми операциями можно более короткое число сделать более длинным в двоичном представлении. Само двоичное число сделать не проблема. Проблема в том, чтобы как-то распаковать строку длиной 6 байт. Именно там относительно долгий str_pad() используется. Вот у меня такая упакованная строка 4Vx�, что с ней сделать, чтобы ее взял как родную 64 битную unpack?
я не пони ты спрашиваешь как шесть байт превратить в инт? --- Добавлено --- ну во-первых можно всегда умножать это дорого, но если целочисленно, то может быть быстрее анпака --- Добавлено --- $i = ($ar[3]<<24) + ($ar[2]<<16) + ($ar[1]<<8) + $ar[0]; отсюда https://stackoverflow.com/questions/12683833/how-to-convert-byte-array-to-integer-in-php вопрос что быстрее - ты попробуй и скажи мне
Занимательная фигня. Спойлер Код (Text): function unpack_mod(string $str) { return hexdec(strrev(unpack('h*', $str)[1])); } function unpack_48_mod2(string $str) { $ar = unpack("C*", $str); return ($ar[6] << 48) + ($ar[5] << 36) + ($ar[4] << 24) + ($ar[3] << 16) + ($ar[2] << 8) + ($ar[1]); } function unpack_24_mod2(string $str) { $ar = unpack("C*", $str); return ($ar[3] << 16) + ($ar[2] << 8) + ($ar[1]); } function unpack_48(string $str) { return unpack('P', str_pad($str, 8, "\0"))[1]; } function pack_48(int $i) { return substr(pack('P', $i), 0, 6); } function pack_24(int $i) { return substr(pack('V', $i), 0, 3); } function unpack_24(string $str) { return unpack('V', str_pad($str, 4, "\0"))[1]; } Вот результаты тестов: Код (Text): Array ( [times] => 100000 [int3] => Array ( [int3] => 15599999 [str3] => ▒ [pack_24_hex] => 7f09ee [unpack_24] => 15599999 [unpack_mod] => 15599999 [unpack_24_mod2] => 15599999 ) [int6] => Array ( [int6] => 1234567890 [str6] => ▒▒I [pack_48_hex] => d20296490000 [unpack_48] => 1234567890 [unpack_mod] => 1234567890 [unpack_48_mod2] => 1234567890 ) ) Array ( [int6] => Array ( [unpack_48] => 0.41487097740173 [unpack_mod] => 0.4118549823761 [unpack_48_mod2] => 0.48053193092346 ) [int3] => Array ( [unpack_24] => 0.24093008041382 [unpack_mod] => 0.241858959198 [unpack_24_mod2] => 0.25665903091431 ) ) Первый массив со входными данными, второй массив с результатами тестов. Видимо вызов unpack самый дорогой тут, потому что в первых 2 функциях он вызывается как бы однократно для большого числа, а в последней функции - по числу байт.
я предложил тебе вариант, чтобы от анпака отказаться вообще, а не юзать вместе оба --- Добавлено --- у тебя же после сдвига получается число, его не нужно пихать в анпак уже --- Добавлено --- это готовое число, бери и используй
Я не понял как надо сделать. Т.е. хочешь сказать, что надо двигать прямо строку? --- Добавлено --- Там же строка на входе перед анпэком. --- Добавлено --- Код (Text): <?php $s = pack('C', 244); Print $s[0] << 0; Так не работает, просит число, чтобы двигать.
отдельные байты строки, да 1. тебе не надо пакать ничего. работай с байтами 2. взял байт из строки, сдвинул байт - получил число. канэц. --- Добавлено --- т.е. pack()/unpack() уходит
PHP: $ar = "abcd"; $i = (ord($ar[3])<<24) + (ord($ar[2])<<16) + (ord($ar[1])<<8) + ord($ar[0]); --- Добавлено --- пробуй на скорость
Получилось быстрее. Код (Text): [int6] => Array ( [unpack_48] => 0.45364308357239 [unpack_mod] => 0.43855810165405 [unpack_48_mod2] => 0.46687388420105 [unpack_48_mod3] => 0.40635180473328 ) на 7.3% быстрее самого быстрого способа.
заебись, едем дальше переделай свой код на новый вариант, прогони тесты, чтобы точно знать, что всё осталось как было тесты нужны. если тестов нету - сделай и прогони на старом, сделай новый код, прогони тесты на новом. дальше поедем вырезать strpad =)
Выходит unpack, вообще нет смысла использовать. Сделал по аналогии вместо pack. Код (Text): function pack_24_mod(int $i) { return chr($i & 0xFF) . chr(($i >> 8) & 0xFF) . chr(($i >> 16) & 0xFF); } function pack_24(int $i) { return substr(pack('V', $i), 0, 3); } Код (Text): [pack_24] => 0.21841502189636 [pack_24_mod] => 0.22249889373779 --- Добавлено --- Сейчас допишу для остальных функций. Пока сделал для всех элементарных функций тесты. --- Добавлено --- strpad() получается больше не нужен, он был как раз в unpack, это единственное его место.
таким же макаром (или через | ) можно отказаться от стрпада --- Добавлено --- а, ок, понял --- Добавлено --- пиши тесты, будем дальше упрощать
Делать тесты оказалось сложнее, чем делать то, что они проверяют. В процессе написания тестов пришлось даже рефакторить код, чтобы пройти тесты. Но зато теперь покрытие тестами 92% и в ходе их написания было выявлено кажется 2 ошибки. Надо все таки попробовать хотя бы раз сделать сначала тест, а потом код.