libera/commonlisp - IRC Chatlog
Search
18:06:15
alcor
2 days ago we had a discussion about using keywords instead of symbols in (LOOP …) e.g. (LOOP :WITH x = … :FOR y :IN …). Now I have a silly OCDish question here. Wouldn't the same argument apply to the "=" symbol? I mean technically if we REALLY wanted to apply that logic to its maximum, shouldn't we write (LOOP :WITH x := … :FOR y :IN …) ?
18:11:08
alcor
I don't want to make a mountain out of molehill, but I'm tempted to do it for entirely um, aesthetic reasons. := (aka the Walrus) looks like a Pascalish/Wirthian assignment operator (I know it totally isn't comparable in a CL context) but it looks acceptable + avoids polluting the package namespace.
18:11:25
bike
= is in the CL package, so if you're using the CL package you're not doing anything to your own by writing it, unlike how it is with WITH or FOR
18:13:14
alcor
bike: Right, that will only make a difference if you don't have a (:use :cl) in your defpackage.
18:13:25
mrcom
What's that quote? "A foolish consistency is the hobgoblin of little minds." Never did figure out if little minds were supposed to be foolishly consistent, or were getting bothered by other people being foolishly consistent. So I settled on doing both,\
18:20:51
mrcom
CL doesn't have raging arguments about tabs-vs-spaces, so all that latent energy has to go into something else.
19:05:52
mrcom
What you're trying to microbenchmark is dispatch time? The framework is a bit complex for that, IMHO. You're building an enormous tree of test data (I think?), so that's going to mix into the results.
19:06:23
paulapatience
skin: I would add a little nuance to your conclusion. If you are looking for maximum performance, you probably won't use a slower implementation than SBCL, and then you demonstrated that classes are slower than structs are slower than etypecase on it.
19:07:05
mrcom
It's also difficult for me to reason about exactly how much of what is happening. Not enough coffee, perhaps.
19:08:38
mrcom
And ECL and ABCL are doing huge amounts; that's probably where most of the elapsed time is going.
19:11:24
mrcom
A simple "(loop :for i :from 0 :below 1000000 :sum (foo))" would be much clearer to reason about, and much less confounded by other things.
19:12:48
mrcom
Yes, that's probably a good idea for double-checking what you're actually testing. I wouldn't do it during the actual measurement run, though. Even in stat mode would be one more confounder.
19:15:33
pranav
ECL's structs can be faster I think. One would need to test it with SI:STRUCTURE-REF and SI:MAKE-STRUCTURE as used in the following. https://github.com/bohonghuang/maparray/blob/master/maparray.lisp#L36
19:16:23
mrcom
I'd also like to see some variations, to judge how the measurements might actually apply. For example, does it matter no-subclassed vs. subclassed 5-deep? 1 slot vs. 10?
19:19:54
younder
I'm more wondering as I could 'patch' them into SBCL as a library that would then be called at the REPL's discretion
19:20:47
mrcom
You're much better off with sbcl's perf tools. It's aware of the idiosyncracies in stack useage, function dispatch, etc.
19:22:27
mrcom
It's got two types; one is deterministic, counting each time a function is called, and the other is statistical, sampling. It's aware of call stacks and chains. Still pretty obscure, sometimes.
19:26:47
younder
Perf is different as it records things like cache misses and branch mis-predictions which matter if you are tuning the compiler
20:06:08
skin
The memory subsystem is an important part of it, but I think the point still stands. Different implementations use the memory subsystem more or less for dispatch evaluation, and that showed up in the numbers.
20:07:21
skin
I mean, I didn't tell those implementations to do all that consing. The consing I did myself to build the tree was not measured; only running the recursive evaluate methods were measured. So I think it's about as good a test as `(loop for 1 to 1000 do ...)`. I think the results are imperfect, but still mean a lot.
20:22:56
scymtym
in at least some implementations, calling a generic function for the first time after its definition or after some change to its methods may invoke the compiler and thus add one-time consing and runtime
20:46:34
aeth
On the earlier discussion, yes, I use := in my LOOPs, not just :for, etc. That is the fully consistent way to use keywords in LOOP.
21:38:50
skin
I rescind my opinion. Structs are faster. The blog post is updated. https://blog.djhaskin.com/blog/benchmarking-the-clos/
21:48:06
zyd
Seems to me that structs vs classes comes down to the use case of them rather than an absolute "just use classes" or "always use structs". If you intend to make say, a bullet hell game, might make sense to represent bullets as structs, right? Especially because that kind of data will likely be just numbers. If I'm thinking about it right.
22:13:52
skin
If class is really were faster then maybe we should just use them because they're also more fully featured and there would be no tradeoffs
22:18:41
younder
In SBCL using struc and ecase is twice as fast., but that doesn't matter because all the other implementations are slow.
22:21:57
aeth
Generally speaking, structs have a different purpose. This is mostly when putting a :type in a slot to give type information to the compiler, which can compound beyond simple access for numbers (remove generic arithmetic) and specialized (with :element-type) arrays of numbers (which have the arithmetic benefits mixed with the removal of bounds checking if you provide the length in the type)
22:23:04
younder
My conclusion is that of the free Lisp's only SBCL and CCL have good performance. Compared with the commercial compilers CLOS is not heavily optimized, but structs are in SBCL. That is why structs are twice as fast. Of course in most cases the uses of class are quite different.
22:26:39
younder
LW didn't make it into this test. It is slower than SBCL for calculations, but CLOS should perform better.
22:37:01
aeth
younder: Whether or not structs or standard-objects are more optimized isn't particularly relevant because structs by their nature _can_ be optimized more.
22:39:52
younder
A lot of the optimizations can only be performed at link time when you know all the virtual methods and that methods will not be overloaded., but in SBCL one rarely compiles to a executable. This is mostly done in the commercial Lisps.
22:43:23
aeth
You cannot know that things won't be overloaded more or recompiled or whatever in general. Although you can probably do so if you compile everything at once, yes, if you check for the presence of problematic calls and optimize only in their absence.
23:28:06
fe[nl]ix
jackdaniel: so the only accessors that work across all implementations' CAS are CAR, CDR, SVREF and special vars
23:47:14
jasom
younder: I compile to an executable all the time; the two reasons being ease of delivery and decreased startup time.