This is the mail archive of the guile@sourceware.cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Making Guile slower?


Mikael Djurfeldt <mdj@mdj.nada.kth.se> writes:

> [I'm resending this message under a more proper subject line.  Also,
>  one additional thing: Note that we can't make some proper mix of
>  these two approaches---that would be totally confusing.  We have to
>  decide whether to always make these, sometimes unneccesary, tests for
>  nonimmediateness or to always give the programmer control over this.
> 
>  And, btw, a "fair" test is to find that worst-case situation which is
>  still a computation of reasonable use.  You have to find code in
>  Guile where this change matters.]

This is about as close to biased against using the nimp tests as you
can get: it sort of simulates repeatedly calling a big pile of if
statements where you do mod_count SCM_FOOP macros (in this case, I
used SCM_VECTORP), and one of those modifies the value.

#include <libguile.h>


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

double
time_thunk1(void (*thunk)(void *a), void *arg)
{
  clock_t start, end;
  double elapsed;
  start = clock();
  thunk(arg);
  end = clock();
  elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
  return elapsed;
}

int iterations = 1000000;
int mod_count = 10;

void
imp_test(void *arg)
{
  SCM foo = (SCM) arg;
  register int i;
  for(i = 0; i < iterations; i++) {
    if(SCM_NIMP(foo) && SCM_VECTORP(foo)) {
      if(!(i%mod_count)) {
        SCM_SETCDR(foo, SCM_MAKINUM(1));
      }
      
    }
  }
}      

void
no_imp_test(void *arg)
{
  SCM foo = (SCM) arg;
  register int i;
  for(i = 0; i < iterations; i++) {
    if(SCM_VECTORP(foo)) {
      if(!(i%mod_count)) {
        SCM_SETCDR(foo, SCM_MAKINUM(1));
      }
    }
  }
}      

int
main(int argc, char **argv)
{
  
  scm_cell foo;
  double res;
  if(argc >= 2)
    iterations = strtol(argv[1], NULL, 10);
  if(argc == 3)
    mod_count = strtol(argv[1], NULL, 10);
  foo.car = scm_tc7_vector;
  foo.cdr = SCM_MAKINUM(1);
  printf("With nimp check: %i iterations\n", iterations);
  res = time_thunk1(imp_test, &foo);
  printf("Time: %f\n", res);
  printf("Without nimp check: %i iterations\n", iterations);
  res = time_thunk1(no_imp_test, &foo);
  printf("Time: %f\n", res);
  return 0;
}

I also tried it malloc as the thing being done to the cell, instead of
just setting it to an inum, but I got some odd results. In fact, I got
overall odd results:

With nimp check: 1000000 iterations
Time: 0.010000
Without nimp check: 1000000 iterations
Time: 0.100000
[greg ~/devel/tests]$ ./imp 1000000 100
With nimp check: 1000000 iterations
Time: 0.010000
Without nimp check: 1000000 iterations
Time: 0.110000

Etc. So I thought it might be a cache thing, so I made a nonimp.c
file. Same results. So I thought that maybe SCM_VECTORP was too
complicated, so I tried SCM_CONSP:

With nimp check: 1000000 iterations
Time: 0.010000
Without nimp check: 1000000 iterations
Time: 0.130000

I thought maybe it was getting a hint that foo isn't changing, so I
added a SETCAR(foo, rand()); inside each loop, making sure that they
used the same seed value.

[greg ~/devel/tests]$ ./imp
With nimp check: 1000000 iterations
Time: 0.420000
Without nimp check: 1000000 iterations
Time: 0.460000

And so on. In any case, I think it's a pointless bit of pennypinching
to worry about one test in the vast pile of code that is guile,
particularly if it makes it less likely to introduce bugs.

-- 
Greg

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]