From: John Watton
Subject: Benchmarks Franz ACL 3.0.1 vs. 4.3.2 (& C, Java, Perl) on Windows NT
Date: 
Message-ID: <uvhwzlf9y.fsf@alcoa.com>
I hope some of you find my multilanguage benchmarks of interest. What
I thought would be a quick and painless learning exercise has taken
longer than imagined. One reason for that is my effort to make the
benchmarks little programs that approach usefulness in their own
right. The "product" to this point is far from satisfactory. For this
reason I welcome comments and suggestions. But if you do, please spare
me the ideas that don't actually give the right answer! I have enough
trouble debugging my own code. My main conclusion: completing this
exercise was more valuable to me than the actual results. Secondary
conclusion: Java is great for the former C++ masses but my experience
with it never made me doubt my religion.

John Watton
Applied Mathematics and Computer Technology
Alcoa Technical Center
_____________________________________________

Machine: Pentium 90 Mhz, 40 Meg RAM
OS: Windows NT
Note: If the tables look messy try a fixed width font.

Double floating point benchmark
Pnpoly area [1]               sec    rel
-----------                   ---    ---
C    | VC++ 4.0 (cl -Ox)     16.5    1.0
Java | JDK 1.1.4 (JIT) [2]   20.2    1.2 
C    | VC++ 4.0 (cl)         23.5    1.4
Lisp | Franz ACL 4.3.2 [3]   25.6    1.6
Java | JDK 1.1.4 (-O)       106.9    6.5
Lisp | Franz ACL 3.0.1      521.3   31.6
Perl | Perl5.003           1007.0   61.0

Strings and ascii file io benchmark
Rhyming dictionary [4]     read string sort write total
------------------         ----  rev's ---- -----   sec  rel
                                ------              ---  ---
C    | VC++ 4.0 (cl -Ox)                            1.6  1.0
C    | VC++ 4.0 (cl)                                1.8  1.1
Lisp | Franz ACL 4.3.2     1.84  1.44  2.22  0.74   6.2  3.9
Perl | Perl5.003                                   22.0 13.8
Java | JDK 1.1.4 (JIT)                             26.9 16.8
Lisp | Franz ACL 3.0.1    30.10  1.60  5.35 19.60  56.6 35.4
Java | JDK 1.1.4 (-O)                              59.2 37.0

Integer benchmark          < 32 bit         > 32 bit
Prime number search [5]         sec   rel        sec   rel
-------------------       ---------   --- ----------   ---
C    | VC++ 4.0 (cl -Ox)        2.6   1.0        n/a   n/a
C    | VC++ 4.0 (cl)            3.1   1.2        n/a   n/a
Java | JDK 1.1.4 (JIT)          4.9   1.9      265.1   3.1
Java | JDK 1.1.4 (-O)           8.0   3.1      343.5   4.0
Lisp | Franz ACL 4.3.2         15.1   5.8       85.6   1.0
Perl | Perl5.003 [6]           56.1  21.6    29477.0 344.4
Lisp | Franz ACL 3.0.1         78.5  30.2      103.6   1.2

Source Code conciseness table [7]
-----------------------------
      Pnpoly Area    Rhyme Dict  Prime search         Total
      lines/chars   lines/chars   lines/chars   lines/chars
C    |     40/954       58/1223      30+/771+    128+/2948+
Java |    36/1044       68/1816       78/2193      182/5053
Lisp |    42/1412        10/463        17/712       69/2587
Perl |     40/982        12/316       64/1478      116/2776

Notes 
----- 

[1] The original C version of pnpoly came from the Usenet
comp.graphics.algorithms FAQ. It is a function to determine if a 2d
point is inside a closed polygon using the ray crossing algorithm.  I
use the routine in a crude calculation of the area of an hypocycloid
of four cusps.  The answer is 117.2853 with inputs: 200, 400.

[2] JIT - a Java just in time compiler beta from Sun.

[3] I used Franz ACL 4.3.2 beta but a released version is now
available (see www.franz.com).

[4] The rhyme benchmark is based on the version on page 224 of _ANSI
Common Lisp_ by Paul Graham. It is a function that reads a file of
words one per line and composes a rhyming dictionary with them. For
this test I copied the file /usr/dict/words from a UNIX machine
(approx 25000 words). If you don't have this file handy try
ftp://ftp.uu.net/doc/dictionaries.

[5] Prime number count really. The < 32 bit test is in the range 0 to
200000 (answer 17985) and the > 32 bit test is in the range
1000000000050 to 1000000000100 (answer 3). The algorithm used is near
the simplest and least efficient possible, but nearly the same for all
languages. I realize that the inputs to the > 32 bit test are in the
range of the long int of some languages but choose not to use it in
favor of the general unlimited integer types.

[6] The Perl version for > 32 bit either doesn't work well or BigInt
isn't ready for prime time.

[7] These numbers were computed using M-= in emacs and include the
spartan comments and blank lines. The Prime search C count is for the
< 32 bit version only, which explains the + notation. By my presenting
this table don't mistake me for someone who believes that conciseness
is everything (or much of anything). I had to contrieve some test
where Lisp is the winner. :-)

Source Code
-----------
_________________________ 
[1] Pnpoly Area Benchmark:

PNPOLY_C_PNPOLY_C_PNPOLY_C_PNPOLY_C_PNPOLY_C_PNPOLY_C_PNPOLY_C_PNPOLY_C
#include "math.h"

