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?


Marius Vollmer <mvo@zagadka.ping.de> writes:

<snip>

> Yes, I did read it.  But I should also say that I'm patently confused
> about the many Gregs on this list who are doing significant thinks.
> Thus, the "you" in this article is addressed at the union of all
> Gregs.

Well, I'm the Greg that deserves all the blame and much of the credit
for the pervasive changes to Guile in the last week.

> > "Greg Harvey" wrote:
> > 
> > I'll state it again: given the rarity of places in the code where
> > nimp is not used in close proximity to the other predicate, as well
> > as the fact that the nimp test should not be compiled to code any
> > more complex than 2 simple instructions, on a value that's about to
> > be used anyway, there is no way it's going to cause a significant
> > performance degradation.
> 
> What worries me is that you are so sure about your reasoning without
> hard evidence.  One of these simple instructions is a branch which is
> *the* instruction for throwing modern CPUs off track.  Your own tests
> have shown that the resulting performance of a piece of code can be
> very counter-intuitive and given that I trust Aubrey very much when it
> comes to bumming code to the edge, I am hard pressed to accept your
> reasoning just because you say "it's cool, son".

There is *absolutely* no difference in the assembly code that GCC 2.95.2
generates (with -O, -O2, -O6) on my PIII processor for:

#include "ports.h"
#include "pairs.h"
#include "tags.h"

int main(char *argv, int argc)
{
  SCM x = SCM_EOL;
  /* remember SCM_CONSP and SCM_OPENP below have the 
     SCM_NIMP test folded into them */
  int f = (SCM_CONSP(x) || SCM_OPENP(x));
  return f;
}

vs.

#include "ports.h"
#include "pairs.h"
#include "tags.h"

#define SCM_OPN		(1L<<16) /* Is the port open? */

#define SCM_SLOPPY_OPENP(x) (SCM_OPN & SCM_CAR(x))
#define SCM_SLOPPY_CONSP(x) (!(1 & SCM_CAR(x)))

int main(char *argv, int argc)
{
  SCM x = SCM_EOL;
  int f = (SCM_NIMP(x) && (SCM_SLOPPY_CONSP(x) || SCM_SLOPPY_OPENP(x)));
  return f;
}

You guys need more faith in optimizers.  That's not to say that there
might be some obscure places in the code where the generated assembly
won't differ, but they will be rare, and are easy to handle using
whatever SCM_SLOPPY_FOOPs we need to introduce.

<snip>

> agree much more than we disagree.  Your plan of introducing sloppy
> variants is exactly the Right Thing.

But only as they are necessary.  Trust in your compiler.

> But I'm worried that you are not aproaching the thing with the
> appropriate conservatism.  Your change might have affected the most
> time critical code of all in Guile, it could maybe have slowed down
> looking up ilocs significantly.

And if someone posts evidence that that is the case, then I will get
whatever performance I lost back.  I promise.

> In my view, the conservative thing would have been to alias the
> existing macros to names including SLOPPY, to introduce STRICT
> variants of these macros (that include the SCM_NIMP test) and then
> gradually change the NIMP && SLOPPY combos to STRICT, with amble
> public testing on the way, and backward compatability.  When no
> references to the old names (without SLOPPY or STRICT) are present,
> you could then rename the STRICT variants to the old, simple names.
> The resulting machine code of Guile would stay unaffected all the
> time, but the clarity of the source would be improved.

But part of the point is that it can be the optimizers job to deal with
the SLOPPY stuff.  It's an optimization detail that we should leave
out of the source whenever possible.

> You are going to do that, and that is a good thing, but I still don't
> like the handwaving about how two instructions don't matter within the
> type checking code, and the temporary distortion of known-good code.

It's the *same* code that gets generated nearly everywhere.  And yes,
I'm aware that *nearly* is a significant qualification, but we have an
obvious way to handle those remaining places if they turn out to be a
performance problem.

> Anyway, although you might not believe it, I'm still having a lot of
> fun with Guile, and I'm very happy that you all do this huge amount of
> work.  Really.  I may sound like I have some authority, which in fact
> I don't have, so you can simply ignore me if you like.

It's not wise to ignore your users (and even less wise to ignore
co-developers).  But I'd love it if people's concerns were supported by
real evidence, instead of just "maybes".

We all agree Guile's performance is hard to figure out.  Everyone has
heard the anecdote about just re-ordering the functions in eval.c
causing a 30% performance degradation.  I've made substantial software
engineering improvements to the guile source artifact that make it far
more readable, less intimidating to new users, more robust and
forgiving. We now have initial support for docstrings and I added
docstrings for a ton of primitives.

My improvements are real and definite.  People *supposing* there might
be a [neglible, even!] slow down w/o any evidence are out of line.
There are undoubtedly places where the generated code is different. It's
likely that those few extra instructions will make absolutely zero
performance difference.  When that's not the case, there is an easy plan 
to get the performance back.  

It'd be far more productive for people worried about performance to
produce useful benchmarks to test the performance, or find places in the
code where the optimizer isn't going to be smart enough to remove the
extra tests and suggest patches for those areas if they are in tight
loops.

Greg Badros

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