Сравним C++, JS, Python, Python + numba, PHP7, PHP8, и Golang на примере расчёта “Простое Число”

от автора

Все топовые языки программирования уже давно доказали свои позиции и «определились» с нишами своего использования.

Тем не менее, для каждого программиста важно иметь представление о количественных характеристиках для каждого из языков, которыми он пользуется.

Измерять можно довольно много параметров и для разных целей.

Для каких-то задач важнее будет наличие быстрого просчёта по математическим операциям. А для других — больше пригодится ускоренная работа с сетью и файлами.

В данной статье мы рассмотрим ускорение программы с использованием JIT-компиляции для языков Python и PHP.

В качестве задачи для расчёта возьмём функцию проверки — является ли число Простыми или нет — «is prime». Возьмём базовый алгоритм проверки на то, что число Простое:

  • число не чётное

  • и не делится на меньшее число до корень из искомого (то есть в цикле пройдёмся от 3 до корень из числа)

Нам будет необходимо вычислить ряд Простых чисел — до максимального. Максимальное число в этой задаче будет: 10 000 000.

В алгоритме и в коде ниже можно видеть, что я не применял распараллеливание, для более «честной» оценки времени исполнения.

Машина, на которой производились запуски:

Название модели:                     MacBook Pro Идентификатор модели:                MacBookPro14,1 Имя процессора:                     Dual-Core Intel Core i5 Скорость процессора:                 2,3 GHz Количество процессоров:              1 Общее количество ядер:              2 Кэш 2-го уровня (в каждом ядре):    256 КБ Кэш 3-го уровня:                  4 МБ Технология Hyper-Threading:       Включен Память:                          8 ГБ Версия Boot ROM:                 428.0.0.0.0 Версия SMC (система):              2.43f10

Рассмотрим варианты алгоритма на разных языках программирования:

C++

g++ --version Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1 Apple clang version 11.0.3 (clang-1103.0.32.62) Target: x86_64-apple-darwin19.6.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin
#include <iostream> #include <cmath> #include <time.h>  using namespace std;  bool isPrime(int num) {     if (num == 2) {         return true;     }     if (num <= 1 || num % 2 == 0) {         return false;     }      double sqrt_num = sqrt(double(num));     for (int div = 3; div <= sqrt_num; div +=2)     {         if (num % div == 0) {             return false;         }     }     return true; }   int main() {     int N = 10000000;     clock_t start, end;     start = clock();     for (int i ; i < N; i++) {         isPrime(i);     }     end = clock();     cout << (end - start) / ((double) CLOCKS_PER_SEC);     cout << " sec \n";     return 0; }

Node.js

node --version   v15.0.1
function isPrime(num) {     if (num === 2) {         return true;     }     if (num <= 1 || num % 2 === 0) {         return false     }     for (let div = 3; div <= Math.sqrt(num); div += 2) {         if (num % div === 0) {             return false;         }     }     return true; }  function main(N) {     const st = new Date().getTime();     for (let i = 0; i < N; i++) {         let prime = isPrime(i);         if (prime) {             // console.log(i + ': ' + prime);         }     }     console.log((new Date().getTime() - st) / 1000); }  (function (){     const N = 10_000_000;     main(N) })()

PHP

<?php  function isPrime($num) {     if ($num == 2) {         return true;     }     if ($num == 1 || $num %2 == 0) {         return false;     }     $to = sqrt($num) + 1;     for ($i = 3; $i <= $to; $i += 2) {         if ($num % $i == 0) {             return false;         }     }     return true; }  function run($N) {     for ($i = 0; $i <= $N; $i++) {         isPrime($i);     } }  function main() {     $st = microtime(true);     run(10000000);      echo microtime(true) - $st; }  // Да, код не продакшен-реди)) Прошу не шеймить за топорность кода. main();

Python (without «numba»)

python3 --version Python 3.8.5
import math from time import perf_counter   def is_prime(num):     if num == 2:         return True     if num == 1 or not num % 2:         return False     for div in range(3, int(math.sqrt(num)) + 1, 2):         if not num % div:             return False     return True   def do(n):     for i in range(n):         is_prime(i)   if __name__ == '__main__':     N = 10_000_000     st = perf_counter()     do(N)     end = perf_counter()     print(end - st)

Python with «numba»

import math from time import perf_counter  from numba import njit   @njit(fastmath=True) def is_prime(num):     if num == 2:         return True     if num == 1 or not num % 2:         return False     for div in range(3, int(math.sqrt(num)) + 1, 2):         if not num % div:             return False     return True   @njit(fastmath=True) def do(n):     for i in range(n):         is_prime(i)   if __name__ == '__main__':     N = 10_000_000     st = perf_counter()     do(N)     end = perf_counter()     print(end - st)

После запуска на локальной машине можно сравнить время исполнения всех вышеперечисленных программ:

Примечание: меньше - лучше.
Примечание: меньше — лучше.

Здесь можно видеть, что версия на JS довольно «быстрая».

А также:

  • python3 + numba показала огромный прирост в производительности! Обогнав даже Go. Круто!

  • PHP8 с включенным JIT показала себя хорошо. И сравнимо с Go!

Вероятно, что-то ушло из моего поля зрения и в данной задаче я не учёл какой-то момент и js в базовом исполнении оказался быстрее Go.

А Вы, что думаете по этому поводу? Что здесь можно добавить или изменить для полноты эксперимента?

Интересно ли Вам посмотреть показатели производительности по работе с текстом, картинками и сетью?

ссылка на оригинал статьи https://habr.com/ru/post/532432/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *