Сейчас я расскажу о бесполезной микрооптимизации, или как ускорить то, что и так быстро работает, в четыре раза.
Вот, допустим, в каком-то опенсорс проекте есть вот такой код:
guid тут - это, скорее всего, строка вроде такой: 644e1dd7-2a7f-18fb-b8ed-ed78c3f92c2b.
t - что-то такое: 2005-08-09T18:31:42.201
gsub!, очевидно, заменяет двоеточия и точки на подчёркивания.
Его и будем ускорять.
Оптимизируя gsub!, можно использовать разные подходы. Можно упростить регулярку. Иногда можно заменить gsub! на sub!. Можно заменить gsub! на gsub. Иногда помогает замена gsub! на tr!, если это применимо. Иногда помогает замена регулярки на простую строку. Попробуем всё, что можно:
И вот результаты:
Звёздочкой отмечена оригинальная версия. Как и следовало ожидать, tr с друзьями разгромил gsub-ы. Также легко заметить что gsub со строкой в качестве первого аргумента рвёт регексповый вариант.
Легко заметить, что двоиточия и точки могут быть только в t, поэтому достаточно tr прогонять только по этой подстроке. Попробуем:
Можно попробовать ещё по хардкору ускорить. Мы-то знаем, где в t двоеточия и точки, правильно? Вот туда и вкостылим подчёркивания.
Провал. Можно ещё попробовать зафризить строковые константы.
Победно. Тут, кстати, заметно, что срабатывает костыль, добавленный в руби 2, связанный с заморозкой строковых литералов. Когда руби парсер видит замороженный литерал, он делает свою чёрную магию, и под мороженый литерал память выделяется только один раз, даже если его морозить в цикле. В 1.9.3 такого не было! В качестве пруфа - результаты этого же бенчмарка, но для руби 1.9.3:
И, наконец, сравним победителя и оригинальную версию: