Производительность исполнения
Для оценки эффективности разработанного компилятора были проведены замеры времени исполнения набора тестовых программ. Сравнение проводилось с использованием следующих инструментов:
разработанный в рамках проекта компилятор;
интерпретатор CPython языка программирования Python (версия Python 3.10.12);
JIT (just-in-time) компилятор языка программирования Python, представленный в пакете Numba (версия 0.61.2);
компилятор Clang (версия 17.0.6) с уровнем оптимизации O0 (без оптимизаций).
Тестовые программы включали в себя алгоритмы:
пузырьковая сортировка (bubble sort) массива чисел типа float (с плавающей запятой) из 1000 элементов;
нахождение числа Фибоначчи под номером 32;
умножение целочисленных матриц, представленных в виде одномерного массива (по строкам) размера 100х100 элементов.
Тестирование производилось на системе со следующими характеристиками:
процессор: Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz;
ОС Ubuntu 22.04.4 LTS;
оперативная память 8 Гб.
Каждый тест запускался 1000 раз, после чего производилось усреднение полученных временных результатов. Для замеров использовались инструменты: разработанный компилятор для получения объектного файла программы для статически типизированного подмножества языка Python, выбранного в качестве целевого языка для проекта, а также библиотека ctypes оригинального Python для измерения времени целевой функции из сгенерированного ранее объектного файла; инструмент perf_counter модуля time языка Python, фиксирующий время в определенной точке программы; библиотека chrono языка C++.
В таблице представлены полученные результаты (время в мс).
Пример |
Compiler |
Python (интерпретация) |
Numba (JIT) |
Clang (-O0) |
|---|---|---|---|---|
Пузырьковая сортировка |
1,46323 |
27,455859 |
1,59733 |
0,614 |
F32 |
15,6045 |
48,7577675 |
15,2445 |
13,926 |
Умножение матриц |
1,98357 |
120,958673 |
25,2622 |
2,177 |
Реализация пузырьковой сортировки содержит частые операции записи в память, частые условные переходы, в связи с этим создает накладные расходы для интерпретации (проверка типов), а также медленное исполнение кода по строкам. Clang же в свою очередь даже на минимальном уровне оптимизаций содержит базовые преобразования (выравнивание, эффективное распределение регистров, оптимальные условные переходы), чем объясняется его преимущество в 2 раза.
Нахождение 32 числа Фибоначчи демонстрирует, как инструмент работает с глубокой рекурсией, а также базовые различия интерпретации и компиляции. Результаты в таблице показывают, что даже без оптимизаций хвостовой рекурсии базовые времена в случае AOT и JIT компиляции в 3 раза быстрее интерпретации, а также совпадение результатов реализованного компилятора и промышленных.
Алгоритм умножения матриц интенсивно использует арифметические операции, а также содержит частые последовательные доступы к элементам массивов. Даже без сложных оптимизаций, например, векторизации и продвинутого кэширования, компилятор выигрывает у JIT компиляции и тем более интерпретации за счет быстрого доступа к данным и выполнении элементарных математических итераций процессорными инструкциями.