LINUX.ORG.RU

Чем заменить медленный PHP

 , , ,


0

3

Есть скрипт, очень простой. Входные данные - два словаря (просто два файла, где по слову на каждой строке). Несколько текстов - это просто строка.

Нужно регулярным выражением найти в тексте все слова из словаря и вернуть в виде массива все, что удалось найти.

Проблема - сделал словарь размером 400Мб и тут даже текст в одно слово - это очень и очень долго.

На чем переписать под Debian? Думал про bash, но вспомнил про python - и понял, что не знаю что выбрать. Учитывая bash я не знаю, а python немного знаю, а нужно максимум скорости.... но получу ли я ее на bash? Есть мечты отделать парой строк через exec...



Последнее исправление: postscreen (всего исправлений: 1)

python тут вряд ли поможет. Регэкспы сами по себе медленные. Думаю что проблема в твоем коде,

Jopich1
()
Ответ на: комментарий от Jopich1

Кстати я не понял ты слова в тексте ищешь без учета морфологии ? Если так то зачем тебе regexp если это быстрее делается через substring ( или что там в php ) ?

Jopich1
()
Ответ на: комментарий от Jopich1

while (($buffer = fgets($handle, 64000)) !== false) { preg_match_all('/[^а-я]'.trim($buffer).'[^а-я]/iSu', $text, $result); if( count($result[0]) != 0 and !in_array(trim($buffer), $isst_words) ){ $isst_words[] = trim($buffer); }

}

postscreen
() автор топика

Т.е. он каждое слово соотведствующее регулярке из текста ищет в словаре?

Словарь отсортирован? Тут для доступа к словарю нужно что-то похожее на индексы у БД. Чтобы не было нужды перебирать весь словарь.

Deleted
()
Ответ на: комментарий от devl547

Словарь то большой, как его еще туда поместить?

postscreen
() автор топика
Ответ на: комментарий от postscreen

Значит я бы сделал так, чтобы словарь не всегда читался с начала.

Deleted
()
Ответ на: комментарий от postscreen

Нужно регулярным выражением найти в тексте все слова из словаря и вернуть в виде массива все, что удалось найти.

что-то я не понял - тебе чего нужно найти сколько раз в тексте встречается слово из словаря ?

Ну разбей исходный текст по словам ( по пробелам ) и ищи совпадения без реэкспом по прямому совпадению ...

Jopich1
()
Ответ на: комментарий от anonymous

Как выглядит быстрый php в этом случае? Отказаться от чтения файлов? От чего? Вроде как-то можно в grep все сразу...

postscreen
() автор топика
Ответ на: комментарий от postscreen

засунь файлы со словарями в память в хэш. По нему и сравнивай

Jopich1
()
Ответ на: комментарий от postscreen

этот кусок вполне переписываем на баш, только вместо 64000 байтов будет строго 1 строка

но если тебе скучно, можешь взять golang||java||C#, читать файл построчно и асинхронно запускать поиск по регулярке, как только строка считалась

если тебе скучно и есть алкоголь||вещества, можешь взять rust||c++

Ford_Focus ★★★★★
()
Ответ на: комментарий от postscreen

быстрый php выглядит как смена алгоритма с «50 миллионов раз регэкспами колбасим текст любой длины» на что-то более разумное.

а скорее всего - в разумной постановке задачи

anonymous
()

нужно максимум скорости.... но получу ли я ее на bash?

Скорость самых быстрых морских черепах на суше.

Из этих двоих бери змеюку не задумываясь

annulen ★★★★★
()
Ответ на: комментарий от annulen

мы как-то лулзов ради сравнивали в подобной задаче ruby 1.9.3 против баша. баш отрывался от руби просто в десятки раз на почти 2 гиговом файле :)

не стоит обижать малышей они взрослых (С) позвать могут :)

Ford_Focus ★★★★★
()
Последнее исправление: Ford_Focus (всего исправлений: 1)
Ответ на: комментарий от postscreen

это не говоря уже о милых мелочах вроде поиска всех вхождений через preg_match_all а потом проверке что там есть хотя бы одно вхождение в count($result[0])

