Комментарии 65
Нужно везде искать плюсы. Например, нагрузка на сервер была в 150 раз меньше.
+5
Полезная нагрузка.
+8
НЛО прилетело и опубликовало эту надпись здесь
Напомнило
— Да в вашем Це два креста вообще плюсов нет!
— Вообще-то есть. Например, я нашел целых два прямо в названии.
;-)
— Да в вашем Це два креста вообще плюсов нет!
— Вообще-то есть. Например, я нашел целых два прямо в названии.
;-)
+7
А еще энтропия во Вселенной медленнее увеличивалась.
0
Есть такое хорошее слово «Энергоэффективность»…
0
Нужно везде искать плюсы.
C++.
C++.
0
Молодец. Но и сам не с того конца подошел, не так ли. Профилирование наше все :)
0
Профилирование вещь такая — своеобразная. С ним надо внимательно.
Я как на результаты с локом в msvcrt посмотрел — была первая мысль «а не стащить ли с линукса lock-free memory allocator». Хорошо что удержался от этой (в данном случае) глупости и стал дальше смотреть, а то можно было бы сурово засесть за полировку ногтей вместо решения проблемы.
По факту я тогда за БД и взялся, чтобы мозги прочистились и результаты профилирования сложились бы в какую-то разумную картинку. Помогло — наутро сообразил, что лечить надо не симптомы.
А то статья бы начиналась «и после трех месяцев тупизны и полировки ненужного я догадался посмотреть в профайлере не только первых пять позиций» ;-)
Я как на результаты с локом в msvcrt посмотрел — была первая мысль «а не стащить ли с линукса lock-free memory allocator». Хорошо что удержался от этой (в данном случае) глупости и стал дальше смотреть, а то можно было бы сурово засесть за полировку ногтей вместо решения проблемы.
По факту я тогда за БД и взялся, чтобы мозги прочистились и результаты профилирования сложились бы в какую-то разумную картинку. Помогло — наутро сообразил, что лечить надо не симптомы.
А то статья бы начиналась «и после трех месяцев тупизны и полировки ненужного я догадался посмотреть в профайлере не только первых пять позиций» ;-)
+3
«а не стащить ли с линукса lock-free memory allocator»
Всем все лишь бы стащить.
HeapCreate (флаг HEAP_NO_SERIALIZE)
+1
(пугается)
Я же имел в виду нечто вот такое, которое вполне себе lock-free thread-safe.
Впрочем, таких реализаций несколько, эта мне сейчас первая в гугле попалась.
Setting HEAP_NO_SERIALIZE eliminates mutual exclusion on the heap. Without serialization, two or more threads that use the same heap handle might attempt to allocate or free memory simultaneously, which may cause corruption in the heap.
Я же имел в виду нечто вот такое, которое вполне себе lock-free thread-safe.
Впрочем, таких реализаций несколько, эта мне сейчас первая в гугле попалась.
+1
Ок, виноват, забыл, что под lock-free обычно имеют ввиду thread-safe.
Глянул одним глазом код аллокаторов. Используются те же спин-блокировки, что и в EnterCriticalSection, так что один фиг.
Но тем не менее, не вижу необходимости в многопоточнй куче для данной задачи, если обработку каждой страницы делать в отдельном потоке, тогда алгоритм парсинга страницы будет отднопоточным и синхронизация внутри алгоритма не потребуется.
Глянул одним глазом код аллокаторов. Используются те же спин-блокировки, что и в EnterCriticalSection, так что один фиг.
Но тем не менее, не вижу необходимости в многопоточнй куче для данной задачи, если обработку каждой страницы делать в отдельном потоке, тогда алгоритм парсинга страницы будет отднопоточным и синхронизация внутри алгоритма не потребуется.
0
А вы не рассматривали использование string::reserve() для уменьшения реаллокаций? Все таки использование char * может быть чревато ошибками.
+1
Там подавляющее большинство const char*, так что — вряд ли.
А reserve() помогло бы в весьма ограниченном числе мест, т..к. фонтан пересоздаваемых строк никак бы не уменьшился.
Вот для иллюстрации,
Хотя по факту достаточно хранить саму строчку и пачку указателей на ее части.
А reserve() помогло бы в весьма ограниченном числе мест, т..к. фонтан пересоздаваемых строк никак бы не уменьшился.
Вот для иллюстрации,
class URL
{
public:
URL(const URL* context, const char* spec);
URL(const char* spec);
...
private:
bool parseURL(const char* spec, int start, int limit);
...
std::string protocol;
std::string host;
std::string domainSuffix;
int port;
std::string file;
std::string query;
std::string authority;
std::string path;
std::string userInfo;
std::string ref;
};
Хотя по факту достаточно хранить саму строчку и пачку указателей на ее части.
0
Может стоит в тексте сразу написать, что вместо копирования подстроки в отдельную переменную используются указатели на начало и конец подстроки.
0
В нормальных реализациях std::string есть copy-on-write, так что при условии что строки не модифицируются, ни какого глубокого копирования не происходит. Единственное известное мне исключение — VC++
+4
Это как раз был именно он — VC++ ;-)
+2
Можно тогда длинную строку сделать и накодить быстренько класс stringref, который бы как раз работал с подстроками.
0
Ну например в STLport строки были тоже не COW. А также в новой Clang'овой libc++ тоже было принято решение делать строки не COW, а с short sring optimization.
И COW может привести к плохой производительности в многопоточных программах, потому что счётчик ссылок всё равно надо защищать.
Обсуждение и пара ссылок в этом вопросе на StackOverflow
И COW может привести к плохой производительности в многопоточных программах, потому что счётчик ссылок всё равно надо защищать.
Обсуждение и пара ссылок в этом вопросе на StackOverflow
+1
А с юникодными урлами оно как работает?
0
Мне по тексту показалось «пользуйтесь готовыми библиотеками, вместо закатывания солнца вручную» что ребята тоже придерживались такой логики, только не там где это стоило делать.
+5
Ширше (или ширее) пользуйтесь готовыми библиотеками, вместо закатывания солнца вручную.
Они и пользовались во весь рост.
Результат оптимизации хороший, но так много статей «ОНИ vs Я» и так мало «посмотрите какой хороший код, мне бы так»
Они и пользовались во весь рост.
Результат оптимизации хороший, но так много статей «ОНИ vs Я» и так мало «посмотрите какой хороший код, мне бы так»
+4
(разводит руками) ядро линукса что-ли в пример привести, какую-нибудь ветку 2.2, она попроще?
А на С++ я с ходу и не подскажу, куда так смотреть можно. WebCore разве что, или Qt на ночь перечитывать.
А на С++ я с ходу и не подскажу, куда так смотреть можно. WebCore разве что, или Qt на ночь перечитывать.
0
Скорее это просто мысли в слух нежеди претензия.
Очень много в нашей индустрии ругают своих коллег. На эту ситуацию можно посмотреть с другой стороны — заказчики возможно хотели 10 страниц в секунду за дешево, получили только 2, неудовлетворившись пошли уже к более квалифицированному инженеру из Германии (?), месячный оклад которого плюс соц. отчисления, налоги и прочее может прокормить маленькую деревушку в Индии в течении года.
Вопрос часто не стоит в качестве кода, а в том что требуется заказчику и насколько хороший результат он готов оплатить.
Очень много в нашей индустрии ругают своих коллег. На эту ситуацию можно посмотреть с другой стороны — заказчики возможно хотели 10 страниц в секунду за дешево, получили только 2, неудовлетворившись пошли уже к более квалифицированному инженеру из Германии (?), месячный оклад которого плюс соц. отчисления, налоги и прочее может прокормить маленькую деревушку в Индии в течении года.
Вопрос часто не стоит в качестве кода, а в том что требуется заказчику и насколько хороший результат он готов оплатить.
0
Так если б я как та бангалорская деревушка — полгодика бы по-повышал производительность с 1 страницы аж до двух — мне бы тоже платили плошку риса в день, не?
Я ведь не только рис ем, да и местный direktsaft тоже недешев. Вот и приходится отжиматься на совесть, а не с 9 до 6 с перерывом на бассейн и трехчасовой ланч.
Мне кстати некоторые заказчики так и говорят — ну ты Виктор и знаешь толк во вкусной и (не)полезной пище — то лапшу тебе японскую, то сок с кокосовым молоком тайский, а если стейк так рибаи! А я им — да полноте, швайнебратен — вот наш выбор!!!, а рибаи да лапша — это я так, эстетствую ;-)
Я ведь не только рис ем, да и местный direktsaft тоже недешев. Вот и приходится отжиматься на совесть, а не с 9 до 6 с перерывом на бассейн и трехчасовой ланч.
Мне кстати некоторые заказчики так и говорят — ну ты Виктор и знаешь толк во вкусной и (не)полезной пище — то лапшу тебе японскую, то сок с кокосовым молоком тайский, а если стейк так рибаи! А я им — да полноте, швайнебратен — вот наш выбор!!!, а рибаи да лапша — это я так, эстетствую ;-)
+1
Читал вслух! Отличная пятничная статья!
+1
> SAX — это так сложно
А вы не боитесь что простой HTML не совсем XML или это всетаки был XHTML? А то вдруг найдется вумный дизайнер который забудет закрыть p или li где-то в середине страницы?
А вы не боитесь что простой HTML не совсем XML или это всетаки был XHTML? А то вдруг найдется вумный дизайнер который забудет закрыть p или li где-то в середине страницы?
0
Судя по тому, что эти теги просто выкидывали регулярками, то в данном случае это не страшно.
0
Я брал libxml2. У нее есть (были?) именно HTML Chunks.
/*
* Summary: interface for an HTML 4.0 non-verifying parser
* Description: this module implements an HTML 4.0 non-verifying parser
* with API compatible with the XML parser ones. It should
* be able to parse "real world" HTML, even if severely
* broken from a specification point of view.
*
* Copy: See Copyright for the status of this software.
*
* Author: Daniel Veillard
*/
+6
хорошо и с юмором — отлично! :)
0
>>Беру char*
Специально для вас был придуман string::reserve
Специально для вас был придуман string::reserve
+1
->Регулярные выражения для разбора мегабайтных структурированных файлов — это плохо
На собеседовании надо мной слегка хихикали, когда я свои уже имеющиеся решения рассказывал, типа почему не использовал регулярные выражения. То что разница в скорости в более чем в 40 раз, что производительность упирается в парсер на тормозном доступе в нет, это мелочь, башь — вот где сила.
->Понятно, сами выражения после их тюнинга я не привожу — это огромная простыня нечитаемых закорючек.
Даже если б оно приемлемо работало, регексы слить стоило только за это. Даже строчка, ищущая IP адрес выглядит практически нечитаемо и очень медленно работает, что говорить про более сложные конструкции.
На собеседовании надо мной слегка хихикали, когда я свои уже имеющиеся решения рассказывал, типа почему не использовал регулярные выражения. То что разница в скорости в более чем в 40 раз, что производительность упирается в парсер на тормозном доступе в нет, это мелочь, башь — вот где сила.
->Понятно, сами выражения после их тюнинга я не привожу — это огромная простыня нечитаемых закорючек.
Даже если б оно приемлемо работало, регексы слить стоило только за это. Даже строчка, ищущая IP адрес выглядит практически нечитаемо и очень медленно работает, что говорить про более сложные конструкции.
+1
Глупый вопрос: а зачем решать подобную задачу на C++? Есть же более подходящие для этого языки. И накосячить в них сложнее.
0
>Даже строчка, ищущая IP адрес выглядит практически нечитаемо
а приведите её для примера плз.
а приведите её для примера плз.
0
Ничего если я?
IPv4 only
IPv4 only
(\d(\d(\d)?)?\.\d(\d(\d)?)?\.\d(\d(\d)?)?\.\d(\d(\d)?)?)|(\h(\h)?\.\h(\h)?\.\h(\h)?\.\h(\h)?)
;-)-4
НЛО прилетело и опубликовало эту надпись здесь
150 раз разницы в производительности — это они всерьез или может так и задумали эти ребята чтобы потом еще тянуть из заказчика деньги?
+1
Сначала я подумал — к чему тут картинки? А оказалось — просто свежие с openclipart понадёргано.
+3
Да, я лентяй, я уже признавался ;-)
Обычно картинки беру именно там, не надо рисовать самому и с лицензиями порядок.
Вот поясню ход моих мыслей, почему взял именно эти.
1. Ага — ускоряем производительность, то есть устраняем узкие места, или решаем задачу «в одну трубу втекает, в другую вытекает»). Оно.
2. Приступаем к вскрытию — то есть проникаем — проникает кто? спецназ — кто там самый был? аватар.
3. Берем в руки профилировщик — давно шашку в руки не брал — рыцарь — гладиатор.
4. Опасность — бомба (банально) — бережемся от — о! берегите спички от детей!
5. Что делал я — я кто? инженер — вот тебе кульман, расписался тут понимаешь!
6. Плохо — почему? последствия — нос разобьешь — какой пингвин отличный, как раз скользит и падает!
7. Снаряд — пушка (банально), подход — штанга, брутально. О, мультик вспомнил про Спортландию, странно что там лука не было. Точно — лук со снарядами перекликается, беру!
8. Святой Коннектий — святой — фольклор — фея. Опа! в стиле техно, отлично!
Ежик — означает храбрость (С) КВН
Обычно картинки беру именно там, не надо рисовать самому и с лицензиями порядок.
Вот поясню ход моих мыслей, почему взял именно эти.
1. Ага — ускоряем производительность, то есть устраняем узкие места, или решаем задачу «в одну трубу втекает, в другую вытекает»). Оно.
2. Приступаем к вскрытию — то есть проникаем — проникает кто? спецназ — кто там самый был? аватар.
3. Берем в руки профилировщик — давно шашку в руки не брал — рыцарь — гладиатор.
4. Опасность — бомба (банально) — бережемся от — о! берегите спички от детей!
5. Что делал я — я кто? инженер — вот тебе кульман, расписался тут понимаешь!
6. Плохо — почему? последствия — нос разобьешь — какой пингвин отличный, как раз скользит и падает!
7. Снаряд — пушка (банально), подход — штанга, брутально. О, мультик вспомнил про Спортландию, странно что там лука не было. Точно — лук со снарядами перекликается, беру!
8. Святой Коннектий — святой — фольклор — фея. Опа! в стиле техно, отлично!
Ежик — означает храбрость (С) КВН
+1
Аплодирую стоя! А какой профилировщик брали?
0
Смеяться на индусами уже как-то стыдно даже. Куда ни глянь: «Need deceloper NOT FROM INDIA/PAKISTAN!»
+1
> Новая картинка — сборщик по-прежнему занят на 100%, БД на 2%, теперь четыре страницы в секунду.
Да вы же повысили производительность исходного кода В ДВА РАЗА! Можно было взять отпуск, а по возвращению сдавать первую версию и тут же предлагать начать разработку второй.
Да вы же повысили производительность исходного кода В ДВА РАЗА! Можно было взять отпуск, а по возвращению сдавать первую версию и тут же предлагать начать разработку второй.
0
Оффтоп: картинки с супергероями делали сами с помощью HeroMachine? Я прям заностальгировал, игрался в них в детстве.
0
НЛО прилетело и опубликовало эту надпись здесь
2 недели на исправления парсинга нескольких цифр из хтмля?
+1
Все остальное было скучно и неинтересно, даже и писать-то не о чем. Исправили баги номер… переделали синхронизацию… исправили то то и это… добавили из фичреквеста пункты…
Обычные будни. Кому интересно читать про «как поправили CSS чтобы могучая закладка в 2 строчки текста не разваливала пол-страницы, баг нумер такой-то»?
А вот про особенности оптимизации — по крайней мере есть о чем рассказать.
Обычные будни. Кому интересно читать про «как поправили CSS чтобы могучая закладка в 2 строчки текста не разваливала пол-страницы, баг нумер такой-то»?
А вот про особенности оптимизации — по крайней мере есть о чем рассказать.
+1
басня «Индусы и д'Артаньян» :)
Интересно, какой процент изначального кода остался жив после оптимизации? Не проще ли было выбросить это чудовище и написать с нуля?
Интересно, какой процент изначального кода остался жив после оптимизации? Не проще ли было выбросить это чудовище и написать с нуля?
0
> Автоинкрементные поля также убрал, вместо них вставил UUID (для подсчета нового значения может приползать неявный lock table)
Это в какой субд так? В mysql — не так
Это в какой субд так? В mysql — не так
0
Вот тут написано следующее:
When accessing the auto-increment counter, InnoDB uses a special table-level AUTO-INC lock that it keeps to the end of the current SQL statement, not to the end of the transaction. The special lock release strategy was introduced to improve concurrency for inserts into a table containing an AUTO_INCREMENT column. Nevertheless, two transactions cannot have the AUTO-INC lock on the same table simultaneously, which can have a performance impact if the AUTO-INC lock is held for a long time. That might be the case for a statement such as INSERT INTO t1… SELECT… FROM t2 that inserts all rows from one table into another.
Фактически, это означает что все bulk inserts бодренько выстраиваются в очередь на table lock — per statement, и не особенно то и спасает, что лок в журнал не попадает. Емнип fast mutex прикрутили только в 5.1.
А теперь представьте себе картинку, что это счастье идет в конкурентных транзакциях в параллель, что в транзакции таких инсертов не один, и получим весьма существенный penalty.
When accessing the auto-increment counter, InnoDB uses a special table-level AUTO-INC lock that it keeps to the end of the current SQL statement, not to the end of the transaction. The special lock release strategy was introduced to improve concurrency for inserts into a table containing an AUTO_INCREMENT column. Nevertheless, two transactions cannot have the AUTO-INC lock on the same table simultaneously, which can have a performance impact if the AUTO-INC lock is held for a long time. That might be the case for a statement such as INSERT INTO t1… SELECT… FROM t2 that inserts all rows from one table into another.
Фактически, это означает что все bulk inserts бодренько выстраиваются в очередь на table lock — per statement, и не особенно то и спасает, что лок в журнал не попадает. Емнип fast mutex прикрутили только в 5.1.
А теперь представьте себе картинку, что это счастье идет в конкурентных транзакциях в параллель, что в транзакции таких инсертов не один, и получим весьма существенный penalty.
0
Cool story! =)
Оптимизировали, оптимизировали, и наконец выоптимизировали!
Такого рода код очень часто приходит от аутсорсеров, к сожалению, и иногда легче всё переписать с нуля, нежели разгребать завалы неправильной кривой архитектуры и индокода в перемешку с быдлокодом и костылями под костылями.
Оптимизировали, оптимизировали, и наконец выоптимизировали!
Такого рода код очень часто приходит от аутсорсеров, к сожалению, и иногда легче всё переписать с нуля, нежели разгребать завалы неправильной кривой архитектуры и индокода в перемешку с быдлокодом и костылями под костылями.
0
Не раскрыта важная тема заказчика — какие у него были начальные ожидания от вашей работы, какие впечатления от конечной оптимизации, от работы великолепной четверки и сделал ли он какие-нибудь выводы на будущее? В)
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
О тонкостях повышения performance на С++, или как делать не надо