Merge pull request #1 from famzah/master

rebase
master
Krzysztof 2016-10-12 00:13:01 +02:00 committed by GitHub
commit e4e121e008
19 changed files with 820 additions and 40 deletions

View File

@ -1,10 +1,11 @@
# langs-performance
C++ vs. Python vs. Perl vs. PHP vs. Java vs. NodeJS vs. Go performance benchmark
C++ vs. Python vs. Perl vs. PHP vs. Java vs. NodeJS vs. Go vs. Ruby performance benchmark
Blog articles:
* 2016: http://blog.famzah.net/2016/02/09/cpp-vs-python-vs-perl-vs-php-performance-benchmark-2016/
* 2010-2012: http://blog.famzah.net/2010/07/01/cpp-vs-python-vs-perl-vs-php-performance-benchmark/
* 2016: https://blog.famzah.net/2016/09/10/cpp-vs-python-vs-php-vs-java-vs-others-performance-benchmark-2016-q3/
* 2016: https://blog.famzah.net/2016/02/09/cpp-vs-python-vs-perl-vs-php-performance-benchmark-2016/
* 2010-2012: https://blog.famzah.net/2010/07/01/cpp-vs-python-vs-perl-vs-php-performance-benchmark/
The benchmarks here do not try to be complete, as they are showing the performance of the languages in one aspect, and mainly: loops, dynamic arrays with numbers, basic math operations.
The times include the interpretation/parsing phase for each language, but its so small that its significance is negligible. The math function is called 10 times, in order to have more reliable results. All scripts are using the very same algorithm to calculate the prime numbers in a given range. The correctness of the implementation is not so important, as we just want to check how fast the languages perform. The original Python algorithm was taken from http://www.daniweb.com/code/snippet216871.html.
The times include the interpretation/parsing phase for each language, but its so small that its significance is negligible. The programs run for 90 wall-clock seconds and there are 6 identical runs, in order to have more reliable results. All scripts are using the very same algorithm to calculate the prime numbers in a given range. The correctness of the implementation is not so important, as we just want to check how fast the languages perform. The original Python algorithm was taken from http://www.daniweb.com/code/snippet216871.html.

View File

