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

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

03.02.2024

JIT, чому Ruby повільний, та як він може стати швидшим

Читав нещодавно статтю про те, як реалізацію парсера на Ruby зробили швидше за С. Хотілося прокоментувати, що це в принципі значить. (Все це також стосується майже будь-якої динамічно типізованої мови, будь то JavaScript, Python, і так далі.)

Робота будь-якої програми більш-менш зводиться до операцій над памʼяттю. Саме тут й криється головна різниця між статичними та динамічними мовами: якщо статична мова, як С, під час компіляції знає форму даних в памʼяті, то динамічна, як Ruby, нічого про неї не знає.

Наприклад, в С структурований тип має зафіксований перелік атрибутів. А в Ruby ми можемо додати чи видалити атрибут в будь-який момент. Так само можемо взагалі передавати обʼєкти різних класів у функцію та користуватись duck typing.

А значить, при кожному зверненні до змінної чи атрибута Ruby мусить спочатку знайти його в памʼяті. Це і є повільний етап. (А не інтерпретація коду, бо код давно ніхто не інтерпретує, а компілює наперед в інструкції віртуальної машини.)

Втім, в реальних програмах структури даних не змінюються часто. Тож нормальний код на Ruby теж можна було б привʼязати до фіксованої форми даних та компілювати так само як і C. Саме це й робить JIT - виявляє фрагменти коду, що працюють зі стабільними структурами даних, та компілює їх.

Однак JIT пришвидшує тільки ті програми, де структури даних сталі, що залежить від стилю коду. Якщо динамічно утворювати нові атрибути в різних місцях логіки, то структура класу не буде сталою, а значить, JIT залучений не буде. Більше можна почитати в статті зверху.