The purpose of this article is to show some speed comparisons between different languages and different compilers/runtimes.
There is an old saying that "There are lies, damned lies and benchmarks.". There are some element of truth to that saying. Benchmark results should always be treated with lots of skepticism.
First, then real world application performance often depends a lot more on disk speed and network speed than CPU speed.
Second, different real world applications are by definition very different. The instruction mix they end up executing are different and the particular instruction mix used by the benchmark is not super relevant.
Third, short benchmarks aka microbenchmarks are notoriously vulnerable to exaggerating the impact of certain optimizations. If a benchmark only does 3 things and a compiler can optimize one of them heavily then it may reduce the benchmark time by 33%, but that does not mean that it can achieve the same for a real world application that does 3000 things.
So bottom line is that by far the best benchmark is the real application.
Foe more information about pitfalls of benchmarks and potential mitigation see Benchmarking.
JvmTest.java:
import java.text.NumberFormat;
import java.text.DecimalFormat;
public class JvmTest {
private static NumberFormat nf = new DecimalFormat("0.00");
private static void printres(long t1, long t2, int n1, int n2, String ops) {
double xperf = (double)n1 * (double)n2 / ((t2 - t1) / 1000.0) ;
String sperf = nf.format(xperf / 1000000);
System.out.println(sperf + " million " + ops + " per second");
}
private final static int NINT = 10000;
private final static int NFP = 1000;
private final static int NSTR = 1000;
private final static int N = 1000000;
public static void testint(int scale) {
int nintscale = NINT / scale;
long t1 = System.currentTimeMillis();
for(int i = 0; i < nintscale; i++) {
int sum = i;
for(int j = 0; j < N; j++) {
sum = ((sum + 1) * 2 + 1) / 2;
}
if(sum != (i + N)) {
System.out.println("Integer test error");
System.exit(1);
}
}
long t2 = System.currentTimeMillis();
printres(t1, t2, nintscale, N, "integer operations");
}
public static void testfp(int scale) {
int nfpscale = NFP / scale;
long t1 = System.currentTimeMillis();
for(int i = 0; i < nfpscale; i++) {
double sum = i;
for(int j = 0; j < N; j++) {
sum = ((sum + 1) * 2 + 1) / 2;
}
if(Math.abs(sum - (i + 1.5 * N)) > 1) {
System.out.println("Floating point test error");
System.exit(1);
}
}
long t2 = System.currentTimeMillis();
printres(t1, t2, nfpscale, N, "floating point operations");
}
private final static String ALFA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static void teststr(int scale) {
int nstrscale = NSTR / scale;
long t1 = System.currentTimeMillis();
for(int i = 0; i < nstrscale; i++) {
StringBuffer sb = new StringBuffer("");
for(int j = 0; j < N; j = j + 10) {
String s = ALFA + ALFA;
int ix = (i + j) % ALFA.length();
sb.append(s.substring(ix, ix + 1) + s.substring(ix + 1, ix + 3) + s.substring(ix + 3, ix + 6) + s.substring(ix + 6, ix + 10));
}
int ix1 = N / 3;
int ix2 = 2 * N / 3;
if(sb.length() != N || sb.charAt(ix1) != ALFA.charAt((i + ix1) % ALFA.length()) || sb.charAt(ix2) != ALFA.charAt((i + ix2) % ALFA.length())) {
System.out.println("String test error");
System.exit(1);
}
}
long t2 = System.currentTimeMillis();
printres(t1, t2, nstrscale, N / 10, "string operations");
}
private final static int REP = 10;
public static void main(String[] args) {
System.out.println(System.getProperty("java.vm.vendor") + " " + System.getProperty("java.vm.name") + " " + System.getProperty("java.vm.version"));
int scale = 1;
if(args.length > 0) {
scale = Integer.parseInt(args[0]);
}
for(int i = 0; i < REP; i++) {
testint(scale);
}
for(int i = 0; i < REP; i++) {
testfp(scale);
}
for(int i = 0; i < REP; i++) {
teststr(scale);
}
}
}
DotNETTest.cs:
using System;
using System.Text;
public class DotNETTest
{
private static void printres(long t1, long t2, int n1, int n2, String ops)
{
double xperf = (double)n1 * (double)n2 / ((t2 - t1) / 1000.0) ;
string sperf = String.Format("{0:0.00}", xperf / 1000000);
Console.WriteLine(sperf + " million " + ops + " per second");
}
private const int NINT = 10000;
private const int NFP = 1000;
private const int NSTR = 100;
private const int N = 1000000;
public static void testint(int scale)
{
int nintscale = NINT / scale;
long t1 = DateTime.Now.Ticks / 10000;
for(int i = 0; i < nintscale; i++)
{
int sum = i;
for(int j = 0; j < N; j++)
{
sum = ((sum + 1) * 2 + 1) / 2;
}
if(sum != (i + N))
{
Console.WriteLine("Integer test error");
Environment.Exit(1);
}
}
long t2 = DateTime.Now.Ticks / 10000;
printres(t1, t2, nintscale, N, "integer operations");
}
public static void testfp(int scale)
{
int nfpscale = NFP / scale;
long t1 = DateTime.Now.Ticks / 10000;
for(int i = 0; i < nfpscale; i++)
{
double sum = i;
for(int j = 0; j < N; j++)
{
sum = ((sum + 1) * 2 + 1) / 2;
}
if(Math.Abs(sum - (i + 1.5 * N)) > 1)
{
Console.WriteLine("Floating point test error");
Environment.Exit(1);
}
}
long t2 = DateTime.Now.Ticks / 10000;
printres(t1, t2, nfpscale, N, "floating point operations");
}
private const string ALFA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static void teststr(int scale)
{
int nstrscale = NSTR / scale;
long t1 = DateTime.Now.Ticks / 10000;
for(int i = 0; i < nstrscale; i++)
{
StringBuilder sb = new StringBuilder("");
for(int j = 0; j < N; j = j + 10)
{
string s = ALFA + ALFA;
int ix = (i + j) % ALFA.Length;
sb.Append(s.Substring(ix, 1) + s.Substring(ix + 1, 2) + s.Substring(ix + 3, 3) + s.Substring(ix + 6, 4));
}
int ix1 = N / 3;
int ix2 = 2 * N / 3;
if(sb.Length != N || sb[ix1] != ALFA[(i + ix1) % ALFA.Length] || sb[ix2] != ALFA[(i + ix2) % ALFA.Length])
{
Console.WriteLine("String test error");
Environment.Exit(1);
}
}
long t2 = DateTime.Now.Ticks / 10000;
printres(t1, t2, nstrscale, N / 10, "string operations");
}
private const int REP = 10;
public static void Main(string[] args)
{
Console.WriteLine("{0} ({1} bit)", Environment.Version, IntPtr.Size * 8);
int scale = 1;
if(args.Length > 0)
{
scale = int.Parse(args[0]);
}
for(int i = 0; i < REP; i++)
{
testint(scale);
}
for(int i = 0; i < REP; i++)
{
testfp(scale);
}
for(int i = 0; i < REP; i++)
{
teststr(scale);
}
}
}
native_test.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "high_res_timer.h"
void printres(TIMECOUNT_T t1, TIMECOUNT_T t2, int n1, int n2, char *ops)
{
double xperf;
xperf = (double)n1 * (double)n2 / ((t2 - t1) * 1.0 / UNITS_PER_SECOND);
printf("%.2f million %s per second\n", xperf / 1000000, ops);
}
#define NINT 10000
#define NFP 1000
#define NSTR 100
#define N 1000000
void testint(int scale)
{
int i, j;
int nintscale, sum;
TIMECOUNT_T t1, t2;
nintscale = NINT / scale;
t1 = GET_TIMECOUNT;
for(i = 0; i < nintscale; i++)
{
sum = i;
for(j = 0; j < N; j++)
{
sum = ((sum + 1) * 2 + 1) / 2;
}
if(sum != (i + N))
{
printf("Integer test error\n");
exit(0);
}
}
t2 = GET_TIMECOUNT;
printres(t1, t2, nintscale, N, "integer operations");
}
void testfp(int scale)
{
int i, j;
int nfpscale;
double sum;
TIMECOUNT_T t1, t2;
nfpscale = NFP / scale;
t1 = GET_TIMECOUNT;
for(i = 0; i < nfpscale; i++)
{
sum = i;
for(j = 0; j < N; j++)
{
sum = ((sum + 1) * 2 + 1) / 2;
}
if(fabs(sum - (i + 1.5 * N)) > 1)
{
printf("Floating point test error\n");
exit(0);
}
}
t2 = GET_TIMECOUNT;
printres(t1, t2, nfpscale, N, "floating point operations");
}
#define ALFA "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
void teststr(int scale)
{
int i, j;
int ix, ix1, ix2;
int nstrscale;
char s[1000], buf[N+1];
TIMECOUNT_T t1, t2;
nstrscale = NSTR / scale;
t1 = GET_TIMECOUNT;
for(i = 0; i < nstrscale; i++)
{
strcpy(buf, "");
for(j = 0; j < N; j = j + 10)
{
strcpy(s, ALFA);
strcat(s, ALFA);
ix = (i + j) % strlen(ALFA);
strncat(buf + j, s + ix, 1);
strncat(buf + j, s + ix + 1, 2);
strncat(buf + j, s + ix + 3, 3);
strncat(buf + j, s + ix + 6 , 4);
}
ix1 = N / 3;
ix2 = 2 * N / 3;
if(strlen(buf) != N || buf[ix1] != ALFA[(i + ix1) % strlen(ALFA)] || buf[ix2] != ALFA[(i + ix2) % strlen(ALFA)])
{
printf("String test error\n");
exit(0);
}
}
t2 = GET_TIMECOUNT;
printres(t1, t2, nstrscale, N / 10, "string operations");
}
#define REP 10
int main(int argc, char *argv[])
{
int i;
int scale;
printf("%d bit\n", (int)(sizeof(char *) * 8));
if(argc > 1)
{
scale = atoi(argv[1]);
}
else
{
scale = 1;
}
for(i = 0; i < REP; i++)
{
testint(scale);
}
for(i = 0; i < REP; i++)
{
testfp(scale);
}
for(i = 0; i < REP; i++)
{
teststr(scale);
}
return 0;
}
native_test.cpp:
#include "high_res_timer.h"
#include <iostream>
#include <iomanip>
#include <ios>
#include <string>
#include <cmath>
#include <cstdlib>
using namespace std;
void printres(TIMECOUNT_T t1, TIMECOUNT_T t2, int n1, int n2, const char *ops)
{
double xperf = (double)n1 * (double)n2 / ((t2 - t1) * 1.0 / UNITS_PER_SECOND);
cout << fixed << setprecision(2) << (xperf / 1000000) << " million " << ops << " per second" << endl;
}
const int NINT = 10000;
const int NFP = 1000;
const int NSTR = 100;
const int N = 1000000;
void testint(int scale)
{
int nintscale = NINT / scale;
TIMECOUNT_T t1 = GET_TIMECOUNT;
for(int i = 0; i < nintscale; i++)
{
int sum = i;
for(int j = 0; j < N; j++)
{
sum = ((sum + 1) * 2 + 1) / 2;
}
if(sum != (i + N))
{
cout << "Integer test error" << endl;
exit(0);
}
}
TIMECOUNT_T t2 = GET_TIMECOUNT;
printres(t1, t2, nintscale, N, "integer operations");
}
void testfp(int scale)
{
int nfpscale = NFP / scale;
TIMECOUNT_T t1 = GET_TIMECOUNT;
for(int i = 0; i < nfpscale; i++)
{
double sum = i;
for(int j = 0; j < N; j++)
{
sum = ((sum + 1) * 2 + 1) / 2;
}
if(fabs(sum - (i + 1.5 * N)) > 1)
{
cout << "Floating point test error" << endl;
exit(0);
}
}
TIMECOUNT_T t2 = GET_TIMECOUNT;
printres(t1, t2, nfpscale, N, "floating point operations");
}
const string ALFA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
void teststr(int scale)
{
int nstrscale = NSTR / scale;
TIMECOUNT_T t1 = GET_TIMECOUNT;
for(int i = 0; i < nstrscale; i++)
{
string s, buf;
buf = "";
for(int j = 0; j < N; j = j + 10)
{
s = ALFA + ALFA;
int ix = (i + j) % ALFA.length();
//buf = buf + s.substr(ix, 1) + s.substr(ix + 1, 2) + s.substr(ix + 3, 3) + s.substr(ix + 6, 4);
buf.append(s, ix, 1);
buf.append(s, ix + 1, 2);
buf.append(s, ix + 3, 3);
buf.append(s, ix + 6, 4);
}
int ix1 = N / 3;
int ix2 = 2 * N / 3;
if(buf.length() != N || buf[ix1] != ALFA[(i + ix1) % ALFA.length()] || buf[ix2] != ALFA[(i + ix2) % ALFA.length()])
{
cout << "String test error" << endl;
exit(0);
}
}
TIMECOUNT_T t2 = GET_TIMECOUNT;
printres(t1, t2, nstrscale, N / 10, "string operations");
}
#define REP 10
int main(int argc, char *argv[])
{
int i;
int scale;
cout << (sizeof(char *) * 8) << " bit" << endl;
if(argc > 1)
{
scale = atoi(argv[1]);
}
else
{
scale = 1;
}
for(i = 0; i < REP; i++)
{
testint(scale);
}
for(i = 0; i < REP; i++)
{
testfp(scale);
}
for(i = 0; i < REP; i++)
{
teststr(scale);
}
return 0;
}
native_test.pas:
program native_test(input, output);
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
procedure printres(t1, t2 : Cardinal; n1, n2 : integer; ops : string);
var
xperf : double;
begin
xperf := n1 * 1.0 * n2 / ((t2 - t1) / 1000.0);
writeln((xperf / 1000000):1:2, ' million ', ops, 'per second');
end;
const
NINT = 10000;
NFP = 1000;
NSTR = 100;
N = 1000000;
procedure testint(scale : integer);
var
i, j, nintscale, sum : integer;
t1, t2 : Cardinal;
begin
nintscale := NINT div scale;
t1 := GetTickCount;
for i := 1 to nintscale do begin
sum := i - 1;
for j := 1 to N do begin
sum := ((sum + 1) * 2 + 1) div 2;
end;
if sum <> (i - 1 + N) then begin
writeln('Integer test error');
halt;
end;
end;
t2 := GetTickCount;
printres(t1, t2, nintscale, N, 'integer operations');
end;
procedure testfp(scale : integer);
var
i, j, nfpscale : integer;
sum : double;
t1, t2 : Cardinal;
begin
nfpscale := NFP div scale;
t1 := GetTickCount;
for i := 1 to nfpscale do begin
sum := i - 1;
for j := 1 to N do begin
sum := ((sum + 1) * 2 + 1) / 2;
end;
if abs(sum - (i - 1 + 1.5 * N)) > 1 then begin
writeln('Floating point test error');
halt;
end;
end;
t2 := GetTickCount;
printres(t1, t2, nfpscale, N, 'floating point operations');
end;
const
ALFA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
procedure teststr(scale : integer);
var
i, j, nstrscale, ix, ix1, ix2 : integer;
s, buf, temp : string;
t1, t2 : Cardinal;
begin
nstrscale := NSTR div scale;
t1 := GetTickCount;
for i := 1 to nstrscale do begin
buf := '';
SetLength(buf, N);
for j := 1 to (N div 10) do begin
s := ALFA + ALFA;
ix := (i - 1 + 10 * (j - 1)) mod Length(ALFA);
temp := Copy(s, ix + 1, 1) + Copy(s, ix + 2, 2) + Copy(s, ix + 4, 3) + Copy(s, ix + 7, 4);
Move(temp[1], buf[10 * (j - 1) + 1], 10);
end;
ix1 := N div 3;
ix2 := 2 * N div 3;
if (Length(buf) <> N) or (buf[ix1] <> ALFA[(i - 2 + ix1) mod Length(ALFA) + 1]) or (buf[ix2] <> ALFA[(i - 2 + ix2) mod Length(ALFA) + 1]) then begin
writeln('String test error');
halt;
end;
end;
t2 := GetTickCount;
printres(t1, t2, nstrscale, N div 10, 'string operations');
end;
const
REP = 10;
var
i, scale : integer;
begin
if paramCount > 0 then begin
scale := StrToInt(paramStr(1));
end else begin
scale := 1;
end;
for i := 1 to REP do begin
testint(scale);
end;
for i := 1 to REP do begin
testfp(scale);
end;
for i := 1 to REP do begin
teststr(scale);
end;
end.
native_test.for:
program native_test
integer*4 REP
parameter (REP = 10)
integer*4 i, scale
character*256 cmdlin
integer*4 cmdlinlen
if(iargc().gt.0) then
call getarg(1, cmdlin)
read(cmdlin,'(I4)') scale
else
scale = 1
end if
do 100 i =1,REP
call testint(scale)
100 continue
do 200 i =1,REP
call testfp(scale)
200 continue
do 300 i =1,REP
call teststr(scale)
300 continue
end
c
subroutine testint(scale)
integer*4 scale
integer*4 NINT,N
parameter (NINT = 10000, N = 1000000)
integer*4 i, j, nintscale, sum
integer*8 t1, t2
nintscale = NINT / scale
call system_clock(t1)
do 200 i = 1, nintscale
sum = i - 1
do 100 j = 1, N
sum = ((sum + 1) * 2 + 1) / 2
100 continue
if(sum.ne.(i - 1 + N)) then
write(*,*) 'Integer test error'
stop
end if
200 continue
call system_clock(t2)
call printres(t1, t2, nintscale, N, 'integer operations')
end
c
subroutine testfp(scale)
integer*4 scale
integer*4 NFP, N
parameter (NFP = 1000, N = 1000000)
integer*4 i, j, nfpscale
real*8 sum
integer*8 t1, t2
nfpscale = NFP / scale
call system_clock(t1)
do 200 i = 1, nfpscale
sum = i - 1
do 100 j = 1, N
sum = ((sum + 1) * 2 + 1) / 2
100 continue
if(abs(sum - (i - 1 + 1.5 * N)).gt.1) then
write(*,*) 'Floating point test error'
stop
end if
200 continue
call system_clock(t2)
call printres(t1, t2, nfpscale, N, 'floating point operations')
end
c
subroutine teststr(scale)
integer*4 scale
integer*4 NSTR, N
character*26 ALFA
parameter (NSTR = 100, N = 1000000,
+ ALFA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
integer*4 i, j, nstrscale, slen, ix, ix1, ix2, ix1m, ix2m
character*52 s
character*1000000 buf
integer*8 t1, t2
nstrscale = NSTR / scale
call system_clock(t1)
do 200 i = 1, nstrscale
slen = 0
do 100 j = 1, N, 10
s = ALFA // ALFA
ix = mod(i - 1 + j - 1, len(ALFA))
buf(slen:slen+9) = s(ix + 1:ix + 1) // s(ix + 2:ix + 3) //
+ s(ix + 4: ix + 6) // s(ix + 7:ix + 10)
slen = slen + 10
100 continue
ix1 = N / 3
ix2 = 2 * N / 3
ix1m = mod(i - 1 + ix1, len(ALFA)) + 1
ix2m = mod(i - 1 + ix2, len(ALFA)) + 1
if((slen.ne.N).or.
+ (buf(ix1:ix1).ne.ALFA(ix1m:ix1m)).or.
+ (buf(ix2:ix2).ne.ALFA(ix2m:ix2m))) then
write(*,*) 'String test error'
stop
end if
200 continue
call system_clock(t2)
call printres(t1, t2, nstrscale, N / 10,
+ 'string operations')
end
c
subroutine printres(t1, t2, n1, n2, ops)
integer*8 t1, t2
integer*4 n1, n2
character*(*) ops
integer*8 dummy, t
real*8 xperf
call system_clock(dummy, t)
xperf = n1 * 1.0 * n2 / ((t2 - t1) / (1.0 * t))
write(*,'(1x,f8.2,9h million ,a,11h per second)')
+ (xperf / 1000000), ops
end
native_test.adb:
with Ada.Command_line,
Ada.Task_Identification,
Ada.Strings.Unbounded,
Ada.Text_IO,
Ada.Integer_Text_IO,
Ada.Float_Text_IO,
Ada.Real_Time;
use Ada.Command_line,
Ada.Task_Identification,
Ada.Strings.Unbounded,
Ada.Text_IO,
Ada.Integer_Text_IO,
Ada.Float_Text_IO,
Ada.Real_Time;
procedure Native_Test is
procedure Print_Res(t1, t2 : Time; n1, n2 : Integer; ops: String) is
xperf : Float;
begin
xperf := Float(n1) * Float(n2) / Float(To_Duration(t2 - t1));
Put(xperf / 1000000.0, Aft => 2, Exp => 0);
Put(" million ");
Put(ops);
Put(" per second");
New_Line;
end Print_Res;
NINT : constant Integer := 10000;
NFP : constant Integer := 1000;
NSTR : constant Integer := 100;
N : constant Integer := 1000000;
procedure Test_Int(scale : Integer) is
nintscale, sum : Integer;
t1, t2 : Time;
begin
nintscale := NINT / scale;
t1 := Clock;
for i in 1..nintscale loop
sum := i - 1;
for j in 1..N loop
sum := ((sum + 1) * 2 + 1) / 2;
end loop;
if sum /= (i - 1 + N) then
Put_Line("Integer test error");
Abort_Task (Current_Task);
end if;
end loop;
t2 := Clock;
Print_Res(t1, t2, nintscale, N, "integer operations");
end Test_Int;
procedure Test_FP(scale : Integer) is
nfpscale : Integer;
sum : Long_Float;
t1, t2 : Time;
begin
nfpscale := NFP / scale;
t1 := Clock;
for i in 1..nfpscale loop
sum := Long_Float(i - 1);
for j in 1..N loop
sum := ((sum + 1.0) * 2.0 + 1.0) / 2.0;
end loop;
if abs (sum - (Long_Float(i - 1) + 1.5 * Long_Float(N))) > 1.0 then
Put_Line("Floating point test error");
Abort_Task (Current_Task);
end if;
end loop;
t2 := Clock;
Print_Res(t1, t2, nfpscale, N, "floating point operations");
end Test_Fp;
procedure Test_Str(scale : Integer) is
ALFA : constant String := "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
s : constant String := ALFA & ALFA;
nstrscale, ix, ix1, ix2, ix1alfa, ix2alfa : Integer;
buf : Unbounded_String;
t1, t2 : Time;
begin
nstrscale := NSTR / scale;
t1 := Clock;
for i in 1..nstrscale loop
buf := To_Unbounded_String("");
for j in 1..N /10 loop
ix := (i - 1 + 10 * (j - 1)) mod ALFA'Length;
Append(buf, s(ix+1..ix+1));
Append(buf, s(ix+2..ix+3));
Append(buf, s(ix+4..ix+6));
Append(buf, s(ix+7..ix+10));
end loop;
ix1 := N / 3;
ix2 := 2 * N / 3;
ix1alfa := (i - 2 + ix1) mod ALFA'Length + 1;
ix2alfa := (i - 2 + ix2) mod ALFA'Length + 1;
if To_String(buf)'Length /= N or To_String(buf)(ix1..ix1) /= ALFA(ix1alfa..ix1alfa) or To_String(buf)(ix2..ix2) /= ALFA(ix2alfa..ix2alfa) then
Put_Line("String test error");
Abort_Task (Current_Task);
end if;
end loop;
t2 := Clock;
Print_Res(t1, t2, nstrscale, N/10, "string operations");
end Test_Str;
REP : constant Integer := 10;
scale : Integer;
begin
if Argument_Count > 0 then
scale := Integer'Value(Argument(1));
else
scale := 1;
end if;
for i in 1..REP loop
Test_Int(scale);
end loop;
for i in 1..REP loop
Test_FP(scale);
end loop;
for i in 1..REP loop
Test_Str(scale);
end loop;
end Native_Test;
script_test.py:
import sys
import time
import math
def printres(t1, t2, n1, n2, ops):
xperf = n1 * n2 / (t2 - t1)
print('%.2f million %s per second' % (xperf / 1000000, ops))
NINT = 10000
NFP = 10000
NSTR = 10000
N = 10000
def testint(scale):
nintscale = NINT // scale
t1 = time.time()
for i in range(nintscale):
sum = i
for j in range(N):
sum = ((sum + 1) * 2 + 1) // 2
if sum != (i + N):
print('Integer test error')
sys.exit(0)
t2 = time.time()
printres(t1, t2, nintscale, N, 'integer operations')
def testfp(scale):
nfpscale = NFP // scale
t1 = time.time()
for i in range(nfpscale):
sum = i
for j in range(N):
sum = ((sum + 1.0) * 2 + 1) / 2
if math.fabs(sum - (i + 1.5 * N)) > 1:
print('Floating point test error')
sys.exit(0)
t2 = time.time()
printres(t1, t2, nfpscale, N, 'floating point operations')
ALFA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def teststr(scale):
nstrscale = NSTR // scale
t1 = time.time()
for i in range(nstrscale):
sb = ''
for j in range(N // 10):
realj = 10 * j
s = ALFA + ALFA
ix = (i + j) % len(ALFA)
sb = sb + s[ix:ix+1] + s[ix+1:ix+3] + s[ix+3:ix+6] + s[ix+6:ix+10]
ix1 = N // 3
ix2 = 2 * N // 3
mix1 = (i + ix1) % len(ALFA)
mix2 = (i + ix2) % len(ALFA)
if len(sb) != N or sb[ix1:ix1] != ALFA[mix1:mix1] or sb[ix2:ix2] != ALFA[mix2:mix2]:
print('String test error')
sys.exit(0)
t2 = time.time()
printres(t1, t2, nstrscale, N // 10, 'string operations')
REP = 10
print(sys.version)
if len(sys.argv) > 1:
scale = int(sys.argv[1])
else:
scale = 1
for i in range(REP):
testint(scale)
for i in range(REP):
testfp(scale)
for i in range(REP):
teststr(scale)
script_test_cython.pyx:
import sys
import time
import math
cdef printres(int t1, int t2, int n1, int n2, ops):
cdef double xperf
xperf = n1 * 1.0 * n2 / (t2 - t1)
print('%.2f million %s per second' % (xperf / 1000000, ops))
cdef int NINT = 1000000
cdef int NFP = 1000000
cdef int NSTR = 10000
cdef int N = 10000
cdef testint(int scale):
cdef int nintscale, sum, i, j
nintscale = NINT // scale
t1 = time.time()
for i in range(nintscale):
sum = i
for j in range(N):
sum = ((sum + 1) * 2 + 1) // 2
if sum != (i + N):
print('Integer test error')
sys.exit(0)
t2 = time.time()
printres(t1, t2, nintscale, N, 'integer operations')
cdef testfp(scale):
cdef int nfpscale, i, j
cdef double sum
nfpscale = NFP // scale
t1 = time.time()
for i in range(nfpscale):
sum = i
for j in range(N):
sum = ((sum + 1.0) * 2 + 1) / 2
if math.fabs(sum - (i + 1.5 * N)) > 1:
print('Floating point test error')
sys.exit(0)
t2 = time.time()
printres(t1, t2, nfpscale, N, 'floating point operations')
ALFA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
cdef teststr(scale):
cdef int nstrscale, i, j, realj, ix, ix1, ix2
nstrscale = NSTR // scale
t1 = time.time()
for i in range(nstrscale):
sb = ''
for j in range(N // 10):
realj = 10 * j
s = ALFA + ALFA
ix = (i + j) % len(ALFA)
sb = sb + s[ix:ix+1] + s[ix+1:ix+3] + s[ix+3:ix+6] + s[ix+6:ix+10]
ix1 = N // 3
ix2 = 2 * N // 3
mix1 = (i + ix1) % len(ALFA)
mix2 = (i + ix2) % len(ALFA)
if len(sb) != N or sb[ix1:ix1] != ALFA[mix1:mix1] or sb[ix2:ix2] != ALFA[mix2:mix2]:
print('String test error')
sys.exit(0)
t2 = time.time()
printres(t1, t2, nstrscale, N // 10, 'string operations')
REP = 10
print(sys.version + ' with cdef')
if len(sys.argv) > 1:
scale = int(sys.argv[1])
else:
scale = 1
for i in range(REP):
testint(scale)
for i in range(REP):
testfp(scale)
for i in range(REP):
teststr(scale)
script_test_codon.py:
import sys
import time
import math
def printres(t1, t2, n1, n2, ops):
xperf = n1 * n2 / (t2 - t1)
print(f'{xperf / 1000000} million {ops} per second')
NINT = 10000
NFP = 10000
NSTR = 100
N = 10000
def testint(scale):
nintscale = NINT // scale
t1 = time.time()
for i in range(nintscale):
sum = i
for j in range(N):
sum = ((sum + 1) * 2 + 1) // 2
if sum != (i + N):
print('Integer test error')
sys.exit(0)
t2 = time.time()
printres(t1, t2, nintscale, N, 'integer operations')
def testfp(scale):
nfpscale = NFP // scale
t1 = time.time()
for i in range(nfpscale):
sum = i + 0.0
for j in range(N):
sum = ((sum + 1.0) * 2 + 1) / 2
if math.fabs(sum - (i + 1.5 * N)) > 1:
print('Floating point test error')
sys.exit(0)
t2 = time.time()
printres(t1, t2, nfpscale, N, 'floating point operations')
ALFA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def teststr(scale):
nstrscale = NSTR // scale
t1 = time.time()
for i in range(nstrscale):
sb = ''
for j in range(N // 10):
realj = 10 * j
s = ALFA + ALFA
ix = (i + j) % len(ALFA)
sb = sb + s[ix:ix+1] + s[ix+1:ix+3] + s[ix+3:ix+6] + s[ix+6:ix+10]
ix1 = N // 3
ix2 = 2 * N // 3
mix1 = (i + ix1) % len(ALFA)
mix2 = (i + ix2) % len(ALFA)
if len(sb) != N or sb[ix1:ix1] != ALFA[mix1:mix1] or sb[ix2:ix2] != ALFA[mix2:mix2]:
print('String test error')
sys.exit(0)
t2 = time.time()
printres(t1, t2, nstrscale, N // 10, 'string operations')
REP = 10
if len(sys.argv) > 1:
scale = int(sys.argv[1])
else:
scale = 1
for i in range(REP):
testint(scale)
for i in range(REP):
testfp(scale)
for i in range(REP):
teststr(scale)
script_test.groovy:
import java.text.DecimalFormat
nf = new DecimalFormat("0.00")
void printres(long t1, long t2, int n1, int n2, String ops) {
xperf = n1 * n2 / ((t2 - t1) / 1000.0)
sperf = nf.format(xperf / 1000000)
println("${sperf} million ${ops} per second")
}
NINT = 10000
NFP = 10000
NSTR = 10000
N = 10000
void testint(int scale) {
nintscale = NINT.intdiv(scale)
t1 = System.currentTimeMillis()
for(i = 0; i < nintscale; i++) {
int sum = i
for(j = 0; j < N; j++) {
sum = ((sum + 1) * 2 + 1).intdiv(2)
}
if(sum != (i + N)) {
println("Integer test error")
System.exit(1)
}
}
t2 = System.currentTimeMillis()
printres(t1, t2, nintscale, N, "integer operations")
}
void testfp(int scale) {
nfpscale = NFP.intdiv(scale)
t1 = System.currentTimeMillis()
for(i = 0; i < nfpscale; i++) {
double sum = i
for(j = 0; j < N; j++) {
sum = ((sum + 1) * 2 + 1) / 2
}
if(Math.abs(sum - (i + 1.5 * N)) > 1) {
println("Floating point test error")
System.exit(1)
}
}
t2 = System.currentTimeMillis()
printres(t1, t2, nfpscale, N, "floating point operations")
}
ALFA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
void teststr(int scale) {
nstrscale = NSTR.intdiv(scale)
t1 = System.currentTimeMillis()
for(i = 0; i < nstrscale; i++) {
sb = new StringBuffer("")
for(j = 0; j < N; j = j + 10) {
s = ALFA + ALFA
ix = (i + j) % ALFA.length()
sb << (s[ix .. ix] + s[ix + 1 .. ix + 2] + s[ix + 3 .. ix + 5] + s[ix + 6 .. ix + 9])
}
ix1 = N.intdiv(3)
ix2 = (2 * N).intdiv(3)
if(sb.length() != N || sb[ix1] != ALFA[(i + ix1) % ALFA.length()] || sb[ix2] != ALFA[(i + ix2) % ALFA.length()]) {
println("String test error")
System.exit(1)
}
}
t2 = System.currentTimeMillis()
printres(t1, t2, nstrscale, N.intdiv(10), "string operations")
}
REP = 10
println("${GroovySystem.version} / ${System.getProperty("java.vm.vendor")} ${System.getProperty("java.vm.name")} ${System.getProperty("java.vm.version")}")
int scale = 1
if(args.length > 0) {
scale = Integer.parseInt(args[0])
}
for(i in 1..REP) {
testint(scale)
}
for(i in 1..REP) {
testfp(scale)
}
for(i in 1..REP) {
teststr(scale)
}
script_test_static.groovy:
import java.text.DecimalFormat
import java.text.NumberFormat
import groovy.transform.*
@CompileStatic
void printres(long t1, long t2, int n1, int n2, String ops) {
NumberFormat nf = new DecimalFormat("0.00")
double xperf = n1 * n2 / ((t2 - t1) / 1000.0)
String sperf = nf.format(xperf / 1000000)
println("${sperf} million ${ops} per second")
}
@CompileStatic
void testint(int scale) {
int NINT = 10000
int N = 10000
int nintscale = NINT.intdiv(scale)
long t1 = System.currentTimeMillis()
for(int i = 0; i < nintscale; i++) {
int sum = i
for(int j = 0; j < N; j++) {
sum = ((sum + 1) * 2 + 1).intdiv(2)
}
if(sum != (i + N)) {
println("Integer test error")
System.exit(1)
}
}
long t2 = System.currentTimeMillis()
printres(t1, t2, nintscale, N, "integer operations")
}
@CompileStatic
void testfp(int scale) {
int NFP = 10000
int N = 10000
int nfpscale = NFP.intdiv(scale)
long t1 = System.currentTimeMillis()
for(int i = 0; i < nfpscale; i++) {
double sum = i
for(int j = 0; j < N; j++) {
sum = ((sum + 1) * 2 + 1) / 2
}
if(Math.abs(sum - (i + 1.5d * N)) > 1) {
println("Floating point test error")
System.exit(1)
}
}
long t2 = System.currentTimeMillis()
printres(t1, t2, nfpscale, N, "floating point operations")
}
@CompileStatic
void teststr(int scale) {
int NSTR = 10000
int N = 10000
String ALFA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
int nstrscale = NSTR.intdiv(scale)
long t1 = System.currentTimeMillis()
for(int i = 0; i < nstrscale; i++) {
StringBuffer sb = new StringBuffer("")
for(int j = 0; j < N; j = j + 10) {
String s = ALFA + ALFA
int ix = (i + j) % ALFA.length()
sb << (s[ix .. ix] + s[ix + 1 .. ix + 2] + s[ix + 3 .. ix + 5] + s[ix + 6 .. ix + 9])
}
int ix1 = N.intdiv(3)
int ix2 = (2 * N).intdiv(3)
if(sb.length() != N || sb[ix1] != ALFA[(i + ix1) % ALFA.length()] || sb[ix2] != ALFA[(i + ix2) % ALFA.length()]) {
println("String test error")
System.exit(1)
}
}
long t2 = System.currentTimeMillis()
printres(t1, t2, nstrscale, N.intdiv(10), "string operations")
}
REP = 10
println("${GroovySystem.version} (static) / ${System.getProperty("java.vm.vendor")} ${System.getProperty("java.vm.name")} ${System.getProperty("java.vm.version")}")
int scale = 1
if(args.length > 0) {
scale = Integer.parseInt(args[0])
}
for(i in 1..REP) {
testint(scale)
}
for(i in 1..REP) {
testfp(scale)
}
for(i in 1..REP) {
teststr(scale)
}
script_test.php:
<?php
function printres($t1, $t2, $n1, $n2, $ops) {
$xperf = $n1 * 1.0 * $n2 / ($t2 - $t1);
echo sprintf("%.2f million %s per second\r\n", $xperf / 1000000, $ops);
}
define('NINT', 10000);
define('NFP', 10000);
define('NSTR', 10000);
define('N', 10000);
function testint($scale) {
$nintscale = NINT / $scale;
$t1 = microtime(true);
for($i = 0; $i < $nintscale; $i++) {
$sum = $i;
for($j = 0; $j < N; $j++) {
$sum = (int)((($sum + 1) * 2 + 1) / 2);
}
if($sum != ($i + N)) {
die('Integer test error');
}
}
$t2 = microtime(true);
printres($t1, $t2, $nintscale, N, 'integer operations');
}
function testfp($scale) {
$nfpscale = NFP / $scale;
$t1 = microtime(true);
for($i = 0; $i < $nfpscale; $i++) {
$sum = $i;
for($j = 0; $j < N; $j++) {
$sum = (($sum + 1.0) * 2.0 + 1.0) / 2.0;
}
if(abs($sum - ($i + 1.5 * N)) > 1) {
die('Floating point test error');
}
}
$t2 = microtime(true);
printres($t1, $t2, $nfpscale, N, 'floating point operations');
}
define('ALFA', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
function teststr($scale) {
$nstrscale = NSTR / $scale;
$t1 = microtime(true);
for($i = 0; $i < $nstrscale; $i++) {
$buf = '';
for($j = 0; $j < N; $j = $j + 10) {
$s = ALFA . ALFA;
$ix = ($i + $j) % strlen(ALFA);
$buf = $buf . substr($s, $ix, 1) . substr($s, $ix + 1, 2) . substr($s, $ix + 3, 3) . substr($s, $ix + 6, 4);
}
$ix1 = (int)(N / 3);
$ix2 = (int)(2 * N / 3);
if(strlen($buf) != N || $buf[$ix1] != ALFA[($i + $ix1) % strlen(ALFA)] || $buf[$ix2] != ALFA[($i + $ix2) % strlen(ALFA)]) {
die('String test error');
}
}
$t2 = microtime(true);
printres($t1, $t2, $nstrscale, N / 10, 'string operations');
}
define('REP', 10);
echo sprintf("PHP %s (%d bit)\r\n", phpversion(), PHP_INT_SIZE * 8);
if($argc > 1) {
$scale = (int)$argv[1];
} else {
$scale = 1;
}
for($i = 0; $i < REP; $i++) {
testint($scale);
}
for($i = 0; $i < REP; $i++) {
testfp($scale);
}
for($i = 0; $i < REP; $i++) {
teststr($scale);
}
?>
Language | Compiler/Runtime | Integer performance | Floating point performance | String performance | Total performance |
---|---|---|---|---|---|
Java | IBM 1.7.0 64 bit | 668 | 209 | 19.55 | 139.75 |
Java | IBM 1.7.0 32 bit | 667 | 209 | 18.91 | 138.14 |
Java | IBM 1.6.0 32 bit | 695 | 208 | 15.87 | 131.89 |
Java | SUN 21.0 Server 64 bit | 551 | 238 | 13.11 | 119.80 |
Java | IBM 1.8.0 32 bit | 667 | 209 | 11.55 | 117.21 |
Java | IBM 1.8.0 64 bit | 666 | 209 | 11.49 | 116.94 |
Java | SUN 17.0 Server 64 bit | 548 | 209 | 13.50 | 115.63 |
Java | SUN 11.0 Server 64 bit | 473 | 209 | 13.19 | 109.25 |
Java | OJDK 11.0 Hotspot 64 bit | 473 | 209 | 13.05 | 108.86 |
Java | BEA 1.6.0 64 bit | 417 | 238 | 10.61 | 101.74 |
Java | SUN 1.6.0 Server 64 bit | 473 | 209 | 9.57 | 98.17 |
Java | SUN 1.6.0 Server 32 bit | 468 | 209 | 9.58 | 97.86 |
Java | SUN 1.7.0 Server 32 bit | 468 | 209 | 9.51 | 97.62 |
Java | BEA 1.6.0 32 bit | 417 | 238 | 9.29 | 97.33 |
Java | SUN 1.8.0 Server 64 bit | 473 | 209 | 9.25 | 97.06 |
Java | OJDK 1.8.0 Hotspot 64 bit | 473 | 209 | 9.03 | 96.29 |
Java | SUN 1.8.0 Server 32 bit | 469 | 209 | 9.04 | 96.05 |
Java | SUN 1.5.0 Server 64 bit | 551 | 209 | 7.58 | 95.57 |
Java | SUN 1.7.0 Server 64 bit | 473 | 209 | 8.77 | 95.35 |
Java | SUN 11.0 Graal 64 bit | 417 | 185 | 10.67 | 93.72 |
Java | SUN 1.5.0 Server 32 bit | 550 | 209 | 6.85 | 92.34 |
Java | IBM 8 OpenJ9 64 bit | 667 | 208 | 4.74 | 86.96 |
Java | OJDK 1.8.0 OpenJ9 64 bit | 663 | 209 | 3.96 | 81.87 |
Java | IBM 11 OpenJ9 64 bit | 668 | 208 | 3.68 | 79.96 |
Java | OJDK 11.0 OpenJ9 64 bit | 667 | 209 | 3.56 | 79.17 |
Java | SUN 1.4.2 Server 32 bit | 550 | 209 | 3.49 | 73.75 |
Java | IBM 17 OpenJ9 64 bit | 668 | 208 | 2.16 | 66.95 |
Java | SUN 1.3.1 Server 32 bit | 635 | 119 | 3.64 | 65.03 |
Java | GraalVM 22.3 native 64 bit | 417 | 185 | 2.48 | 57.62 |
Java | SUN 1.5.0 Client 32 bit | 371 | 133 | 3.03 | 53.07 |
Java | Apache 1.6.0 32 bit | 371 | 177 | 2.24 | 52.79 |
Java | SUN 1.4.2 Client 32 bit | 371 | 133 | 2.16 | 47.41 |
Java | SUN 1.6.0 Client 32 bit | 112 | 185 | 4.37 | 44.90 |
Java | SUN 1.8.0 Client 32 bit | 111 | 185 | 4.32 | 44.60 |
Java | SUN 1.7.0 Client 32 bit | 112 | 185 | 4.00 | 43.60 |
Java | SUN 1.3.1 Client 32 bit | 109 | 133 | 3.31 | 36.34 |
We see that:
The first three conclusions are as expected.
Language | Compiler/Runtime | Integer performance | Floating point performance | String performance | Total performance |
---|---|---|---|---|---|
C# | .NET 2.0 /o+ 32 bit | 1665 | 185 | 6.41 | 125.45 |
C# | .NET 4.0 /o+ 32 bit | 1669 | 185 | 5.43 | 118.80 |
C# | .NET 2.0 32 bit | 1112 | 185 | 6.41 | 109.66 |
C# | .NET 8.0 64 bit | 660 | 206 | 9.32 | 108.21 |
C# | .NET 6.0 64 bit | 667 | 208 | 9.09 | 108.04 |
C# | .NET 5.0 64 bit | 668 | 209 | 8.22 | 104.70 |
C# | .NET 4.0 32 bit | 1112 | 185 | 5.51 | 104.27 |
C# | .NET 6.0 32 bit | 667 | 208 | 7.87 | 102.97 |
C# | Core 3.1 64 bit | 668 | 185 | 7.81 | 98.82 |
C# | .NET 2.0 /o+ 64 bit | 786 | 186 | 5.93 | 95.35 |
C# | .NET 5.0 32 bit | 665 | 209 | 6.05 | 94.39 |
C# | .NET 4.0 /o+ 64 bit | 556 | 185 | 8.01 | 93.75 |
C# | .NET 4.0 64 bit | 555 | 185 | 7.91 | 93.30 |
C# | .NET 7.0 64 bit | 660 | 144 | 8.09 | 91.61 |
C# | Core 3.1 32 bit | 668 | 185 | 6.05 | 90.76 |
C# | .NET 2.0 64 bit | 668 | 167 | 5.93 | 87.13 |
C# | Mono 4.0 32 bit | 417 | 134 | 4.24 | 61.88 |
C# | Mono 4.0 -optimize+ 32 bit | 417 | 134 | 4.22 | 61.78 |
We see that:
Language | Compiler/Runtime | Integer performance | Floating point performance | String performance | Total performance |
---|---|---|---|---|---|
C | GCC 11.1 -O3 -funroll-loops 32 bit | 13354 | 236 | 25.71 | 432.72 |
Fortran | GCC 11.1 -O3 -funroll-loops 64 bit | 13334 | 238 | 25.29 | 431.35 |
C | GCC 11.1 -O3 -funroll-loops 64 bit | 13358 | 239 | 23.10 | 419.36 |
Fortran | GCC 11.1 -O3 -funroll-loops 32 bit | 13332 | 236 | 15.28 | 363.62 |
C++ | GCC 11.1 -O3 -funroll-loops 64 bit | 13351 | 238 | 6.10 | 268.62 |
C++ | GCC 11.1 -O3 -funroll-loops 32 bit | 13349 | 236 | 3.84 | 229.56 |
Fortran | GCC 11.1 -O3 64 bit | 1666 | 238 | 25.55 | 216.38 |
C | GCC 11.1 -O3 32 bit | 1670 | 223 | 25.73 | 212.40 |
C | GCC 11.1 -O3 64 bit | 1670 | 239 | 23.31 | 210.32 |
Fortran | GCC 11.1 -O3 32 bit | 1667 | 222 | 15.91 | 180.57 |
C | GCC 13.1 -O3 -funroll-loops 64 bit | 668 | 239 | 25.25 | 159.15 |
C | GCC 13.1-O3 64 bit | 668 | 239 | 22.52 | 153.20 |
C | MSVC++ VS19 /O2 64 bit | 1055 | 239 | 13.76 | 151.39 |
C++ | MSVC++ VS19 /O2 64 bit | 1047 | 238 | 11.56 | 142.29 |
C | MSVC++ VS19 /O2 32 bit | 835 | 239 | 13.93 | 140.61 |
C | MSVC++ VS12 /O2 64 bit | 833 | 209 | 15.75 | 139.97 |
C | LLVM 16.0 -O3 64 bit | 557 | 239 | 19.89 | 138.34 |
C | LLVM 12.0 -O3 64 bit | 557 | 239 | 19.54 | 137.53 |
C++ | GCC 11.1 -O3 64 bit | 1669 | 238 | 6.08 | 134.17 |
C | MSVC++ VS12 /O2 32 bit | 835 | 209 | 13.62 | 133.46 |
C++ | GCC 11.1 -O3 32 bit | 1662 | 223 | 4.09 | 114.87 |
C++ | MSVC++ VS19 /O2 32 bit | 835 | 238 | 6.95 | 111.37 |
C++ | GCC 13.1 -O3 -funroll-loops 64 bit | 668 | 239 | 8.34 | 110.01 |
C++ | GCC 13.1 -O3 64 bit | 668 | 239 | 8.28 | 109.75 |
C++ | LLVM 16.0 -O3 64 bit | 557 | 239 | 8.28 | 103.30 |
Fortran | GCC 11.1 64 bit | 278 | 139 | 24.63 | 98.37 |
Ada | Gnat 2017 -gnatp -O3 64 bit | 554 | 238 | 5.74 | 91.13 |
Ada | Gnat 2017 -O3 64 bit | 505 | 238 | 5.73 | 88.31 |
C | GCC 13.1 64 bit | 278 | 139 | 17.19 | 87.25 |
C | GCC 11.1 32 bit | 277 | 139 | 16.46 | 85.90 |
C | MSVC++ VS12 64 bit | 371 | 134 | 12.70 | 85.79 |
C | MSVC++ VS19 64 bit | 371 | 134 | 12.70 | 85.79 |
C | GCC 11.1 64 bit | 278 | 139 | 16.31 | 85.74 |
C | MSVC++ VS19 32 bit | 371 | 134 | 12.20 | 84.65 |
C | MSVC++ VS12 32 bit | 371 | 133 | 12.16 | 84.34 |
Fortran | GCC 11.1 32 bit | 278 | 139 | 14.30 | 82.06 |
C++ | GCC 13.1 64 bit | 278 | 139 | 6.05 | 61.60 |
C++ | GCC 11.1 64 bit | 278 | 139 | 5.73 | 60.50 |
Ada | Gnat 2017 -gnatp 64 bit | 276 | 138 | 5.44 | 59.17 |
Pascal | FPC 3.2 -O4 64 bit | 417 | 186 | 2.41 | 57.18 |
C | LLVM 16.0 64 bit | 103 | 145 | 12.18 | 56.66 |
Ada | Gnat 2017 64 bit | 256 | 138 | 5.10 | 56.48 |
C | LLVM 12.0 64 bit | 103 | 134 | 12.35 | 55.45 |
C++ | GCC 11.1 32 bit | 278 | 139 | 3.64 | 52.01 |
C++ | MSVC++ VS19 64 bit | 371 | 134 | 2.55 | 50.23 |
Pascal | Delphi 7 32 bit | 834 | 134 | 1.12 | 50.02 |
Pascal | FPC 3.2 64 bit | 278 | 145 | 2.40 | 45.91 |
C++ | LLVM 16.0 64 bit | 103 | 145 | 6.28 | 45.43 |
C++ | MSVC++ VS19 32 bit | 371 | 133 | 1.77 | 44.37 |
Pascal | Delphi 7 -$O- 32 bit | 370 | 134 | 1.12 | 38.15 |
We see that:
GCC -funroll-loops has a huge impact on the integer test, but as mentioned in disclaimer such an improvement should not be expected for a real application.
Language | Compiler/Runtime | Integer performance | Floating point performance | String performance | Total performance |
---|---|---|---|---|---|
Groovy | Groovy 4.0 / Oracle Java 17 64 bit @CompileStatic | 535 | 207 | 3.04 | 69.57 |
Python | PyPy 7.3 (Python 2.7) 64 bit | 402 | 207 | 2.46 | 58.94 |
Python | PyPy 7.3 (Python 3.7) 64 bit | 401 | 207 | 2.31 | 57.66 |
Groovy | Groovy 2.5 / Oracle Java 8 64 bit @CompileStatic | 160 | 207 | 2.86 | 45.58 |
Groovy | Groovy 3.0 / Oracle Java 11 64 bit @CompileStatic | 145 | 207 | 3.14 | 45.51 |
Python | GraalPython 3.8 / Graal Java 11 64 bit | 243 | 172 | 1.46 | 39.37 |
Python | codon 0.16.3 run -release | 824 | 236 | 0.28 | 37.90 |
Python | Cython 3.0 (Python 3.6) pyx cdef | 256 | 238 | 0.67 | 34.43 |
Python | GraalPython 3.10 / Graal Java 21 64 bit | 291 | 183 | 0.29 | 24.90 |
PHP | HHVM 3.30 | 33 | 44 | 2.22 | 14.81 |
Python | codon 0.16.3 run | 366 | 72 | 0.07 | 12.26 |
PHP | PHP 7.2 GCC 64 bit | 17 | 25 | 1.83 | 9.31 |
PHP | PHP 8.3 FrankenPHP 1.0.0 64 bit | 19 | 29 | 1.36 | 9.08 |
PHP | PHP 7.4 GCC 64 bit | 22 | 34 | 0.67 | 7.91 |
PHP | PHP 8.0 MSVC++ 64 bit | 13 | 18 | 1.34 | 6.70 |
PHP | PHP 8.2 MSVC++ 64 bit | 11 | 14 | 1.30 | 5.76 |
Groovy | Groovy 4.0 / Oracle Java 17 64 bit | 13 | 15 | 0.86 | 5.53 |
PHP | PHP 8.0 MSVC++ 32 bit | 9 | 13 | 1.24 | 5.39 |
PHP | PHP 8.2 MSVC++ 32 bit | 10 | 13 | 1.20 | 5.37 |
PHP | PHP 7.4 MSVC++ 64 bit | 9 | 13 | 1.39 | 5.37 |
Python | Cython 3.0 (Python 3.6) | 10 | 22 | 0.61 | 5.07 |
PHP | PHP 7.2 MSVC++ 32 bit | 9 | 12 | 1.11 | 4.85 |
Groovy | Groovy 2.5 / Oracle Java 8 64 bit | 10 | 10 | 1.04 | 4.63 |
PHP | PeachPie 1.0 / .NET 6 64 bit | 8 | 14 | 0.87 | 4.56 |
PHP | PeachPie 1.0 / .NET 5 64 bit | 7 | 15 | 0.80 | 4.40 |
PHP | PHP 7.4 MSVC++ 32 bit | 8 | 9 | 1.19 | 4.39 |
Groovy | Groovy 3.0 / Oracle Java 11 64 bit | 8 | 8 | 0.99 | 4.08 |
Python | Jython 2.7 / SUN Java 11 64 bit | 13 | 13 | 0.32 | 3.78 |
Python | CPython 3.6 GCC 64 bit | 6 | 8 | 0.76 | 3.30 |
PHP | PHP 5.6 MSVC++ 32 bit | 8 | 10 | 0.39 | 3.13 |
Python | IronPython 3.4 / .NET 6.0 64 bit | 13 | 14 | 0.16 | 3.06 |
PHP | Quercus 4.0 free / SUN JDK 11 64 bit | 6 | 6 | 0.61 | 2.79 |
Python | CPython 3.8 GCC 64 bit | 7 | 7 | 0.41 | 2.78 |
Python | CPython 2.7 MSVC++ 64 bit | 8 | 6 | 0.42 | 2.72 |
Python | IronPython 3.4 / .NET 4.8 64 bit | 9 | 14 | 0.15 | 2.70 |
Python | IronPython 2.7 / .NET 4.8 64 bit | 8 | 12 | 0.18 | 2.58 |
Python | IronPython 2.7 / .NET 4 64 bit | 8 | 11 | 0.18 | 2.49 |
Python | IronPython 3.4 / .NET 4.8 32 bit | 10 | 8 | 0.16 | 2.29 |
Python | CPython 3.6 MSVC++ 64 bit | 5 | 5 | 0.44 | 2.22 |
Python | IronPython 2.7 / .NET 4.8 32 bit | 9 | 7 | 0.16 | 2.19 |
Python | IronPython 2.7 / .NET 4 32 bit | 9 | 7 | 0.16 | 2.18 |
We see that:
The second one should not surprise anyone.
Language | Compiler/Runtime | Integer performance | Floating point performance | String performance | Total performance |
---|---|---|---|---|---|
C | GCC 11.1 -O3 -funroll-loops 32 bit | 13354 | 236 | 25.71 | 432.72 |
Fortran | GCC 11.1 -O3 -funroll-loops 64 bit | 13334 | 238 | 25.29 | 431.35 |
C | GCC 11.1 -O3 -funroll-loops 64 bit | 13358 | 239 | 23.10 | 419.36 |
Fortran | GCC 11.1 -O3 -funroll-loops 32 bit | 13332 | 236 | 15.28 | 363.62 |
C++ | GCC 11.1 -O3 -funroll-loops 64 bit | 13351 | 238 | 6.10 | 268.62 |
C++ | GCC 11.1 -O3 -funroll-loops 32 bit | 13349 | 236 | 3.84 | 229.56 |
Fortran | GCC 11.1 -O3 64 bit | 1666 | 238 | 25.55 | 216.38 |
C | GCC 11.1 -O3 32 bit | 1670 | 223 | 25.73 | 212.40 |
C | GCC 11.1 -O3 64 bit | 1670 | 239 | 23.31 | 210.32 |
Fortran | GCC 11.1 -O3 32 bit | 1667 | 222 | 15.91 | 180.57 |
C | GCC 13.1 -O3 -funroll-loops 64 bit | 668 | 239 | 25.25 | 159.15 |
C | GCC 13.1-O3 64 bit | 668 | 239 | 22.52 | 153.20 |
C | MSVC++ VS19 /O2 64 bit | 1055 | 239 | 13.76 | 151.39 |
C++ | MSVC++ VS19 /O2 64 bit | 1047 | 238 | 11.56 | 142.29 |
C | MSVC++ VS19 /O2 32 bit | 835 | 239 | 13.93 | 140.61 |
C | MSVC++ VS12 /O2 64 bit | 833 | 209 | 15.75 | 139.97 |
Java | IBM 1.7.0 64 bit | 668 | 209 | 19.55 | 139.75 |
C | LLVM 16.0 -O3 64 bit | 557 | 239 | 19.89 | 138.34 |
Java | IBM 1.7.0 32 bit | 667 | 209 | 18.91 | 138.14 |
C | LLVM 12.0 -O3 64 bit | 557 | 239 | 19.54 | 137.53 |
C++ | GCC 11.1 -O3 64 bit | 1669 | 238 | 6.08 | 134.17 |
C | MSVC++ VS12 /O2 32 bit | 835 | 209 | 13.62 | 133.46 |
Java | IBM 1.6.0 32 bit | 695 | 208 | 15.87 | 131.89 |
C# | .NET 2.0 /o+ 32 bit | 1665 | 185 | 6.41 | 125.45 |
Java | SUN 21.0 Server 64 bit | 551 | 238 | 13.11 | 119.80 |
C# | .NET 4.0 /o+ 32 bit | 1669 | 185 | 5.43 | 118.80 |
Java | IBM 1.8.0 32 bit | 667 | 209 | 11.55 | 117.21 |
Java | IBM 1.8.0 64 bit | 666 | 209 | 11.49 | 116.94 |
Java | SUN 17.0 Server 64 bit | 548 | 209 | 13.50 | 115.63 |
C++ | GCC 11.1 -O3 32 bit | 1662 | 223 | 4.09 | 114.87 |
C++ | MSVC++ VS19 /O2 32 bit | 835 | 238 | 6.95 | 111.37 |
C++ | GCC 13.1 -O3 -funroll-loops 64 bit | 668 | 239 | 8.34 | 110.01 |
C++ | GCC 13.1 -O3 64 bit | 668 | 239 | 8.28 | 109.75 |
C# | .NET 2.0 32 bit | 1112 | 185 | 6.41 | 109.66 |
Java | SUN 11.0 Server 64 bit | 473 | 209 | 13.19 | 109.25 |
Java | OJDK 11.0 Hotspot 64 bit | 473 | 209 | 13.05 | 108.86 |
C# | .NET 8.0 64 bit | 660 | 206 | 9.32 | 108.21 |
C# | .NET 6.0 64 bit | 667 | 208 | 9.09 | 108.04 |
C# | .NET 5.0 64 bit | 668 | 209 | 8.22 | 104.70 |
C# | .NET 4.0 32 bit | 1112 | 185 | 5.51 | 104.27 |
C++ | LLVM 16.0 -O3 64 bit | 557 | 239 | 8.28 | 103.30 |
C# | .NET 6.0 32 bit | 667 | 208 | 7.87 | 102.97 |
Java | BEA 1.6.0 64 bit | 417 | 238 | 10.61 | 101.74 |
C# | Core 3.1 64 bit | 668 | 185 | 7.81 | 98.82 |
Fortran | GCC 11.1 64 bit | 278 | 139 | 24.63 | 98.37 |
Java | SUN 1.6.0 Server 64 bit | 473 | 209 | 9.57 | 98.17 |
Java | SUN 1.6.0 Server 32 bit | 468 | 209 | 9.58 | 97.86 |
Java | SUN 1.7.0 Server 32 bit | 468 | 209 | 9.51 | 97.62 |
Java | BEA 1.6.0 32 bit | 417 | 238 | 9.29 | 97.33 |
Java | SUN 1.8.0 Server 64 bit | 473 | 209 | 9.25 | 97.06 |
Java | OJDK 1.8.0 Hotspot 64 bit | 473 | 209 | 9.03 | 96.29 |
Java | SUN 1.8.0 Server 32 bit | 469 | 209 | 9.04 | 96.05 |
Java | SUN 1.5.0 Server 64 bit | 551 | 209 | 7.58 | 95.57 |
Java | SUN 1.7.0 Server 64 bit | 473 | 209 | 8.77 | 95.35 |
C# | .NET 2.0 /o+ 64 bit | 786 | 186 | 5.93 | 95.35 |
C# | .NET 5.0 32 bit | 665 | 209 | 6.05 | 94.39 |
C# | .NET 4.0 /o+ 64 bit | 556 | 185 | 8.01 | 93.75 |
Java | SUN 11.0 Graal 64 bit | 417 | 185 | 10.67 | 93.72 |
C# | .NET 4.0 64 bit | 555 | 185 | 7.91 | 93.30 |
Java | SUN 1.5.0 Server 32 bit | 550 | 209 | 6.85 | 92.34 |
C# | .NET 7.0 64 bit | 660 | 144 | 8.09 | 91.61 |
Ada | Gnat 2017 -gnatp -O3 64 bit | 554 | 238 | 5.74 | 91.13 |
C# | Core 3.1 32 bit | 668 | 185 | 6.05 | 90.76 |
Ada | Gnat 2017 -O3 64 bit | 505 | 238 | 5.73 | 88.31 |
C | GCC 13.1 64 bit | 278 | 139 | 17.19 | 87.25 |
C# | .NET 2.0 64 bit | 668 | 167 | 5.93 | 87.13 |
Java | IBM 8 OpenJ9 64 bit | 667 | 208 | 4.74 | 86.96 |
C | GCC 11.1 32 bit | 277 | 139 | 16.46 | 85.90 |
C | MSVC++ VS12 64 bit | 371 | 134 | 12.70 | 85.79 |
C | MSVC++ VS19 64 bit | 371 | 134 | 12.70 | 85.79 |
C | GCC 11.1 64 bit | 278 | 139 | 16.31 | 85.74 |
C | MSVC++ VS19 32 bit | 371 | 134 | 12.20 | 84.65 |
C | MSVC++ VS12 32 bit | 371 | 133 | 12.16 | 84.34 |
Fortran | GCC 11.1 32 bit | 278 | 139 | 14.30 | 82.06 |
Java | OJDK 1.8.0 OpenJ9 64 bit | 663 | 209 | 3.96 | 81.87 |
Java | IBM 11 OpenJ9 64 bit | 668 | 208 | 3.68 | 79.96 |
Java | OJDK 11.0 OpenJ9 64 bit | 667 | 209 | 3.56 | 79.17 |
Java | SUN 1.4.2 Server 32 bit | 550 | 209 | 3.49 | 73.75 |
Groovy | Groovy 4.0 / Oracle Java 17 64 bit @CompileStatic | 535 | 207 | 3.04 | 69.57 |
Java | IBM 17 OpenJ9 64 bit | 668 | 208 | 2.16 | 66.95 |
Java | SUN 1.3.1 Server 32 bit | 635 | 119 | 3.64 | 65.03 |
C# | Mono 4.0 32 bit | 417 | 134 | 4.24 | 61.88 |
C# | Mono 4.0 -optimize+ 32 bit | 417 | 134 | 4.22 | 61.78 |
C++ | GCC 13.1 64 bit | 278 | 139 | 6.05 | 61.60 |
C++ | GCC 11.1 64 bit | 278 | 139 | 5.73 | 60.50 |
Ada | Gnat 2017 -gnatp 64 bit | 276 | 138 | 5.44 | 59.17 |
Python | PyPy 7.3 (Python 2.7) 64 bit | 402 | 207 | 2.46 | 58.94 |
Python | PyPy 7.3 (Python 3.7) 64 bit | 401 | 207 | 2.31 | 57.66 |
Java | GraalVM 22.3 native 64 bit | 417 | 185 | 2.48 | 57.62 |
Pascal | FPC 3.2 -O4 64 bit | 417 | 186 | 2.41 | 57.18 |
C | LLVM 16.0 64 bit | 103 | 145 | 12.18 | 56.66 |
Ada | Gnat 2017 64 bit | 256 | 138 | 5.10 | 56.48 |
C | LLVM 12.0 64 bit | 103 | 134 | 12.35 | 55.45 |
Java | SUN 1.5.0 Client 32 bit | 371 | 133 | 3.03 | 53.07 |
Java | Apache 1.6.0 32 bit | 371 | 177 | 2.24 | 52.79 |
C++ | GCC 11.1 32 bit | 278 | 139 | 3.64 | 52.01 |
C++ | MSVC++ VS19 64 bit | 371 | 134 | 2.55 | 50.23 |
Pascal | Delphi 7 32 bit | 834 | 134 | 1.12 | 50.02 |
Java | SUN 1.4.2 Client 32 bit | 371 | 133 | 2.16 | 47.41 |
Pascal | FPC 3.2 64 bit | 278 | 145 | 2.40 | 45.91 |
Groovy | Groovy 2.5 / Oracle Java 8 64 bit @CompileStatic | 160 | 207 | 2.86 | 45.58 |
Groovy | Groovy 3.0 / Oracle Java 11 64 bit @CompileStatic | 145 | 207 | 3.14 | 45.51 |
C++ | LLVM 16.0 64 bit | 103 | 145 | 6.28 | 45.43 |
Java | SUN 1.6.0 Client 32 bit | 112 | 185 | 4.37 | 44.90 |
Java | SUN 1.8.0 Client 32 bit | 111 | 185 | 4.32 | 44.60 |
C++ | MSVC++ VS19 32 bit | 371 | 133 | 1.77 | 44.37 |
Java | SUN 1.7.0 Client 32 bit | 112 | 185 | 4.00 | 43.60 |
Python | GraalPython 3.8 / Graal Java 11 64 bit | 243 | 172 | 1.46 | 39.37 |
Pascal | Delphi 7 -$O- 32 bit | 370 | 134 | 1.12 | 38.15 |
Python | codon 0.16.3 run -release | 824 | 236 | 0.28 | 37.90 |
Java | SUN 1.3.1 Client 32 bit | 109 | 133 | 3.31 | 36.34 |
Python | Cython 3.0 (Python 3.6) pyx cdef | 256 | 238 | 0.67 | 34.43 |
Python | GraalPython 3.10 / Graal Java 21 64 bit | 291 | 183 | 0.29 | 24.90 |
PHP | HHVM 3.30 | 33 | 44 | 2.22 | 14.81 |
Python | codon 0.16.3 run | 366 | 72 | 0.07 | 12.26 |
PHP | PHP 7.2 GCC 64 bit | 17 | 25 | 1.83 | 9.31 |
PHP | PHP 8.3 FrankenPHP 1.0.0 64 bit | 19 | 29 | 1.36 | 9.08 |
PHP | PHP 7.4 GCC 64 bit | 22 | 34 | 0.67 | 7.91 |
PHP | PHP 8.0 MSVC++ 64 bit | 13 | 18 | 1.34 | 6.70 |
PHP | PHP 8.2 MSVC++ 64 bit | 11 | 14 | 1.30 | 5.76 |
Groovy | Groovy 4.0 / Oracle Java 17 64 bit | 13 | 15 | 0.86 | 5.53 |
PHP | PHP 8.0 MSVC++ 32 bit | 9 | 13 | 1.24 | 5.39 |
PHP | PHP 7.4 MSVC++ 64 bit | 9 | 13 | 1.39 | 5.37 |
PHP | PHP 8.2 MSVC++ 32 bit | 10 | 13 | 1.20 | 5.37 |
Python | Cython 3.0 (Python 3.6) | 10 | 22 | 0.61 | 5.07 |
PHP | PHP 7.2 MSVC++ 32 bit | 9 | 12 | 1.11 | 4.85 |
Groovy | Groovy 2.5 / Oracle Java 8 64 bit | 10 | 10 | 1.04 | 4.63 |
PHP | PeachPie 1.0 / .NET 6 64 bit | 8 | 14 | 0.87 | 4.56 |
PHP | PeachPie 1.0 / .NET 5 64 bit | 7 | 15 | 0.80 | 4.40 |
PHP | PHP 7.4 MSVC++ 32 bit | 8 | 9 | 1.19 | 4.39 |
Groovy | Groovy 3.0 / Oracle Java 11 64 bit | 8 | 8 | 0.99 | 4.08 |
Python | Jython 2.7 / SUN Java 11 64 bit | 13 | 13 | 0.32 | 3.78 |
Python | CPython 3.6 GCC 64 bit | 6 | 8 | 0.76 | 3.30 |
PHP | PHP 5.6 MSVC++ 32 bit | 8 | 10 | 0.39 | 3.13 |
Python | IronPython 3.4 / .NET 6.0 64 bit | 13 | 14 | 0.16 | 3.06 |
PHP | Quercus 4.0 free / SUN JDK 11 64 bit | 6 | 6 | 0.61 | 2.79 |
Python | CPython 3.8 GCC 64 bit | 7 | 7 | 0.41 | 2.78 |
Python | CPython 2.7 MSVC++ 64 bit | 8 | 6 | 0.42 | 2.72 |
Python | IronPython 3.4 / .NET 4.8 64 bit | 9 | 14 | 0.15 | 2.70 |
Python | IronPython 2.7 / .NET 4.8 64 bit | 8 | 12 | 0.18 | 2.58 |
Python | IronPython 2.7 / .NET 4 64 bit | 8 | 11 | 0.18 | 2.49 |
Python | IronPython 3.4 / .NET 4.8 32 bit | 10 | 8 | 0.16 | 2.29 |
Python | CPython 3.6 MSVC++ 64 bit | 5 | 5 | 0.44 | 2.22 |
Python | IronPython 2.7 / .NET 4.8 32 bit | 9 | 7 | 0.16 | 2.19 |
Python | IronPython 2.7 / .NET 4 32 bit | 9 | 7 | 0.16 | 2.18 |
We see that:
The last one should not surprise anyone.
Version | Date | Description |
---|---|---|
1.0 | January 14th 2004 | Initial version (in Danish) published on Eksperten.dk |
2.0 | October 2nd 2021 | New benchmark code and complete rewrite (in English) |
2.1 | November 16th 2021 | Add Ada |
2.2 | December 26th 2022 | Add a few new versions |
2.3 | May 7th 2022 | Add C++ and Fortran |
2.4 | May 17th 2022 | Add some new versions |
2.5 | December 15th 2023 | Add more script tests (Groovy, codon, cython, FrankenPHP) |
See list of all articles here
Please send comments to Arne Vajhøj