Салимóненко Дмитрий Александрович
Разное
Честно говоря, даже не знаю, как озаглавить эту статью, поэтому озаглавил так. Недавно мне в очередной раз рекомендовали «обновить браузер», а я в очередной раз (прямо «как этот») разъяснял, почему этого делать не стоит, как минимум, в моем случае. Ну, прошло сколько-то дней. Отлаживаю у себя сайт. Вдруг, смотрю, PHPStorm стал тормозить, просто безбожно. Ну, думаю, понятно… все эти новомодные явы и котлины, на коих он, PHPStorm-то, написан. Вот, типа того, и тормоза появились. В диспетчере задач загрузка ВСЕХ процессоров 100%. М-да…
Подумалось – это чего? Типа, «всё», что ли? Ну, на случай сохранил важные данные. Перегрузил компьютер. А вскоре – опять то же самое. Ну, ладно… тогда сделал откатку на более позднюю контрольную точку… Да что ж такое. Потом опять откатку на еще более позднюю – все равно без толку, проблема повторилась.
А переустановку системы мне как-то не хочется делать. Ибо, во-первых, за многие годы я уж и подзабыл, как это делается. Во-вторых, это же опять массу всего устанавливать заново… Заново делать настройки программ. Заново - устанавливать виртуальные машины, и там - ну, и т.д. Да, в общем, проблем – на несколько дней.
Потом обратил внимание – оказывается, это Denwer (Apache HTTP Server) в диспетчере задач занимает 99% ресурсов процессора, а вовсе не PHPStorm. Я тут же скоренько мысленно раскаялся перед его разработчиками.
Бо, я с уголовными «понятиями» (что весьма распространено у нас на России, да и не только здесь, впрочем), для которых раскаяние хуже всего на свете, даже хуже смерти - не хочу иметь ничего общего. Следует понимать, что раскаяние – это такой же естественный процесс, как утром умыться или чаю попить. Это должно быть «на автомате», без раздумий. Кто не понимает сей простейшей вещи – идите-ка от меня куда-нибудь подальше (а лучше – еще подальше, если есть возможность). Я-то уж знаю, что объяснять вам «таким» - бесполезно, только молчанку или хихикания в ответ можно услышать. И добро хоть, если только это, а не нечто иное, так сказать.
Вообще, физическая, искренняя неспособность раскаяться – это один из признаков уголовного характера. Такой человек живет в мире этих самых «понятий» и всё такое. Или, по-другому, может, так понятнее: физическая, искренняя неспособность раскаяться формирует именно такой тип характера, который в будущем «развивается» в сторону уголовных деяний и соответствующего социума. Притягивая к себе аналогичных людей и, конечно же, находя с ними общий язык. Т.е. если человек в упор не понимает, зачем, мол, это нужно-то – раскаиваться, не привык к этому – то лично мне с ним все ясно. Это – экспресс-тест. Совершил ли он уже кой-чего или (пока еще) нет – это уже второй вопрос. По мелочам или по крупному – опять же, это уже детали.
Разумеется, следует отличать: одно дело – человек с плакатом вышел или в интернете написал и признан, типа того, «уголовником». И совсем другое – когда ограбил, убил и/или пустил целую страну под откос. Вместе с ее народом.
Бывает так, что это – уголовник в прошлом, но потом ставший жить по-человечески, решивший более в подобные нюансы не ввязываться; но, корни-то остались, их-то он выкорчевать не желает. А бывают и полностью противоположные ситуации… их разглядеть иногда сложнее – до поры.
Кстати, наверное, именно поэтому один из великий римских полководцев отбирал себе в дружину таких воинов, которые краснели в случае, если ошиблись в чем-то. Т.е. тех, у кого совесть была. И тех, кто были способны к раскаянию.
Кстати, а теперь, на досуге, можете вспомнить о том, КОГО набирают нынче в, так сказать, «российские дружины». Вспомнили?... Вот так. Посему, можете теперь подумать о, так сказать, будущем сих дружин и их… ммм… влиянии на социум. И не надо фыркать, загораживаясь лете-визором и пытаться отводить разговорчики в сторону, якобы, мол, "и так все понятно". Нее, ещё не понятно. Всё еще впереди. 90% из вас ИМЕННО ЭТОГО ХОТЕЛИ. Речь-то не о Беларуси (и, тем более, не об Украине или Финляндии), а о России. И не надо страхи испытывать (а то я уже иногда слышу некоторые слова на этот счет). РАНЬШЕ бояться надо было, когда это еще можно было предотвратить. Сейчас – уже поздно.
Ладно, стал детализировать, что именно Денверу не понравилось. Любопытно, что в 24-м Firefox однажды даже некая ошибка вывелась на экран, а потом – просто молчок, да и все. Видимо, он полегче, по-проворнее, поэтому хоть что-то смог изобразить. Ну, а 36-й Firefox – вообще даже не желал отвечать, молчал изначально. В итоге, вскоре оказалось, что виной всему - примерно такое регулярное выражение:
'~([\s\S]*?)<span id\=\"qwe\">([\s\S]*?)<\/span>([\s\S]*?)$~'
Вроде, невинное такое с виду. И оно очень хорошо, быстро работает (в функции preg_replace), если в строке поиска СУЩЕСТВУЕТ соответствующий шаблон. А вот если НЕ существует – то сервер ищет, ищет его и в итоге нагружает все процессоры по максимуму, после чего для PHPStorm ресурсов уже не хватает. Все-таки, еще раз: язык java + язык Kotlin – это ужасная, убойная смесь. Конечно, оно в совокупности – самое то, если есть цель – подзагрузить у пользователя процессор на компьютере посильнее. Но, что-то мне сдается – едва ли у разработчиков была именно такая цель…
Впрочем, не все со мной согласны. Вроде как, к примеру, компания Goоgle – объявила сей язык аж одним из наиболее перспективных. Ну, Google... как бы сказать. В общем, это уже не то, что было лет 10...15 назад. Не удивлюсь, если в итоге Google будет куплен, скажем, тем же Илоном Маском. Ну, или Трампом каким-нибудь.
Кстати, при этом все остальное (браузеры, Word и т.д.) тем не менее, работали все так же быстро и безотказно. Так что все-таки у разработчиков PHPStorm вина все же есть, если уж разбираться до конца. Делали бы они его на С++, а не на этих своих Котлинах (Kotlin) - проблем бы, я думаю, вообще не было. Ну, да ладно.
А суть в том, что, по всей видимости (это уже мои догадки), что если РНР не может найти соответствие этому шаблону, то он начинает перебор С ЛЮБОГО места поисковой строки – вплоть до ее конца (см. символ $). Да еще тут у меня целых три шаблона (в скобках), которые обозначают любое количество любых символов. Понятно, что тут можно, и в самом деле, искать очень долго, если начинать поиск каждый раз с нового места.
И так все ищет и ищет, пытаясь найти соответствие (ну, мне так кажется, но могу быть неправым). А так как строка поиска занимает под полмегабайта, т.е. не столь малая, ну, в итоге очередная итерация поиска (с нового места в строке), видимо, и занимает ресурсы процессоров, все больше и больше.
А еще проблема, скорее всего, в том, что под любой символ вполне подходит и знак < тоже. А также буквы s, p, a, n и т.д. Т.е. у регулярного выражения - еще и неоднозначный выбор.
Внес небольшое изменение и проблема исчезла:
'~^([\s\S]*?)<span id\=\"qwe\">([\s\S]*?)<\/span>([\s\S]*?)$~'
Т.е. добавил символ ^ в начале регулярного выражения, чтобы поиск гарантированно начинался с самого начала строки.
Вроде, мелочь. Но, видимо, как-то я это раньше просмотрел. Почему? Видимо, потому, что тестировал-то на МАЛЫХ строках, там поиск так или иначе вскоре заканчивался, даже при отсутствии совпадений. Ибо меньше было вариантов перебора. А вот на большой строке – и аукнулось.
Причем, любопытно, что процессоры компьютера в результате некорректного поиска загружаются надолго, что приходится перезагружать Denwer. Впрочем, даже и это помогает не всегда.
В который раз уже убеждаюсь, что с регулярными выражениями следует быть ОЧЕНЬ внимательным, чтобы не допускалось подобных не то, чтобы ошибок, а как бы сказать… неоптимальных (или некорректных?...) выражений. Т.е. делать их так, чтобы они были заведомо… как бы это сказать… удобоваримыми для РНР, что ли.
Дело в том, что едва ли первый вариант можно назвать некорректным. На первый взгляд, он - вполне себе. Т.е. просто так, без тщательного тестирования (причем, на очень длинных строках), не скажешь, как оно себя поведет. Дело, именно, в «удобоваримости».
Иначе потом можно долго ходить вокруг да около. И вместо оптимизации программного кода «раздумывать» о более мощном компьютере – как это и делают ряд нынешних разработчиков. Особливо тех, кои имеют прям таки "неземную любовь" в разного рода абстракциям, особенно - многоуровневым.
Впрочем, так как актуальна там, на самом деле, лишь ВТОРАЯ группа замены (вторые круглые скобки), то, судя по всему, следовало применить не
preg_replace('~^([\s\S]*?)<span id\=\"qwe\">([\s\S]*?)<\/span>([\s\S]*?)$~', '$2', $string)
а нечто, вроде
preg_match('~<span id\=\"qwe\">([\s\S]*?)<\/span>~', $string, $matches)
или даже так:
preg_match('~<span id\=\"qwe\">([^<]*?)<\/span>~', $string, $matches)
И – смотреть $matches[1]
на предмет наличия совпадений по данной группе. И, при необходимости, выполнять замену. Так было бы гораздо быстрее, ибо уже нет этих «страшных» ([\s\S]*?)
.
А вот если бы все ограничивалось малыми строками (ну, на несколько килобайт, к примеру) - то я бы так и не узнал об этой ошибке. Так что те, кто всецело полагается на разработчиков неких высокоуровневых библиотек (а их сейчас - масса, пожалуй, даже больше, чем самих разработчиков), мол, "ну, они-то там наверняка все оптимизировали, там же обновления выходят" - те, мягко говоря, ошибаются. Потому как подобных ситуаций, на самом деле, много. Просто неохота обо всех них писать. И едва ли все подобные "особые ситуации" корректно обработаны в библиотеках. Ну, лично я в это не верю. Собственно, если о вере... и в бога-то - не особо верю, существую параллельно, если можно так выразиться. Ну, а уж в чужие разработки - тем более. Они ведь редко носят божественный (гениальный) характер.
С уважением, Салимоненко Д.А.