Стендап Сьогодні 📢 Канал в Telegram @stendap_sogodni

🤖🚫 AI-free content. This post is 100% written by a human, as is everything on my blog. Enjoy!

16.09.2024

Чому "переписувати на мову" в принципі погана ідея?

Коли програма працює повільно, традиційно чуєш ідею — перепишім на мові Y! На мою думку, так варто робити тільки після того, як вичерпано можливості оптимізації. Яких завжди знаходиться багато. Звісно, переписати іншою мовою легше (в наш час, певно, майже автоматично) - але потенційний виграш тут менше, а підтримка такого рішення значно ускладниться, особливо коли йдеться про живий продукт, а не іграшкову програму.

Переписав вчорашній приклад на Go. Це не найшвидша мова, але мені найзручніша. Повільність Go здебільшого стосується збірки сміття, якого в цьому прикладі можна взагалі уникнути. Також програму на Go мені буде легко зробити паралельною. Ось gist з всіма розвʼязками.

🟰 Наївний переклад працює на 10% швидше за Паскаль. Зазначу що це вже не найгірше рішення — воно створює масиви заздалегідь, а не на кожну ітерацію. Але не бачу сенсу штучно погіршувати програму, порівняно з оригіналом. Різниця в 10% досить передбачувана — обидві мови типізовані, компілюються; не здивуюся, якщо машинний код програм майже однаковий.

Перша оптимізація коду з купою арифметики: не повторюймо операції! Особливо ділення — найповільнішу з операцій. Інтуїція підказує, що арифметика — це швидко; але коли вся програма — це одна арифметика, мусимо звернути увагу на кожний вираз. Дещо можна було навіть винести з циклу та викликати у 200 000 разів рідше.

➖ Також приклад робив зайві обчислення заради виводу результату; вивід відбувався раз на 100 ітерацій, а обчислення — щоразу. Усунення повторюваних та зайвих операцій прискорило розвʼязок у 2 рази!

✖️ Друга оптимізація: використовуйте локальні змінні. Тут сам здивувався. Початкова програма весь стан тримала в глобальних змінних. Так, мені здавалося, я заощаджу на керуванні памʼяттю. Але ось що виявилось: перенесення всіх змінних всередину функції прискорив розвʼязок ще в 3 рази! В 3 рази! Я знаю, що глобальні змінні розташовуються в BSS-сегменті, а локальні — на стеку, але ніяк не очікував таку величезну перевагу останнього. Перевіряйте свої переконання!

➕ Отже, переписування зробило програму швидше на 10%, а оптимізація — на 82%. Та ті ж самі нехитрі оптимізації можна було зробити й на Паскалі. І це тільки найпростіша програма, без кешування, всяких неефективних структур даних, чи алгоритмів з експоненційною складністю. Не поспішайте переписувати — розумійте базові принципи, які роблять програми швидкими або повільними.