int pnpoly(int npol, double *xp, double *yp, double x, double y)
{
  int i, j, c = 0;
  for (i = 0, j = npol-1; i < npol; j = i++) {
    if ((((yp[i]<=y) && (y<yp[j])) ||
	 ((yp[j]<=y) && (y<yp[i]))) &&
	(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
      c = !c;
  }
  return c;
}

main(int argc, char *argv[]) {
  int npol = atoi(argv[1]); /* 200 */
  int div = atoi(argv[2]); /* 400 */
  int count = 0;
  double pi = acos(-1.0);
  double* xp;
  double* yp;
  double theta;
  double a = 10.0;
  double fdiv = 2*a/div;
  int i=0, j=0;
  xp = malloc(npol*sizeof(double));
  yp = malloc(npol*sizeof(double));
  for(i=0;i<npol;i++) {
    theta = i*2*pi/npol;
    xp[i] = a+a*pow(cos(theta), 3);
    yp[i] = a+a*pow(sin(theta), 3);
  }
  for(i=0;i<=div;i++) {
    for(j=0;j<=div;j++) {
      if (pnpoly(npol,xp,yp,i*fdiv,j*fdiv)) count++;
    }
  }
  printf("\nArea: %f \n", 4*a*a*count/((div+1)*(div+1)));
  return(0);
}

PNPOLY_JAVA_PNPOLY_JAVA_PNPOLY_JAVA_PNPOLY_JAVA_PNPOLY_JAVA_PNPOLY_JAVA
public class Pnpoly {
  public static boolean pnpoly(int npol, double[] xp, double[] yp, double x, double y)
    {
      int i, j;
      boolean c = false;
      for (i = 0, j = npol-1; i < npol; j = i++) {
	if ((((yp[i]<=y) && (y<yp[j])) ||
	     ((yp[j]<=y) && (y<yp[i]))) &&
	    (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
	  c = !c;
      }
      return c;
    }

  public static void main(String args[]) {
    int npol = Integer.parseInt(args[0]); // 200
    int div = Integer.parseInt(args[1]); // 400
    int count = 0;
    double theta;
    double a = 10.0;
    double fdiv = 2*a/div;
    int i=0, j=0;
    double[] xp = new double[npol], yp = new double[npol];
    for(i=0;i<npol;i++) {
      theta = i*2*Math.PI/npol;
      xp[i] = a+a*Math.pow(Math.cos(theta), 3);
      yp[i] = a+a*Math.pow(Math.sin(theta), 3);
    }
    for(i=0;i<=div;i++) {
      for(j=0;j<=div;j++) {
	if (Pnpoly.pnpoly(npol,xp,yp,i*fdiv,j*fdiv)) count++;
      }
    }
    System.out.println("Area: " + 4*a*a*count/((div+1)*(div+1)));
  }
}

PNPOLY_LISP_PNPOLY_LISP_PNPOLY_LISP_PNPOLY_LISP_PNPOLY_LISP_PNPOLY_LISP
(defun pnpoly (npol xp yp x y)
  (declare (optimize (speed 3) (safety 0))
	   (fixnum npol)
	   (double-float x y)
	   (type (simple-array double-float (*)) xp yp))
  (let* ((c nil)
	 (j (1- npol)))
    (declare (fixnum j))
    (dotimes (i npol c)
      (declare (fixnum i))
      (if (and (or (and (<= (aref yp i) y) (< y (aref yp j)))
		   (and (<= (aref yp j) y) (< y (aref yp i))))
	       (< x (+ (aref xp i) (/ (* (- (aref xp j) (aref xp i))
					 (- y (aref yp i)))
				      (- (aref yp j) (aref yp i))))))
	  (setq c (not c)))
      (setq j i)))) 

(defun pnpolymain (npol div)
  (declare (optimize (speed 3) (safety 0))
	   (fixnum npol div)
	   (:explain :boxing :calls))
  (let* ((xp (make-array npol :element-type 'double-float))
	 (yp (make-array npol :element-type 'double-float))
	 (theta 0.0d0)
	 (a 10.0d0)
	 (fdiv (/ (* 2 a) div))
	 (count 0))
    (declare (double-float fdiv a theta)
	     (fixnum count)
	     (type (simple-array double-float (*)) xp yp))
    (dotimes (i npol)
      (declare (fixnum i))
      (setq theta (/ (* 2 i pi) npol))
      (setf (aref xp i) (+ a (* a (expt (cos theta) 3)))
	    (aref yp i) (+ a (* a (expt (sin theta) 3)))))
    (dotimes (u (1+ div))
      (declare (fixnum u))
      (dotimes (v (1+ div))
	(declare (fixnum v))
	(if (pnpoly npol xp yp (* u fdiv) (* v fdiv)) (incf count))))
    (format t "~%Area:  ~a" (/ (* count 4 a a) (* (1+ div) (1+ div))))))

PNPOLY_PERL_PNPOLY_PERL_PNPOLY_PERL_PNPOLY_PERL_PNPOLY_PERL_PNPOLY_PERL
$div = pop(@ARGV);
$npol = pop(@ARGV);
pnpolymain($npol, $div);

sub pnpoly {
    my($npol, $xxp, $yyp, $x, $y) = @_;
    my($j, $c, $i) = ($npol - 1, 0, 0);
    for ($i = 0; $i < $npol; $i++) {
	if (((($$yyp[$i] <= $y) && ($y < $$yyp[$j])) ||
	     (($$yyp[$j] <= $y) && ($y < $$yyp[$i]))) &&
	    ($x < (($$xxp[$j] - $$xxp[$i]) * 
		   ($y - $$yyp[$i]) /
		   ($$yyp[$j] - $$yyp[$i]) + $$xxp[$i]))) {
	    $c = !$c;}
	$j = $i;
    }
    $c;
}

sub pnpolymain {
    my($npol, $div) = @_;
    my($count, $a, $fdiv, $theta, $i, $j, $x, $y, $pi, @xp, @yp);
    $count=0;
    $a = 10.0;
    $fdiv = 2*$a/$div;
    $pi = atan2(1,1) * 4;
    for($i=0;$i<$npol;$i++) {
	$theta = $i*2*$pi/$npol;
	push @xp, $a+$a*(cos($theta)**3);
	push @yp, $a+$a*(sin($theta)**3);
    }
    for($i=0;$i<=$div;$i++) {
	for($j=0;$j<=$div;$j++) {
	    $x = $i*$fdiv;
	    $y = $j*$fdiv;
	    if (pnpoly($npol,·@xp,·@yp,$x,$y)) {$count++};
	}
    }
    print "\nArea: ", 4*$a*$a*$count/(($div+1)*($div+1));
}
________________________________ 
[2] Rhyming dictionary benchmark:

RHYME_C_RHYME_C_RHYME_C_RHYME_C_RHYME_C_RHYME_C_RHYME_C_RHYME_C
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

void stringrev (char* word)
{
  char tmp;
  int len, i, j;
  int half;
  len = strlen(word);
  half = len/2;
  for (i=0,j=len-1;i+1<=half;i++,j--) {
    tmp = word[i];
    word[i] = word[j];
    word[j] = tmp;
  }
}

int pstrcmp (const void* p1, const void* p2)
{
  return strcmp(*(char **)p1, *(char **)p2);
}

void main (int argc, char *argv[])
{
  char wordbuf[128];
  char* newword;
  FILE *in;
  FILE *out;
  int i, end, len, count = 0, grow = 5000, listsize = 5000;
  char** list;
  list = malloc(grow*sizeof(char*));
  in = fopen(argv[1], "r");
  out = fopen(argv[2], "w");
  for (;;) {
    end = fscanf(in, "%s", wordbuf);
    if (end == EOF) break;
    len = 1+strlen(wordbuf);
    newword = malloc(len);
    strncpy(newword, wordbuf, len);
    if (listsize==count+1) {
      list = realloc(list, (listsize+grow)*sizeof(char*));
      listsize = listsize+grow;
    }
    list[count]=newword;
    count++;
  }
  for (i=0;i<=count-1;i++) {
    stringrev(list[i]);
  }
  qsort((void *)list, (size_t)count, sizeof(char*), pstrcmp);
  for (i=0;i<=count-1;i++) {
    stringrev(list[i]);
  }
  for (i=0;i<=count-1;i++) {
    fprintf(out, "%s\n", list[i]);
  }
}

RHYME_JAVA_RHYME_JAVA_RHYME_JAVA_RHYME_JAVA_RHYME_JAVA_RHYME_JAVA
import java.io.*;
import java.util.*;

public class Rhyme {

  public static void main(String args[]) throws IOException {
    String ifile = args[0];
    FileInputStream istream = new FileInputStream(ifile);
    InputStreamReader iread = new InputStreamReader(istream);
    BufferedReader r = new BufferedReader(iread);
    String word;
    Vector words = new Vector(5000, 5000);
    while((word = r.readLine()) != null) 
      words.addElement(word);
    r.close();
    Rhyme.reverseWords(words);
    Rhyme.sort(words);
    Rhyme.reverseWords(words);
    String ofile = args[1];
    FileOutputStream ostream = new FileOutputStream(ofile);
    OutputStreamWriter owrite = new OutputStreamWriter(ostream);
    BufferedWriter w = new BufferedWriter(owrite);
    for (int i = 0; i < words.size(); i++) {
      w.write((String) words.elementAt(i));
      w.newLine();
    }
    w.flush();
    w.close();
  }

  public static void reverseWords(Vector a) {
    for (int i = 0; i < a.size(); i++) 
      a.setElementAt((new String ((new StringBuffer ((String) a.elementAt(i))).reverse())), i);
  }
  // adapted from a quicksort by Gosling
  public static void sort(Vector a, int lo0, int hi0) {
    int lo = lo0;
    int hi = hi0;
    if (lo >= hi) {
      return;
    }
    String mid = (String) a.elementAt((lo + hi) / 2);
    while (lo < hi) {
      while (lo<hi && ((String) a.elementAt(lo)).compareTo(mid) < 0) {
	lo++;
      }
      while (lo<hi && ((String) a.elementAt(hi)).compareTo(mid) > 0) {
	hi--;
      }
      if (lo < hi) {
	Object T = a.elementAt(lo);
	a.setElementAt(a.elementAt(hi), lo);
	a.setElementAt(T, hi);
      }
    }
    if (hi < lo) {
      int T = hi;
      hi = lo;
      lo = T;
    }
    sort(a, lo0, lo);
    sort(a, lo == lo0 ? lo+1 : lo, hi0);
  }
  
  public static void sort(Vector a) {
    sort(a, 0, a.size()-1);
  }
}

RHYME_LISP_RHYME_LISP_RHYME_LISP_RHYME_LISP_RHYME_LISP_RHYME_LISP
(defun rhyme (from to &aux dict)
  (declare (optimize (speed 3) (safety 0)))
     (with-open-file (in from :direction :input)
       (setq dict (loop for w = (read-line in nil nil)
                    until (not w) collect w)))
     (setq dict (mapc #'nreverse dict))
     (setq dict (sort dict #'string<))
     (setq dict (mapc #'nreverse dict))
     (with-open-file (out to :direction :output :if-exists :supersede)
       (dolist (x dict) (write-line x out))))

RHYME_PERL_RHYME_PERL_RHYME_PERL_RHYME_PERL_RHYME_PERL_RHYME_PERL
$out = pop(@ARGV);
$in = pop(@ARGV);
open(INFILE, $in);
while (<INFILE>) {
    chop;
    push @words, $_;
}
@words = map {pack "C*", (reverse (unpack "C*", $_))} @words;
@words = sort @words;
@words = map {pack "C*", (reverse (unpack "C*", $_))} @words;
open(OUTFILE, ">$out");
map {print (OUTFILE $_, "\n")} @words;
_________________________________ 
[3] Prime Number Search Benchmark:

PRIME_C_PRIME_C_PRIME_C_PRIME_C_PRIME_C_PRIME_C_PRIME_C_PRIME_C_PRIME_C
#include "math.h"
#include "stdio.h"
#include "limits.h"

main(int argc, char *argv[]) {
  int s, e;
  int count = 0;
  int i, stop, testdiv;
  char p[100];
  itoa(INT_MAX, p, 10);
  if ((strlen(argv[2])>strlen(p)) ||
      ((strlen(argv[2])==strlen(p)) && (strcmp(argv[2], p) > 0))) {
    printf("integer %s is beyond int max %d \n", argv[2], INT_MAX);
    return 1;
  }
  s = atoi(argv[1]); /* 0 */
  e = atoi(argv[2]); /* 200000 */
  if ((s <= 2) && (e >= 2)) {count = 1;} else {count = 0;};
  if ((s % 2) == 1) {i = s;} else {i = s+1;}
  for (i = i; i <= e; i = i+2) {
    stop = sqrt(i);
    count++;
    for (testdiv = 3; testdiv <= stop; testdiv = testdiv+2) {
      if (0 == i % testdiv) {
	count--;
	break;}
    }
  }
  printf ("\nprimes counted %d\n", count);
}

PRIME_JAVA_PRIME_JAVA_PRIME_JAVA_PRIME_JAVA_PRIME_JAVA_PRIME_JAVA
import java.math.*;

public class Prime {
  public static void int_range(String args[])
    {
      int s = Integer.parseInt(args[0]);
      int e = Integer.parseInt(args[1]);
      int count, stop, i;
      if ((s <= 2) && (e >= 2)) {count = 1;} else {count = 0;}
      if ((s % 2) == 1) {i = s;} else {i = s+1;}
      for (i = i; i <= e; i = i+2) {
	stop = (int) Math.sqrt(i);
	count++;
	for (int testdiv = 3; testdiv <= stop; testdiv = testdiv+2) {
	  if (0 == i % testdiv) {
	    count--;
	    break;}
	}
      }
      System.out.println ("primes counted " + count);
    }

  public static void bigint_range(String args[])
    {
      BigInteger s = new BigInteger(args[0]);
      BigInteger e = new BigInteger(args[1]);
      BigInteger big0 = new BigInteger("0");
      BigInteger big1 = new BigInteger("1");
      BigInteger big2 = new BigInteger("2");
      BigInteger big3 = new BigInteger("3");
      BigInteger stop, i, testdiv;
      int count;
      if ((s.compareTo(big2) <= 0) && (e.compareTo(big2) >= 0)) 
	{count = 1;} else {count = 0;}
      if ((s.mod(big2)).equals(big1)) {i = s;} else {i = s.add(big1);}
      for (i = i; i.compareTo(e) <= 0; i = i.add(big2)) {
	stop = Prime.intsqrt(i);
	count++;
	for (testdiv = big3; testdiv.compareTo(stop) <= 0; testdiv = testdiv.add(big2)) {
	  if (big0.equals(i.mod(testdiv))) {
	    count--;
	    break;}
	}
      }
      System.out.println ("primes counted " + count);
    }

  public static BigInteger intsqrt(BigInteger x)
    {
      BigInteger guess, newguess;
      BigInteger big1 = new BigInteger("1");
      BigInteger big2 = new BigInteger("2");
      guess = x;
      for(;;) {
	newguess=((guess.multiply(guess)).add(x)).divide(guess.multiply(big2));
	newguess=newguess.add(big1);
	if (guess.equals(newguess)) {
	  return(guess.subtract(big1));
	}
	else {
	  guess=newguess;
	}
      }
    }

  public static void main(String args[]) {
    // String p=String.valueOf(Integer.MAX_VALUE);
    String p=String.valueOf(1);
    if ((args[1].length()>p.length()) ||
	((args[1].length()==p.length()) && 
	 (args[1].compareTo(p) > 0))) {
      Prime.bigint_range(args);
    }
    else {
      Prime.int_range(args); 
    }
  }
}

PRIME_LISP_PRIME_LISP_PRIME_LISP_PRIME_LISP_PRIME_LISP_PRIME_LISP
(defun prime-count (s e)
  (declare (optimize (speed 3) (safety 0))
	   (integer s e))
  (macrolet ((search-template (typeint)
	       `(loop for n ,typeint from (if (oddp x) x (1+ x)) to y by 2
		    for stop ,typeint = (isqrt n)
		    with count ,typeint = (if (<= x 2 y) 1 0) ; to count 2
		    when (= n (loop for test-div ,typeint from 3 to stop by 2
				  when (zerop (mod n test-div)) do (return test-div)
				  finally (return n)))
		    do (incf count)
		    finally (print count))))
    (flet ((search-fixnum-range (x y) (search-template fixnum))
	   (search-bignum-range (x y) (search-template integer)))
      (if (> e most-positive-fixnum)
	  (search-bignum-range s e)
	(search-fixnum-range s e)))))

PRIME_PERL_PRIME_PERL_PRIME_PERL_PRIME_PERL_PRIME_PERL_PRIME_PERL
use Math::BigInt;
$end = pop(@ARGV);
$start = pop(@ARGV);

if (length($end)>8) { # greater than 8 characters assume not fixnum anymore
    primebig($start, $end);
}
else {
    primefix($start, $end);
}

sub primefix {
    use integer;
    my($s, $e) = @_;
    my($count, $i, $stop);
    if (($s <= 2) && ($e >= 2)) {$count = 1;} else {$count = 0;};
    if (($s % 2) == 1) {$i = $s;} else {$i = $s+1;}
    for ($i = $i; $i <= $e; $i = $i+2) {
	$stop = $i**0.5; #$stop = (sqrt $i);
	$count++;
      LINE:
	for ($testdiv = 3; $testdiv <= $stop; $testdiv = $testdiv+2) {
	    if (0 == $i % $testdiv) {
		$count--;
		last LINE;}
	}}
    print "\nprimes counted ", $count, "\n";
    no integer;
}

sub primebig {
    my($s, $e) = @_;
    my($count, $i, $stop, $three);
    $s = Math::BigInt->new($s);
    $e = Math::BigInt->new($e);
    $three = Math::BigInt->new("3");
    if (($s <= 2) && ($e >= 2)) {$count = 1;} else {$count = 0;};
    if (($s % 2) == 1) {$i = $s;} else {$i = $s+1;}
    for ($i = $i; $i <= $e; $i = $i+2) {
	$stop = intsqrt($i); 
	$count++;
      LINE:
	for ($testdiv = $three; $testdiv <= $stop; $testdiv = $testdiv+2) {
	    if (0 == $i % $testdiv) {
		$count--;
		last LINE;}
	}}
    print "\nprimes counted ", $count, "\n";
}

sub intsqrt {
    my($x) = @_;
    my($guess, $newguess);
    $guess = $x;
    for(;;) {
	$newguess = (1+($guess*$guess+$x)/(2*$guess));
	if ($guess==$newguess) {
	    return $guess-1;
	}
	else {
	    $guess = $newguess;
	}
    }
}

From: Ray Drew
Subject: Re: Benchmarks Franz ACL 3.0.1 vs. 4.3.2 (& C, Java, Perl) on Windows NT
Date: 
Message-ID: <01bd0580$3439d500$d4fd82c1@an212.du.pipex.com>
Is Franz ACL 3.0.1 really that much slower than 4.3.2?

-- 
Ray Drew
CIA MediaSystems
London
·····@cia-group.com

John Watton <···········@alcoa.com> wrote in article
<·············@alcoa.com>...
> Pnpoly area [1]               sec    rel
> -----------                   ---    ---
> C    | VC++ 4.0 (cl -Ox)     16.5    1.0
> Lisp | Franz ACL 4.3.2 [3]   25.6    1.6
> Lisp | Franz ACL 3.0.1      521.3   31.6
> 
> Strings and ascii file io benchmark
> Rhyming dictionary [4]     read string sort write total
> ------------------         ----  rev's ---- -----   sec  rel
>                                 ------              ---  ---
> C    | VC++ 4.0 (cl -Ox)                            1.6  1.0
> Lisp | Franz ACL 4.3.2     1.84  1.44  2.22  0.74   6.2  3.9
> Lisp | Franz ACL 3.0.1    30.10  1.60  5.35 19.60  56.6 35.4
From: Markku Laukkanen
Subject: Re: Benchmarks Franz ACL 3.0.1 vs. 4.3.2 (& C, Java, Perl) on Windows NT
Date: 
Message-ID: <34938D1A.AFED7D3E@research.nokia.com>
John Watton wrote:

> I hope some of you find my multilanguage benchmarks of interest. What

... SNIP

> Machine: Pentium 90 Mhz, 40 Meg RAM
> OS: Windows NT
> Note: If the tables look messy try a fixed width font.
>
> Double floating point benchmark
> Pnpoly area [1]               sec    rel
> -----------                   ---    ---
> C    | VC++ 4.0 (cl -Ox)     16.5    1.0
> Java | JDK 1.1.4 (JIT) [2]   20.2    1.2
> C    | VC++ 4.0 (cl)         23.5    1.4
> Lisp | Franz ACL 4.3.2 [3]   25.6    1.6
> Java | JDK 1.1.4 (-O)       106.9    6.5
> Lisp | Franz ACL 3.0.1      521.3   31.6
> Perl | Perl5.003           1007.0   61.0



Oh my God, it looks weird, reaaaalllly weird for ACL....
Your code (from the way how I looked it) should optimize everything...
So most of  the floating point operations should be non-boxing operations...
Are you sure, that you compiled the code when using ACL ?

Because the results doesn't make any sense otherwise.
It can't be, that some CL implementation can be so slow in floating point operations ....
 (Hopefully)

    PKY

(define-optimizer +
  #'(lambda (res-type  &rest args)
      (case (length args)
     (0 0)
     (1 (if (or (subtypep (type (car args))
     'number)
         (safety-zero))
     (form (car args))
   (list 'is-number-p (form (car args)))))
     (2 (optimize-arithmetic-2 '+ res-type (car args) (second args)
          'fix+ 'fixnum+ 'float+ 'twoop+))
     (t (more-than-2 '+ res-type args 'fix+ 'fixnum+ 'float+ 'twoop+)))))