или проверке в цикле 50 миллионов раз !in_array(trim($buffer), $isst_words. пэхапэшники те еще говноеды, но надо же хоть немного понимать, почему это плохо.

в общем, проблема не в медленном пэхапэ, и не в том, что ты не знаешь питон. проблема в том, что ты вообще не одупляешь, что ты делаешь. тут не инструмент надо менять

anonymous
()
Ответ на: комментарий от postscreen

срань господня, я только посмотрел на регэкс. что, по-твоему, он должен искать?

anonymous
()

а нужно максимум скорости.... но получу ли я ее на bash?

Господь с вами. Язык коммандной оболочки и скорость — это на разных полюсах.

Возьмите хотя бы АВК, что ли. А если задача совсем примитивная, то может и grep’а хватить.

Zmicier ★★★★★
()
Последнее исправление: Zmicier (всего исправлений: 1)
Ответ на: комментарий от Zmicier

awk тоже не шибко быстр, за исключением mawk

annulen ★★★★★
()
Ответ на: комментарий от ism

на плюсах, да. чувак, да этот парень лоботомию пережил как минимум трижды, ты прикинь, что он напишет на плюсах, если на пехапе он пишет вот такое

while (($buffer = fgets($handle, 64000)) !== false) { 
	preg_match_all('/[^а-я]'.trim($buffer).'[^а-я]/iSu', $text, $result); 
	if( count($result[0]) != 0 and !in_array(trim($buffer), $isst_words) ){ 
		$isst_words[] = trim($buffer); 
	}
}
anonymous
()
Ответ на: комментарий от th3m3

мы банально можем взять одну задачу, написать на py3 и php7 и выполнить на своих машинах/серверах. почему бы и нет?

Ford_Focus ★★★★★
()

Нужно регулярным выражением

вот просто нет. Потому, что пони.

1) читаем словарь в память, кладем в хэшмап/ассоциативный массив, хз как оно в похапе называется, обзываем dict

2) читаем текст, разбиваем его на массив строк чем-нито типа split, обзываем input_words

3) заводим хэшмап найденных в тексте слов, обзываем found_words

4) проходим по массиву input_words, каждое слово проверяем на:

4.1) нахождение в found_words, если есть - пропускаем

4.2) нахождение в dict, если есть - добавляем в found_words

5) ключи found_words - искомое «все, что удалось найти»

arkhnchul ★★★
()
Последнее исправление: arkhnchul (всего исправлений: 2)

Можно взять, например, freebasic и сделать посимвольную обработку, анализируя на месте, и делая всё в один проход.

buratino ★★★★★
()

Ну ты молодец вместо пхп выбирать из ещё более тормозных и неудобных язычков.

Deleted
()

Такой «метод решения» на любом языке будет тормозить, на каком ни пиши. Тут надо менять сам подход к задаче

dave ★★★★★
()

Чем заменить медленный PHP
Думал про bash, но вспомнил про python - и понял, что не знаю что выбрать. Учитывая bash я не знаю, а python немного знаю, а нужно максимум скорости

python заметно медленнее, чем PHP, bash — НАМНОГО медленнее :)

Смотреть нужно в сторону Java/Golang/Rust.

Я сам в подобной истории, когда производительности PHP не хватает, стал Go использовать. Брат жив.

KRoN73 ★★★★★
()

медленный PHP

вспомнил про python

Звучит как «нужно чем-то заменить медленный автобус, вспомнил про самокат».

WereFox ★☆
()

1. если хочешь мгновенный результат, то засунуть словарь в индекс систему - solr, elastic.

2. если устраивает просто ускорение в 10-20 раз, но разбей словарь по индексу - хотя бы на первой букве. получшь n dict файлов, по которому будешь в около n раз быстрее искать.

язык не имеет значения.

vtVitus ★★★★★
()
Ответ на: комментарий от postscreen

Словарь нужно читать не по одному слову за раз, а хотя бы по 100к слов. Можно и сразу весь, 400Мб это не много.

trim нужно делать один раз.

Вместо preg_match_all достаточно preg_match - тебе же всё равно нужно узнать только факт что слово встречается. Зачем парсить весь текст и выбрасывать результат?

Самый эпик - in_array. Сделай хэш, и проверяй по array_key_exists.

no-such-file ★★★★★
()
Ответ на: комментарий от KRoN73

У опа проблема не выборе языка, а в алгоритме.

python заметно медленнее, чем PHP

Весьма спорное утверждение. На каких задачах? Каком-то синтетическом тесте? php научился в асинхронность? Хотя бы не умирать после запроса? Для питона есть всякие numpy, cython, pypy если уж очень надо.

pawnhearts ★★★★★
()
Ответ на: комментарий от pawnhearts

Весьма спорное утверждение. На каких задачах?

На задаче топикстартера :)

У опа проблема не выборе языка, а в алгоритме.

Само собой. Но это другая история.

KRoN73 ★★★★★
()

Словарь надо билдить в конечный автомат при загрузке. Чтобы быстро билдить - надо делать это лениво. Смотри конкурс от компании Hola, там народ фильтры по email писал на JS. Есть очень быстрые решения с кодом + статьи на хабре описывающие код.

Norgat ★★★★★
()
Ответ на: комментарий от anonymous

Хм.. Кое что я не правильно задании понял, но да ладно. Вот довольно быстрый код на PHP. Можно сделать намного быстрее с отсортированным словарём, но для этого надо постараться, а мне лень. :-P

<?php

$text = "Мама мыла раму";
$words = array_unique(array_map('mb_strtolower', preg_split("~\W+~u", $text)));

//We suppose dictionary is normalized already: contains only lowercased words and no empty strings
$foundWords = [];
$fh = fopen('dictionary.txt', 'r');
while ($strRaw = fgets($fh)) {
    $str = trim($strRaw);
    if (in_array($str, $words)) {
        $foundWords[] = $str;
    }
}
fclose($fh);

print_r($foundWords);

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.