@ -0,0 +1,30 @@
--- ../primes.java 2016-09-22 22:10:58.787516331 +0300
+++ primes.java 2016-09-22 22:11:14.919516331 +0300
@@ -2,15 +2,15 @@
import java.lang.Math;
class PrimeNumbersGenerator {
- ArrayList<Integer> get_primes7(int n) {
- ArrayList<Integer> res = new ArrayList<Integer>();
+ List<Integer> get_primes7(int n) {
+ List<Integer> res = new LinkedList<Integer>();
if (n < 2) return res;
if (n == 2) {
res.add(2);
return res;
}
- ArrayList<Integer> s = new ArrayList<Integer>();
+ List<Integer> s = new ArrayList<Integer>();
for (int i = 3; i < n + 1; i += 2) {
s.add(i);
}
@@ -46,7 +46,7 @@
long startTime = System.currentTimeMillis();
long periodTime = Long.parseLong(System.getenv("RUN_TIME"), 10) * 1000;
- ArrayList<Integer> res;
+ List<Integer> res;
while ((System.currentTimeMillis() - startTime) < periodTime) {
res = (new PrimeNumbersGenerator()).get_primes7(10000000);

View File

@ -0,0 +1,9 @@
# Performance notes
Java can be (a lot) faster than what we see it with its default interpeter settings:
* Initial heap size -- setting this larger than the default value will allow the ArrayList to grow more efficiently by pre-allocating a bigger memory block from the system. The "java" command-line argument is "-Xms500m".
* Heap and GC tuning -- we can control the ratio between the old and young generations. The "java" command-line argument is "-XX:NewRatio=1".
* Skip the unneeded boxing/unboxing -- this requires a more native Java implementation. See the source code of "[primes-alt.java](../primes-alt.java)".
* Use LinkedList -- it has O(1) complexity for adding elements. Benchmark tests however don't show significant improvement under Java 8, and under Java 7 we see a slow down of 59%.
These tweaks are not included in the Java benchmark test, because I wanted to test the default languages setup. I don't aim to fine-tune any of the implementations by optimizing them for the current task/algorithm. This is a generic test, not an attempt to complete the current task in the fastest possible way for each programming language.

View File

@ -85,8 +85,12 @@ class IntList {
class PrimeNumbersBenchmarkApp {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long periodTime = Long.parseLong(System.getenv("RUN_TIME"), 10) * 1000;
IntList res;
for (int i = 1; i <= 10; ++i) {
while ((System.currentTimeMillis() - startTime) < periodTime) {
res = (new PrimeNumbersGenerator()).get_primes7(10000000);
System.out.format("Found %d prime numbers.\n", res.size());
}

View File

@ -2,6 +2,8 @@
#include <cmath>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
using namespace std;
@ -59,7 +61,10 @@ void get_primes7(int n, vector<int> &res) {
}
int main() {
for (int i = 1; i <= 10; ++i) {
std::time_t startTime = std::time(NULL);
std::time_t periodTime = (std::time_t) atoi(std::getenv("RUN_TIME"));
while ((std::time(NULL) - startTime) < periodTime) {
vector<int> res;
get_primes7(10000000, res);
printf("Found %d prime numbers.\n", (int)res.size());

View File

@ -3,6 +3,9 @@ package main
import (
"fmt"
"math"
"time"
"os"
"strconv"
)
func getPrimes7(n int) []int {
@ -47,8 +50,12 @@ func getPrimes7(n int) []int {
}
func main() {
var startTime = int32(time.Now().Unix())
var periodTime, _ = strconv.ParseInt(os.Getenv("RUN_TIME"), 10, 32)
var res []int
for i := 0; i < 10; i++ {
for (int32(time.Now().Unix()) - startTime) < int32(periodTime) {
res = getPrimes7(10000000)
fmt.Printf("Found %d prime numbers.\n", len(res))
}

View File

@ -43,8 +43,12 @@ class PrimeNumbersGenerator {
class PrimeNumbersBenchmarkApp {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long periodTime = Long.parseLong(System.getenv("RUN_TIME"), 10) * 1000;
ArrayList<Integer> res;
for (int i = 1; i <= 10; ++i) {
while ((System.currentTimeMillis() - startTime) < periodTime) {
res = (new PrimeNumbersGenerator()).get_primes7(10000000);
System.out.format("Found %d prime numbers.\n", res.size());
}

View File

@ -34,7 +34,10 @@ function get_primes7(n) {
return res;
}
for (var i = 0; i < 10; i++) {
var startTime = Date.now();
var periodTime = parseInt(process.env.RUN_TIME, 10) * 1000
while ((Date.now() - startTime) < periodTime) {
var res = get_primes7(10000000);
console.log("Found " + res.length + " prime numbers.");
}

View File

@ -31,8 +31,12 @@ function get_primes7($n) {
return $res;
}
$startTime = time();
$periodTime = getenv('RUN_TIME');
$res = array();
for ($i = 1; $i <= 10; ++$i) {
while ((time() - $startTime) < $periodTime) {
$res = get_primes7(10000000);
print "Found ".count($res)." prime numbers.\n";
}

View File

@ -35,8 +35,12 @@ sub get_primes7($) {
return @res;
}
my $startTime = time();
my $periodTime = $ENV{'RUN_TIME'};
my @res;
for (1..10) {
while ((time() - $startTime) < $periodTime) {
@res = get_primes7(10000000);
print "Found ".(scalar @res)." prime numbers.\n";
}

View File

@ -1,4 +1,6 @@
import sys
import time
import os
def get_primes7(n):
"""
@ -28,6 +30,9 @@ def get_primes7(n):
m = 2*i+3
return [2]+[x for x in s if x]
for t in range(10):
startTime = int(time.time())
periodTime = int(os.environ['RUN_TIME'])
while (int(time.time()) - startTime) < periodTime:
res = get_primes7(10000000)
print("Found {} prime numbers.".format(len(res)))

35
primes.rb Normal file
View File

@ -0,0 +1,35 @@
require 'time'
def get_primes7(n)
return [] if n < 2
return [2] if n == 2
# do only odd numbers starting at 3
s = 3.upto(n + 1).select(&:odd?)
mroot = n ** 0.5
half = s.length
i = 0
m = 3
until m > mroot do
if s[i]
j = (m * m - 3) / 2
s[j] = nil
until j >= half do
s[j] = nil
j += m
end
end
i += 1
m = 2 * i + 3
end
[2] + s.compact
end
startTime = Time.now.to_i
periodTime = ENV['RUN_TIME'].to_i
while (Time.now.to_i - startTime) < periodTime do
res = get_primes7(10000000)
puts "Found #{res.length} prime numbers."
end

174
results/2016-09-09.out Normal file
View File

@ -0,0 +1,174 @@
# Run time limited to 90 wall-clock seconds
#
# C++ (optimized with -O2)
# ... compilation
# ... run 1
real_TIME:89.49sec user_CPU:84.25sec sys_CPU:5.22sec max_RSS:55152kb swaps:0 ctx_sw:452+1 nlines:906 run_try:1 header:'C++ (optimized with -O2)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# ... run 2
real_TIME:90.06sec user_CPU:84.77sec sys_CPU:5.27sec max_RSS:55152kb swaps:0 ctx_sw:309+1 nlines:928 run_try:2 header:'C++ (optimized with -O2)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# ... run 3
real_TIME:89.97sec user_CPU:84.56sec sys_CPU:5.39sec max_RSS:55208kb swaps:0 ctx_sw:293+1 nlines:930 run_try:3 header:'C++ (optimized with -O2)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# ... run 4
real_TIME:89.98sec user_CPU:84.52sec sys_CPU:5.44sec max_RSS:55320kb swaps:0 ctx_sw:294+1 nlines:916 run_try:4 header:'C++ (optimized with -O2)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# ... run 5
real_TIME:89.98sec user_CPU:84.53sec sys_CPU:5.42sec max_RSS:55256kb swaps:0 ctx_sw:395+1 nlines:930 run_try:5 header:'C++ (optimized with -O2)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# ... run 6
real_TIME:89.92sec user_CPU:84.41sec sys_CPU:5.49sec max_RSS:55236kb swaps:0 ctx_sw:299+1 nlines:931 run_try:6 header:'C++ (optimized with -O2)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# C++ (not optimized)
# ... compilation
# ... run 1
real_TIME:89.61sec user_CPU:87.72sec sys_CPU:1.86sec max_RSS:55220kb swaps:0 ctx_sw:311+1 nlines:301 run_try:1 header:'C++ (not optimized)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# ... run 2
real_TIME:90.04sec user_CPU:88.28sec sys_CPU:1.74sec max_RSS:55164kb swaps:0 ctx_sw:291+1 nlines:306 run_try:2 header:'C++ (not optimized)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# ... run 3
real_TIME:90.00sec user_CPU:88.12sec sys_CPU:1.87sec max_RSS:55144kb swaps:0 ctx_sw:296+1 nlines:305 run_try:3 header:'C++ (not optimized)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# ... run 4
real_TIME:90.12sec user_CPU:88.40sec sys_CPU:1.70sec max_RSS:55224kb swaps:0 ctx_sw:381+1 nlines:306 run_try:4 header:'C++ (not optimized)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# ... run 5
real_TIME:90.02sec user_CPU:88.38sec sys_CPU:1.62sec max_RSS:55184kb swaps:0 ctx_sw:356+1 nlines:303 run_try:5 header:'C++ (not optimized)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# ... run 6
real_TIME:89.98sec user_CPU:88.24sec sys_CPU:1.72sec max_RSS:55140kb swaps:0 ctx_sw:347+1 nlines:306 run_try:6 header:'C++ (not optimized)' version:'g++ (Debian 6.1.1-11) 6.1.1 20160802 ' src_file:primes.cpp
# Go
# ... compilation
# ... run 1
real_TIME:89.54sec user_CPU:127.43sec sys_CPU:5.46sec max_RSS:183544kb swaps:0 ctx_sw:28400+61963 nlines:482 run_try:1 header:'Go' version:'go version go1.7 linux/amd64 ' src_file:primes.go
# ... run 2
real_TIME:89.99sec user_CPU:121.48sec sys_CPU:5.20sec max_RSS:183800kb swaps:0 ctx_sw:29063+59750 nlines:461 run_try:2 header:'Go' version:'go version go1.7 linux/amd64 ' src_file:primes.go
# ... run 3
real_TIME:90.10sec user_CPU:131.69sec sys_CPU:5.14sec max_RSS:153168kb swaps:0 ctx_sw:29771+64656 nlines:502 run_try:3 header:'Go' version:'go version go1.7 linux/amd64 ' src_file:primes.go
# ... run 4
real_TIME:89.96sec user_CPU:124.80sec sys_CPU:5.18sec max_RSS:175864kb swaps:0 ctx_sw:30136+62021 nlines:468 run_try:4 header:'Go' version:'go version go1.7 linux/amd64 ' src_file:primes.go
# ... run 5
real_TIME:89.97sec user_CPU:125.88sec sys_CPU:5.28sec max_RSS:165752kb swaps:0 ctx_sw:30655+62437 nlines:471 run_try:5 header:'Go' version:'go version go1.7 linux/amd64 ' src_file:primes.go
# ... run 6
real_TIME:89.99sec user_CPU:131.58sec sys_CPU:5.49sec max_RSS:183176kb swaps:0 ctx_sw:30187+64365 nlines:499 run_try:6 header:'Go' version:'go version go1.7 linux/amd64 ' src_file:primes.go
# Python 2.7 + PyPy
# ... compilation
# ... run 1
real_TIME:89.82sec user_CPU:82.17sec sys_CPU:7.49sec max_RSS:112260kb swaps:0 ctx_sw:291+204 nlines:590 run_try:1 header:'Python 2.7 + PyPy' version:'Python 2.7.10 (5.4.0+dfsg-2, Sep 01 2016, 05:04:17) [PyPy 5.4.0 with GCC 6.2.0 20160822] ' src_file:primes.py
# ... run 2
real_TIME:90.05sec user_CPU:82.30sec sys_CPU:7.74sec max_RSS:112392kb swaps:0 ctx_sw:181+1 nlines:593 run_try:2 header:'Python 2.7 + PyPy' version:'Python 2.7.10 (5.4.0+dfsg-2, Sep 01 2016, 05:04:17) [PyPy 5.4.0 with GCC 6.2.0 20160822] ' src_file:primes.py
# ... run 3
real_TIME:89.95sec user_CPU:82.19sec sys_CPU:7.75sec max_RSS:112360kb swaps:0 ctx_sw:273+1 nlines:597 run_try:3 header:'Python 2.7 + PyPy' version:'Python 2.7.10 (5.4.0+dfsg-2, Sep 01 2016, 05:04:17) [PyPy 5.4.0 with GCC 6.2.0 20160822] ' src_file:primes.py
# ... run 4
real_TIME:89.98sec user_CPU:82.40sec sys_CPU:7.55sec max_RSS:112436kb swaps:0 ctx_sw:398+1 nlines:595 run_try:4 header:'Python 2.7 + PyPy' version:'Python 2.7.10 (5.4.0+dfsg-2, Sep 01 2016, 05:04:17) [PyPy 5.4.0 with GCC 6.2.0 20160822] ' src_file:primes.py
# ... run 5
real_TIME:90.01sec user_CPU:82.48sec sys_CPU:7.52sec max_RSS:112520kb swaps:0 ctx_sw:278+1 nlines:596 run_try:5 header:'Python 2.7 + PyPy' version:'Python 2.7.10 (5.4.0+dfsg-2, Sep 01 2016, 05:04:17) [PyPy 5.4.0 with GCC 6.2.0 20160822] ' src_file:primes.py
# ... run 6
real_TIME:89.98sec user_CPU:82.44sec sys_CPU:7.53sec max_RSS:112412kb swaps:0 ctx_sw:175+1 nlines:593 run_try:6 header:'Python 2.7 + PyPy' version:'Python 2.7.10 (5.4.0+dfsg-2, Sep 01 2016, 05:04:17) [PyPy 5.4.0 with GCC 6.2.0 20160822] ' src_file:primes.py
# Python 2.7
# ... compilation
# ... run 1
real_TIME:91.31sec user_CPU:90.75sec sys_CPU:0.50sec max_RSS:197252kb swaps:0 ctx_sw:401+58 nlines:38 run_try:1 header:'Python 2.7' version:'Python 2.7.12+ ' src_file:primes.py
# ... run 2
real_TIME:89.84sec user_CPU:89.36sec sys_CPU:0.48sec max_RSS:197304kb swaps:0 ctx_sw:316+1 nlines:38 run_try:2 header:'Python 2.7' version:'Python 2.7.12+ ' src_file:primes.py
# ... run 3
real_TIME:91.61sec user_CPU:91.10sec sys_CPU:0.49sec max_RSS:197200kb swaps:0 ctx_sw:398+1 nlines:39 run_try:3 header:'Python 2.7' version:'Python 2.7.12+ ' src_file:primes.py
# ... run 4
real_TIME:89.59sec user_CPU:89.09sec sys_CPU:0.49sec max_RSS:197308kb swaps:0 ctx_sw:315+1 nlines:38 run_try:4 header:'Python 2.7' version:'Python 2.7.12+ ' src_file:primes.py
# ... run 5
real_TIME:90.18sec user_CPU:89.70sec sys_CPU:0.46sec max_RSS:197132kb swaps:0 ctx_sw:396+1 nlines:38 run_try:5 header:'Python 2.7' version:'Python 2.7.12+ ' src_file:primes.py
# ... run 6
real_TIME:90.10sec user_CPU:89.62sec sys_CPU:0.46sec max_RSS:197308kb swaps:0 ctx_sw:234+1 nlines:38 run_try:6 header:'Python 2.7' version:'Python 2.7.12+ ' src_file:primes.py
# Python 3.5
# ... compilation
# ... run 1
real_TIME:90.13sec user_CPU:89.38sec sys_CPU:0.68sec max_RSS:242756kb swaps:0 ctx_sw:382+71 nlines:50 run_try:1 header:'Python 3.5' version:'Python 3.5.2+ ' src_file:primes.py
# ... run 2
real_TIME:90.25sec user_CPU:89.50sec sys_CPU:0.73sec max_RSS:242800kb swaps:0 ctx_sw:381+1 nlines:50 run_try:2 header:'Python 3.5' version:'Python 3.5.2+ ' src_file:primes.py
# ... run 3
real_TIME:91.27sec user_CPU:90.52sec sys_CPU:0.73sec max_RSS:242872kb swaps:0 ctx_sw:384+1 nlines:51 run_try:3 header:'Python 3.5' version:'Python 3.5.2+ ' src_file:primes.py
# ... run 4
real_TIME:90.14sec user_CPU:89.46sec sys_CPU:0.67sec max_RSS:242756kb swaps:0 ctx_sw:296+1 nlines:51 run_try:4 header:'Python 3.5' version:'Python 3.5.2+ ' src_file:primes.py
# ... run 5
real_TIME:89.80sec user_CPU:89.03sec sys_CPU:0.75sec max_RSS:242804kb swaps:0 ctx_sw:442+1 nlines:50 run_try:5 header:'Python 3.5' version:'Python 3.5.2+ ' src_file:primes.py
# ... run 6
real_TIME:90.76sec user_CPU:90.00sec sys_CPU:0.75sec max_RSS:242752kb swaps:0 ctx_sw:307+1 nlines:51 run_try:6 header:'Python 3.5' version:'Python 3.5.2+ ' src_file:primes.py
# Perl
# ... compilation
# ... run 1
real_TIME:92.90sec user_CPU:92.81sec sys_CPU:0.07sec max_RSS:242588kb swaps:0 ctx_sw:215+19 nlines:36 run_try:1 header:'Perl' version:'This is perl 5, version 22, subversion 2 (v5.22.2) built for x86_64-linux-gnu-thread-multi ' src_file:primes.pl
# ... run 2
real_TIME:91.49sec user_CPU:91.42sec sys_CPU:0.05sec max_RSS:242772kb swaps:0 ctx_sw:450+1 nlines:36 run_try:2 header:'Perl' version:'This is perl 5, version 22, subversion 2 (v5.22.2) built for x86_64-linux-gnu-thread-multi ' src_file:primes.pl
# ... run 3
real_TIME:91.76sec user_CPU:91.67sec sys_CPU:0.07sec max_RSS:242728kb swaps:0 ctx_sw:396+1 nlines:36 run_try:3 header:'Perl' version:'This is perl 5, version 22, subversion 2 (v5.22.2) built for x86_64-linux-gnu-thread-multi ' src_file:primes.pl
# ... run 4
real_TIME:91.30sec user_CPU:91.23sec sys_CPU:0.06sec max_RSS:242708kb swaps:0 ctx_sw:254+1 nlines:36 run_try:4 header:'Perl' version:'This is perl 5, version 22, subversion 2 (v5.22.2) built for x86_64-linux-gnu-thread-multi ' src_file:primes.pl
# ... run 5
real_TIME:90.03sec user_CPU:89.93sec sys_CPU:0.08sec max_RSS:242644kb swaps:0 ctx_sw:440+1 nlines:35 run_try:5 header:'Perl' version:'This is perl 5, version 22, subversion 2 (v5.22.2) built for x86_64-linux-gnu-thread-multi ' src_file:primes.pl
# ... run 6
real_TIME:89.62sec user_CPU:89.54sec sys_CPU:0.07sec max_RSS:242768kb swaps:0 ctx_sw:313+1 nlines:35 run_try:6 header:'Perl' version:'This is perl 5, version 22, subversion 2 (v5.22.2) built for x86_64-linux-gnu-thread-multi ' src_file:primes.pl
# PHP 7.0
# ... compilation
# ... run 1
real_TIME:89.91sec user_CPU:87.59sec sys_CPU:2.31sec max_RSS:231316kb swaps:0 ctx_sw:315+1 nlines:133 run_try:1 header:'PHP 7.0' version:'PHP 7.0.10-1 (cli) ( NTS ) ' src_file:primes.php
# ... run 2
real_TIME:90.01sec user_CPU:87.65sec sys_CPU:2.35sec max_RSS:231356kb swaps:0 ctx_sw:181+1 nlines:131 run_try:2 header:'PHP 7.0' version:'PHP 7.0.10-1 (cli) ( NTS ) ' src_file:primes.php
# ... run 3
real_TIME:89.63sec user_CPU:87.33sec sys_CPU:2.29sec max_RSS:231388kb swaps:0 ctx_sw:392+1 nlines:135 run_try:3 header:'PHP 7.0' version:'PHP 7.0.10-1 (cli) ( NTS ) ' src_file:primes.php
# ... run 4
real_TIME:90.45sec user_CPU:88.18sec sys_CPU:2.26sec max_RSS:231452kb swaps:0 ctx_sw:312+1 nlines:133 run_try:4 header:'PHP 7.0' version:'PHP 7.0.10-1 (cli) ( NTS ) ' src_file:primes.php
# ... run 5
real_TIME:89.52sec user_CPU:87.27sec sys_CPU:2.23sec max_RSS:231420kb swaps:0 ctx_sw:593+1 nlines:134 run_try:5 header:'PHP 7.0' version:'PHP 7.0.10-1 (cli) ( NTS ) ' src_file:primes.php
# ... run 6
real_TIME:90.31sec user_CPU:88.04sec sys_CPU:2.26sec max_RSS:231408kb swaps:0 ctx_sw:405+1 nlines:135 run_try:6 header:'PHP 7.0' version:'PHP 7.0.10-1 (cli) ( NTS ) ' src_file:primes.php
# Java 8
# ... compilation
# ... run 1
real_TIME:90.70sec user_CPU:127.76sec sys_CPU:0.81sec max_RSS:513456kb swaps:0 ctx_sw:3677+5342 nlines:104 run_try:1 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 2
real_TIME:90.58sec user_CPU:125.52sec sys_CPU:0.80sec max_RSS:513316kb swaps:0 ctx_sw:3982+5777 nlines:103 run_try:2 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 3
real_TIME:90.37sec user_CPU:126.02sec sys_CPU:0.89sec max_RSS:513360kb swaps:0 ctx_sw:3672+5783 nlines:104 run_try:3 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 4
real_TIME:91.03sec user_CPU:126.13sec sys_CPU:0.80sec max_RSS:513420kb swaps:0 ctx_sw:3857+5563 nlines:105 run_try:4 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 5
real_TIME:90.96sec user_CPU:127.15sec sys_CPU:0.82sec max_RSS:513200kb swaps:0 ctx_sw:3831+5593 nlines:105 run_try:5 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 6
real_TIME:90.32sec user_CPU:125.06sec sys_CPU:0.74sec max_RSS:513456kb swaps:0 ctx_sw:4150+5378 nlines:104 run_try:6 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# Java 8 (non-std lib)
# ... compilation
# ... run 1
real_TIME:90.11sec user_CPU:89.87sec sys_CPU:0.46sec max_RSS:459716kb swaps:0 ctx_sw:4530+5951 nlines:799 run_try:1 header:'Java 8 (non-std lib)' version:'javac 1.8.0_102 ' src_file:primes-alt.java
# ... run 2
real_TIME:90.11sec user_CPU:89.81sec sys_CPU:0.50sec max_RSS:460756kb swaps:0 ctx_sw:4579+5996 nlines:803 run_try:2 header:'Java 8 (non-std lib)' version:'javac 1.8.0_102 ' src_file:primes-alt.java
# ... run 3
real_TIME:90.15sec user_CPU:90.00sec sys_CPU:0.44sec max_RSS:445756kb swaps:0 ctx_sw:4507+6045 nlines:806 run_try:3 header:'Java 8 (non-std lib)' version:'javac 1.8.0_102 ' src_file:primes-alt.java
# ... run 4
real_TIME:90.11sec user_CPU:89.81sec sys_CPU:0.49sec max_RSS:462368kb swaps:0 ctx_sw:4717+6164 nlines:800 run_try:4 header:'Java 8 (non-std lib)' version:'javac 1.8.0_102 ' src_file:primes-alt.java
# ... run 5
real_TIME:90.16sec user_CPU:89.84sec sys_CPU:0.58sec max_RSS:476500kb swaps:0 ctx_sw:4490+5908 nlines:807 run_try:5 header:'Java 8 (non-std lib)' version:'javac 1.8.0_102 ' src_file:primes-alt.java
# ... run 6
real_TIME:90.17sec user_CPU:90.05sec sys_CPU:0.48sec max_RSS:445548kb swaps:0 ctx_sw:4923+5958 nlines:801 run_try:6 header:'Java 8 (non-std lib)' version:'javac 1.8.0_102 ' src_file:primes-alt.java
# JavaScript (nodejs)
# ... compilation
# ... run 1
real_TIME:90.58sec user_CPU:83.88sec sys_CPU:6.64sec max_RSS:477928kb swaps:0 ctx_sw:240+138 nlines:125 run_try:1 header:'JavaScript (nodejs)' version:'v4.3.1 ' src_file:primes.js
# ... run 2
real_TIME:90.86sec user_CPU:84.32sec sys_CPU:6.55sec max_RSS:477816kb swaps:0 ctx_sw:281+73 nlines:126 run_try:2 header:'JavaScript (nodejs)' version:'v4.3.1 ' src_file:primes.js
# ... run 3
real_TIME:90.33sec user_CPU:83.54sec sys_CPU:6.78sec max_RSS:477896kb swaps:0 ctx_sw:593+72 nlines:125 run_try:3 header:'JavaScript (nodejs)' version:'v4.3.1 ' src_file:primes.js
# ... run 4
real_TIME:90.39sec user_CPU:84.04sec sys_CPU:6.36sec max_RSS:477852kb swaps:0 ctx_sw:315+90 nlines:126 run_try:4 header:'JavaScript (nodejs)' version:'v4.3.1 ' src_file:primes.js
# ... run 5
real_TIME:90.43sec user_CPU:83.94sec sys_CPU:6.50sec max_RSS:477888kb swaps:0 ctx_sw:307+73 nlines:126 run_try:5 header:'JavaScript (nodejs)' version:'v4.3.1 ' src_file:primes.js
# ... run 6
real_TIME:90.45sec user_CPU:83.92sec sys_CPU:6.52sec max_RSS:477856kb swaps:0 ctx_sw:460+73 nlines:126 run_try:6 header:'JavaScript (nodejs)' version:'v4.3.1 ' src_file:primes.js
# Ruby
# ... compilation
# ... run 1
real_TIME:89.92sec user_CPU:88.24sec sys_CPU:1.61sec max_RSS:228420kb swaps:0 ctx_sw:457+77 nlines:69 run_try:1 header:'Ruby' version:'ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu] ' src_file:primes.rb
# ... run 2
real_TIME:90.80sec user_CPU:89.13sec sys_CPU:1.65sec max_RSS:228352kb swaps:0 ctx_sw:395+3 nlines:68 run_try:2 header:'Ruby' version:'ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu] ' src_file:primes.rb
# ... run 3
real_TIME:90.27sec user_CPU:88.66sec sys_CPU:1.60sec max_RSS:228500kb swaps:0 ctx_sw:196+3 nlines:70 run_try:3 header:'Ruby' version:'ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu] ' src_file:primes.rb
# ... run 4
real_TIME:90.05sec user_CPU:88.52sec sys_CPU:1.51sec max_RSS:228460kb swaps:0 ctx_sw:449+3 nlines:68 run_try:4 header:'Ruby' version:'ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu] ' src_file:primes.rb
# ... run 5
real_TIME:90.03sec user_CPU:88.41sec sys_CPU:1.61sec max_RSS:228500kb swaps:0 ctx_sw:271+3 nlines:67 run_try:5 header:'Ruby' version:'ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu] ' src_file:primes.rb
# ... run 6
real_TIME:89.32sec user_CPU:87.62sec sys_CPU:1.68sec max_RSS:228508kb swaps:0 ctx_sw:461+3 nlines:69 run_try:6 header:'Ruby' version:'ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu] ' src_file:primes.rb
#
#SKIPPING: Python 3.2 / python3.2 -V
#SKIPPING: PHP 5.6 / php5.6 -v
#SKIPPING: JavaScript (nodejs) / node -v

View File

@ -0,0 +1,16 @@
# Run time limited to 90 wall-clock seconds
#
# Java 7
# ... compilation
# ... run 1
real_TIME:90.93sec user_CPU:126.82sec sys_CPU:0.76sec max_RSS:680564kb swaps:0 ctx_sw:5308+4566 nlines:167 run_try:1 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java
# ... run 2
real_TIME:90.25sec user_CPU:127.01sec sys_CPU:0.69sec max_RSS:795588kb swaps:0 ctx_sw:4882+4565 nlines:162 run_try:2 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java
# ... run 3
real_TIME:90.62sec user_CPU:126.52sec sys_CPU:0.54sec max_RSS:681920kb swaps:0 ctx_sw:4928+4369 nlines:166 run_try:3 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java
# ... run 4
real_TIME:90.24sec user_CPU:129.11sec sys_CPU:0.51sec max_RSS:807728kb swaps:0 ctx_sw:4814+4353 nlines:140 run_try:4 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java
# ... run 5
real_TIME:90.50sec user_CPU:128.11sec sys_CPU:0.57sec max_RSS:738532kb swaps:0 ctx_sw:4748+4715 nlines:151 run_try:5 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java
# ... run 6
real_TIME:90.16sec user_CPU:125.96sec sys_CPU:0.50sec max_RSS:735604kb swaps:0 ctx_sw:5853+4230 nlines:156 run_try:6 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java

View File

@ -0,0 +1,16 @@
# Run time limited to 90 wall-clock seconds
#
# Java 7
# ... compilation
# ... run 1
real_TIME:90.44sec user_CPU:122.52sec sys_CPU:1.16sec max_RSS:780688kb swaps:0 ctx_sw:5534+5500 nlines:248 run_try:1 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java
# ... run 2
real_TIME:90.32sec user_CPU:123.95sec sys_CPU:0.51sec max_RSS:776000kb swaps:0 ctx_sw:6132+5794 nlines:238 run_try:2 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java
# ... run 3
real_TIME:90.29sec user_CPU:123.78sec sys_CPU:0.56sec max_RSS:794788kb swaps:0 ctx_sw:4891+5050 nlines:237 run_try:3 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java
# ... run 4
real_TIME:90.37sec user_CPU:122.49sec sys_CPU:0.43sec max_RSS:777092kb swaps:0 ctx_sw:5745+5244 nlines:250 run_try:4 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java
# ... run 5
real_TIME:90.62sec user_CPU:124.88sec sys_CPU:0.43sec max_RSS:787036kb swaps:0 ctx_sw:6079+5284 nlines:238 run_try:5 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java
# ... run 6
real_TIME:90.25sec user_CPU:120.78sec sys_CPU:0.74sec max_RSS:807584kb swaps:0 ctx_sw:8699+5378 nlines:235 run_try:6 header:'Java 7' version:'javac 1.7.0_111 ' src_file:primes.java

View File

@ -0,0 +1,16 @@
# Run time limited to 90 wall-clock seconds
#
# Java 8
# ... compilation
# ... run 1
real_TIME:91.68sec user_CPU:130.78sec sys_CPU:0.98sec max_RSS:531208kb swaps:0 ctx_sw:3378+5188 nlines:76 run_try:1 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 2
real_TIME:90.18sec user_CPU:127.97sec sys_CPU:1.03sec max_RSS:532960kb swaps:0 ctx_sw:3621+4771 nlines:76 run_try:2 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 3
real_TIME:91.05sec user_CPU:129.22sec sys_CPU:0.98sec max_RSS:520248kb swaps:0 ctx_sw:3285+4896 nlines:70 run_try:3 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 4
real_TIME:90.83sec user_CPU:128.33sec sys_CPU:1.08sec max_RSS:524944kb swaps:0 ctx_sw:3599+4502 nlines:76 run_try:4 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 5
real_TIME:92.35sec user_CPU:132.43sec sys_CPU:0.89sec max_RSS:531048kb swaps:0 ctx_sw:3199+4389 nlines:75 run_try:5 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 6
real_TIME:90.83sec user_CPU:129.61sec sys_CPU:1.00sec max_RSS:516364kb swaps:0 ctx_sw:3296+4823 nlines:70 run_try:6 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java

View File

@ -0,0 +1,16 @@
# Run time limited to 90 wall-clock seconds
#
# Java 8
# ... compilation
# ... run 1
real_TIME:90.44sec user_CPU:124.97sec sys_CPU:1.61sec max_RSS:513288kb swaps:0 ctx_sw:3477+5036 nlines:69 run_try:1 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 2
real_TIME:90.40sec user_CPU:126.78sec sys_CPU:0.81sec max_RSS:513016kb swaps:0 ctx_sw:3417+4681 nlines:71 run_try:2 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 3
real_TIME:91.48sec user_CPU:128.19sec sys_CPU:0.86sec max_RSS:513284kb swaps:0 ctx_sw:3167+4779 nlines:72 run_try:3 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 4
real_TIME:90.71sec user_CPU:127.14sec sys_CPU:0.94sec max_RSS:513256kb swaps:0 ctx_sw:3265+4928 nlines:70 run_try:4 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 5
real_TIME:91.38sec user_CPU:128.82sec sys_CPU:0.96sec max_RSS:513440kb swaps:0 ctx_sw:3134+4988 nlines:69 run_try:5 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java
# ... run 6
real_TIME:91.93sec user_CPU:128.10sec sys_CPU:1.01sec max_RSS:513260kb swaps:0 ctx_sw:3478+5307 nlines:69 run_try:6 header:'Java 8' version:'javac 1.8.0_102 ' src_file:primes.java

345
results/analyze Executable file
View File

@ -0,0 +1,345 @@
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
sub analyze_run_data {
my $test_name = shift;
my $data = shift;
my $i;
my $deviation;
my $cnt;
my $averages = {};
my $k;
my $avg;
$cnt = scalar @{$data};
for ($i = 0; $i < $cnt; ++$i) {
if ($data->[$i]->{'swaps'} != 0) {
# Did we run out of memory?
warn(sprintf(
"%s: run_try=%d: swaps is non-zero: %d\n",
$test_name, $i + 1, $data->[$i]->{'swaps'}
));
}
if ($data->[$i]->{'sys_t'} + $data->[$i]->{'user_t'} > $data->[$i]->{'real_t'}) {
warn(sprintf(
"%s: run_try=%d: CPU time (%.1f) is bigger than wall-clock time (%.1f); multi-threaded?\n",
$test_name, $i + 1,
$data->[$i]->{'sys_t'} + $data->[$i]->{'user_t'},
$data->[$i]->{'real_t'}
));
}
}
foreach $k (qw/ real_t sys_t user_t cpu_t /) {
$averages->{$k} = 0;
}
for ($i = 0; $i < $cnt; ++$i) {
$data->[$i]->{'cpu_t'} = $data->[$i]->{'sys_t'} + $data->[$i]->{'user_t'};
$data->[$i]->{'per_10_lines'} = {};
foreach $k (qw/ real_t sys_t user_t cpu_t /) {
$data->[$i]->{'per_10_lines'}->{$k} = $data->[$i]->{$k} / $data->[$i]->{'nlines'} * 10;
# XXX: Average values for 10 lines of output.
# XXX: So that we can compare with the previous test method.
$averages->{$k} += $data->[$i]->{'per_10_lines'}->{$k};
}
}
foreach $k (qw/ real_t sys_t user_t cpu_t /) {
$averages->{$k} = $averages->{$k} / $cnt;
}
#print Dumper($data)."\n";
#print Dumper($averages)."\n";
for ($i = 0; $i < $cnt; ++$i) {
foreach $k (qw/ real_t cpu_t /) {
$avg = $averages->{$k};
$deviation = (($avg - $data->[$i]->{'per_10_lines'}->{$k}) / $avg) * 100;
if (abs($deviation) > 5) { # percents
warn(sprintf(
"%s: run_try=%d: Measurement deviations are too high for '%s': %.1f\n",
$test_name, $i + 1, $k, $deviation
));
}
}
}
return $averages;
}
sub _print_results_as_html_header {
print <<'EOF'
<table border="1" style="border-collapse:collapse;" cellpadding="4">
<thead>
<tr>
<th rowspan="2" align="center">Language</th>
<th colspan="3" align="center">CPU time</th>
<th colspan="2" align="center">Slower than</th>
<th rowspan="2" align="center">Language<br>version</th>
<th rowspan="2" align="center">Source<br>code</th>
</tr>
<tr>
<th align="center">User</th>
<th align="center">System</th>
<th align="center">Total</th>
<th align="center">C++</th>
<th align="center">previous</th>
</tr>
</thead>
<tbody>
EOF
}
sub _print_results_as_html_footer {
print <<'EOF'
</tbody>
</table>
EOF
}
sub _print_results_as_html_template {
return <<'EOF'
<tr>
<td>%s</td>
<td align="right">%.3f</td>
<td align="right">%.3f</td>
<td align="right">%.3f</td>
<td align="center">%s</td>
<td align="center">%s</td>
<td align="right">%s</td>
<td align="center"><a href="https://github.com/famzah/langs-performance/blob/master/%s">link</a></td>
</tr>
EOF
}
sub _print_results_as_html_enrich_test_name {
my $test_name = shift;
if ($test_name eq 'C++ (optimized with -O2)') {
return 'C++ <em>(<a href="http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Optimize-Options.html#Optimize-Options">optimized with -O2</a>)</em>';
}
if ($test_name =~ /^Java (\d)$/) {
return 'Java '.$1.' (<a href="https://github.com/famzah/langs-performance/tree/master/java-optimizations">see notes</a>)';
}
if ($test_name =~ /^Java (\d) \(non-std lib\)$/) {
return '<font color="#D1D0CE">Java '.$1.' <em>(<a href="/2010/07/01/cpp-vs-python-vs-perl-vs-php-performance-benchmark/#comment-4084">non-std lib</a>)</em></font>';
}
if ($test_name =~ /^Python (\d\.\d) \+ PyPy$/) {
return '<font color="#D1D0CE">Python '.$1.' + PyPy</font>';
}
if ($test_name eq 'JavaScript (nodejs)') {
return 'Javascript (<a href="http://nodejs.org/">nodejs</a>)';
}
if ($test_name eq 'C++ (not optimized)') {
return '<font color="#D1D0CE">C++ <em>(not optimized)</em></font>';
}
return $test_name;
}
sub _print_results_as_html {
my $test_name = shift;
my $averages = shift;
my @slower = @{ $_[0] }; shift;
my $test_data = shift;
printf(
_print_results_as_html_template(),
_print_results_as_html_enrich_test_name($test_name),
$averages->{'user_t'},
$averages->{'sys_t'},
$averages->{'cpu_t'},
$slower[0],
$slower[1],
$test_data->{'meta'}->{'version'},
$test_data->{'meta'}->{'src_file'}
);
}
sub _print_results_as_text {
my $test_name = shift;
my $averages = shift;
my @slower = @{ $_[0] }; shift;
my $test_data = shift;
printf(
"%-30s: user_t=%6.3f sys_t=%6.3f cpu_t=%6.3f to_CPP=%5s to_prev=%5s version=%s\n",
$test_name,
$averages->{'user_t'},
$averages->{'sys_t'},
$averages->{'cpu_t'},
$slower[0],
$slower[1],
$test_data->{'meta'}->{'version'}
);
}
sub print_results {
my $output = shift;
my @sorted_all = @{ $_[0] }; shift;
my $test_data;
my $test_name;
my $averages;
my @slower = ();
my $idx = -1;
my ($sl_idx, $src_idx);
my $ratio;
my @args;
foreach (@sorted_all) {
$test_name = $_->{'test_name'};
$test_data = $_->{'test_data'};
$averages = $_->{'averages'};
++$idx;
#print Dumper($test_data->{'run_data'})."\n";
#print Dumper($averages)."\n";
if ($idx == 0) {
$slower[0] = '-';
$slower[1] = '-';
} else {
foreach $sl_idx (0,1) {
if ($sl_idx == 0) {
$src_idx = 0;
} else {
$src_idx = $idx - 1;
}
$ratio = $averages->{'cpu_t'} / $sorted_all[$src_idx]->{'averages'}->{'cpu_t'};
$slower[$sl_idx] = sprintf('%d%%', ($ratio - 1.00) * 100);
}
}
@args = ($test_name, $averages, \@slower, $test_data);
if ($output eq 'text') {
_print_results_as_text(@args);
} elsif ($output eq 'html') {
_print_results_as_html(@args);
} else {
die("Unknown output: $output");
}
}
}
sub usage {
die("Usage: $0 [text|html]\nRead results at STDIN and format them as specified.\n");
}
sub parse_ARGV {
my $output_mode = shift @ARGV;
if (!defined($output_mode)) {
usage();
}
if ($output_mode !~ /^(text|html)$/) {
usage();
}
return $output_mode;
}
sub main {
my $line;
my $data = {};
my $averages;
my $k;
my $test_data;
my $test_name;
my @sorted_all = ();
my $output_mode;
$output_mode = parse_ARGV();
while ($line = <STDIN>) {
chomp($line);
if ($line =~ /^\s*#/) {
next;
}
if ($line !~ /^real_TIME:(\d+\.\d+)sec user_CPU:(\d+\.\d+)sec sys_CPU:(\d+\.\d+)sec max_RSS:(\d+)kb swaps:(\d+) ctx_sw:(\d+)\+(\d+) nlines:(\d+) run_try:(\d+) header:'([^']+)' version:'([^']+)' src_file:(\S+)$/) {
die("Unable to parse line: $line\n");
}
my $row = {}; # new reference every time
my $run_try;
my $test_name;
$row->{'real_t'} = $1;
$row->{'user_t'} = $2;
$row->{'sys_t'} = $3;
$row->{'max_RSS'} = $4;
$row->{'swaps'} = $5;
$row->{'ctx_sw_unvol'} = $6;
$row->{'ctx_sw_vol'} = $7;
$row->{'nlines'} = $8;
$run_try = $9 - 1; # XXX: fix index
#
$test_name = $10;
$row->{'version'} = $11;
$row->{'src_file'} = $12;
# trim white-space
$row->{'version'} =~ s/^\s*//;
$row->{'version'} =~ s/\s*$//;
if (!exists($data->{$test_name})) {
$data->{$test_name} = {
'meta' => {},
'run_data' => [],
};
foreach $k (qw/ version src_file /) {
$data->{$test_name}->{'meta'}->{$k} = $row->{$k};
}
}
foreach $k (qw/ version src_file /) {
if ($data->{$test_name}->{'meta'}->{$k} ne $row->{$k}) {
die("Sanity check failed for meta: $line");
}
}
if (exists($data->{$test_name}->{'run_data'}->[$run_try])) {
die("Duplicate run#: $line");
}
delete($row->{'version'});
delete($row->{'src_file'});
$data->{$test_name}->{'run_data'}->[$run_try] = $row;
foreach $k (qw/ version src_file /) {
delete($data->{$test_name}->{'run_data'}->[$run_try]->{$k});
}
}
while (($test_name, $test_data) = each %{$data}) {
$averages = analyze_run_data($test_name, $test_data->{'run_data'});
push(@sorted_all,
{
'test_name' => $test_name,
'test_data' => $test_data,
'averages' => $averages,
});
}
@sorted_all = sort {
$a->{'averages'}->{'cpu_t'} <=> $b->{'averages'}->{'cpu_t'};
} @sorted_all;
if ($output_mode eq 'html') {
_print_results_as_html_header();
}
print_results($output_mode, \@sorted_all);
if ($output_mode eq 'html') {
_print_results_as_html_footer();
}
}
main();

142
run.sh
View File

@ -1,50 +1,136 @@
#!/bin/bash
set -u
EXPSTR='Found 664579 prime numbers.'
RUN_TIME="${RUN_TIME:=90}" # wall-clock time seconds
RUN_TRIES="${RUN_TRIES:=6}" # number of identical runs
MIN_NLINES="${MIN_NLINES:=10}" # it's a fatal error if we get less than this number of output lines
SRC_FILTER="${SRC_FILTER:=x}" # if provided, execute only the given test
DRY_RUN="${DRY_RUN:=0}" # if enabled, do only the compilation phase
export RUN_TIME
echo "# Run time limited to $RUN_TIME wall-clock seconds"
echo "#"
# Note: This increases the memory usage but should still provide linear performance.
function run_benchmark() {
HEADER="$1"
CMD1="$2"
CMD2="$3"
COMPILE_CMD="$2"
RUN_CMD="$3"
VERSION_CMD="$4"
VERSION_FILTER_CMD="$5"
SRC_FILE="$6"
if [ "$SRC_FILTER" != 'x' ]; then
if [ "$SRC_FILE" != "$SRC_FILTER" ]; then
return
fi
fi
$VERSION_CMD >/dev/null 2>&1
if [ "$?" == 127 ]; then # "command not found"
echo "SKIPPING: $HEADER / $VERSION_CMD" >&2
return # skip non-existing interpreter
fi
echo "== $HEADER =="
for n in {1..2}; do
$CMD1 && OUT=$(time $CMD2)
VERSION_OUT="$( $VERSION_CMD 2>&1 | $VERSION_FILTER_CMD | tr '\n' ' ' )"
echo "$OUT" | grep -xv "$EXPSTR" # check that all scripts output the same lines
echo "# $HEADER"
NLINES=$(echo "$OUT"|wc -l)
[ "$NLINES" == '10' ] || echo "Unexpected loops count: $NLINES"
echo "# ... compilation"
$COMPILE_CMD || exit 1 # compilation failed
for n in $(seq 1 "$RUN_TRIES"); do
if [ "$DRY_RUN" -ne 0 ]; then
continue
fi
echo "# ... run $n"
TIMES_FILE="$(mktemp --suffix .langs_perf)" || exit 1
OUT="$(
{
/usr/bin/time -o "$TIMES_FILE" --format \
'real_TIME:%esec user_CPU:%Usec sys_CPU:%Ssec max_RSS:%Mkb swaps:%W ctx_sw:%c+%w' \
$RUN_CMD
} 2>&1
)"
TIMES_OUT="$(cat "$TIMES_FILE" | grep -vx 'Command terminated by signal 9')"
rm "$TIMES_FILE"
# check that all scripts output the same lines
if [ "$(echo "$OUT" | grep -xv "$EXPSTR")" != '' ]; then
echo "ERROR: Unexpected output: $OUT" >&2
exit 1
fi
NLINES="$(echo "$OUT"|wc -l)"
if [ "$NLINES" -lt "$MIN_NLINES" ]; then
echo "ERROR: Not enough successful loops: $NLINES" >&2
echo "$OUT" >&2
exit 1
fi
echo "$TIMES_OUT nlines:$NLINES run_try:$n "\
"header:'$HEADER' version:'$VERSION_OUT' src_file:$SRC_FILE"
done
echo
$VERSION_CMD | $VERSION_FILTER_CMD
echo
}
C='g++' ; run_benchmark 'C++ (optimized with -O2)' "$C -Wall -O2 primes.cpp -o primes.cpp.out" './primes.cpp.out' "$C --version" 'head -n1'
##
C='g++' ; SRC='primes.cpp' ; run_benchmark 'C++ (optimized with -O2)' \
"$C -Wall -O2 $SRC -o primes.cpp.out" './primes.cpp.out' "$C --version" 'head -n1' "$SRC"
rm -f ./primes.cpp.out
C='g++' ; run_benchmark 'C++ (not optimized)' "$C -Wall primes.cpp -o primes.cpp.out" './primes.cpp.out' "$C --version" 'head -n1'
C='g++' ; SRC='primes.cpp' ; run_benchmark 'C++ (not optimized)' \
"$C -Wall $SRC -o primes.cpp.out" './primes.cpp.out' "$C --version" 'head -n1' "$SRC"
rm -f ./primes.cpp.out
C='go' ; run_benchmark 'Go (not optimized, default compiler)' "$C build primes.go" './primes' "$C version" 'cat'
##
C='go' ; SRC='primes.go' ; run_benchmark 'Go' \
"$C build $SRC" './primes' "$C version" 'cat' "$SRC"
go clean
C='pypy' ; run_benchmark 'PyPy 2.7' 'true' "$C ./primes.py" "$C -V" 'cat'
C='python2.7' ; run_benchmark 'Python 2.7' 'true' "$C ./primes.py" "$C -V" 'cat'
C='python3.2' ; run_benchmark 'Python 3.2' 'true' "$C ./primes.py" "$C -V" 'cat'
C='python3.5' ; run_benchmark 'Python 3.5' 'true' "$C ./primes.py" "$C -V" 'cat'
C='perl' ; run_benchmark 'Perl' 'true' "$C ./primes.pl" "$C -v" 'grep built'
C='php5.6' ; run_benchmark 'PHP 5.6' 'true' "$C ./primes.php" "$C -v" 'head -n1'
C='php7.0' ; run_benchmark 'PHP 7.0' 'true' "$C ./primes.php" "$C -v" 'head -n1'
C='javac' ; run_benchmark 'Java (std)' "$C primes.java" 'java PrimeNumbersBenchmarkApp' "$C -version" 'cat'
rm -f PrimeNumbersBenchmarkApp.class PrimeNumbersGenerator.class
C='javac' ; run_benchmark 'Java (non-std)' "$C primes-non-std-lib.java" 'java PrimeNumbersBenchmarkApp' "$C -version" 'cat'
rm -f PrimeNumbersBenchmarkApp.class PrimeNumbersGenerator.class IntList.class
C='node' ; run_benchmark 'JavaScript (nodejs)' 'true' "$C ./primes.js" "$C -v" 'cat'
C='nodejs' ; run_benchmark 'JavaScript (nodejs)' 'true' "$C ./primes.js" "$C -v" 'cat'
##
C='pypy' ; SRC='primes.py' ; run_benchmark 'Python 2.7 + PyPy' 'true' "$C $SRC" "$C -V" 'cat' "$SRC"
C='python2.7' ; SRC='primes.py' ; run_benchmark 'Python 2.7' 'true' "$C $SRC" "$C -V" 'cat' "$SRC"
C='python3.2' ; SRC='primes.py' ; run_benchmark 'Python 3.2' 'true' "$C $SRC" "$C -V" 'cat' "$SRC"
C='python3.5' ; SRC='primes.py' ; run_benchmark 'Python 3.5' 'true' "$C $SRC" "$C -V" 'cat' "$SRC"
##
C='perl' ; SRC='primes.pl' ; run_benchmark 'Perl' 'true' "$C $SRC" "$C -v" 'grep built' "$SRC"
##
C='php5.6' ; SRC='primes.php' ; run_benchmark 'PHP 5.6' 'true' "$C $SRC" "$C -v" 'head -n1' "$SRC"
C='php7.0' ; SRC='primes.php' ; run_benchmark 'PHP 7.0' 'true' "$C $SRC" "$C -v" 'head -n1' "$SRC"
##
JF1='PrimeNumbersBenchmarkApp'
JF2='PrimeNumbersGenerator'
JF3='IntList'
C='javac' ; SRC='primes.java' ; run_benchmark 'Java 8' \
"$C $SRC" "java $JF1" "$C -version" 'cat' "$SRC"
rm -f ${JF1}.class ${JF2}.class
C='javac' ; SRC='primes-alt.java' ; run_benchmark 'Java 8 (non-std lib)' \
"$C $SRC" "java $JF1" "$C -version" 'cat' "$SRC"
rm -f ${JF1}.class ${JF2}.class ${JF3}.class
##
# Node.js has two different binary names; try both of them
C='node' ; SRC='primes.js' ; run_benchmark 'JavaScript (nodejs)' 'true' "$C $SRC" "$C -v" 'cat' "$SRC"
C='nodejs' ; SRC='primes.js' ; run_benchmark 'JavaScript (nodejs)' 'true' "$C $SRC" "$C -v" 'cat' "$SRC"
##
C='ruby' ; SRC='primes.rb' ; run_benchmark 'Ruby' 'true' "$C $SRC" "$C -v" 'cat' "$SRC"