> ## Content Index
> Fetch the complete content index at: https://www.rozhkov.me/llms.txt
> Use this file to discover other available public pages before exploring further.

# Мікрооптимізації vs читаємість
- URL: https://www.rozhkov.me/microoptimizations-vs-readability/
- Published: 2022-08-31T06:15:00.000Z
- Updated: 2022-08-31T09:28:35.000Z
- Author: Vova Rozhkov
- Tags: робота

[Бот для управління чатом](https://www.rozhkov.me/telegram-status-bot/) зроблений на Ruby on Rails. Для визначення команди використовується наступна конструкція: `if command.downcase == "!ban"`

`.downcase` тому що раніше на телефоні мав клавіатуру яка після знаку оклика піднімала регістр. Зараз вже не така, але регістро-незалежний код залишився.

У всіх Rails проектах для підтримання порядку використовую лінтер [Rubocop](https://rubocop.org/). Крім форматування він ще підказуває ідіоматичні речі та перформенс проблеми. І от після чергового [регулярного апдейту пакетів](https://www.rozhkov.me/rotting-software-update/) я проганяю рубокоп, а він мені і каже:

```
app/models/moderator_bot.rb:42:8: C: [Correctable] Performance/Casecmp: Use command.casecmp("!ban").zero? instead of command.downcase == "!ban".
    if command.downcase == "!ban"
       ^^^^^^^^^^^^^^^^^^^^^^^^^^
```

Ну я такий думаю ок, зроблю `rubocop -A`, хай автоматом підставить те що треба. Зробив, забув.

Нещодавно додавав ще одну команду, дивлюся на той код, а він мені не подобається. Ну от уявіть, замість простого і всім зрозумілого `downcase` та `==` я тепер бачу сішне `casecmp` а потім ще й `zero?`. Треба пам'ятати що є така функція яка порівнює рядки, і якщо вони співпадають, то вона вертає 0, а якщо не співпадають, то щось відмінне від 0, можливо 1, а можливо і -1.

Я вирішив що так діла не буде, і треба викинути гидку сішну конструкцію. Та стало цікаво, звідки взагалі взялося це правило. Пішов на [документацію](https://docs.rubocop.org/rubocop-performance/cops%5Fperformance.html#performancecasecmp), там є посилання на гітхаб з бенчмарками та результатами замірів. Різниця між `==` та `casecmp` у нас [така](https://github.com/fastruby/fast-ruby#stringcasecmp-vs--stringcasecmp-vs-stringdowncase---code):

```
Comparison:
      String#casecmp:  6948231.0 i/s
String#downcase + ==:  5017089.5 i/s - 1.38x  (± 0.00) slower
     String#casecmp?:  3686650.7 i/s - 1.88x  (± 0.00) slower
```

Тобто «оптимізоване» порівняння рядків буде аж на 40% швидше! Ніби непогано! Але сама операція при цьому займає 200 *нано*секунд! ~~Тих порівняннь у мене по коду п'ять штук далі.~~ З одного боку я розумію що от з таких 50 наносекунд різниці тут і там, потім складається повільний веб, але не у моєму випадку тільки в базу сходити буде коштувати десяток мілісекунд.

Вони б ще туди інтрінсіки запхали, їй-б-гу.

Викинув те правило та повернув все на `==`. Чого і вам бажаю.

*upd: Уважний читач Ігор Є. помітив, що замість «п'яти порівнянь далі по коду» можна зробити extract variable. І хоча пост не зовсім про це, а більше про читаємість, маю зізнатися що тут я дав маху. Зовісм глупий став.*