I realize that this might start a flame-war against either CLOS, or
DEFSTRUCT.
I am not to be held liable for any casualties inflicted in this flame
war...
My question is simple:
I'm trying to write some code that should meet some minimal efficiency
benchmarks, and I'm wondering what the differences are between a class
and a struct. I'm aware of classes' fancy slot accessors etc, and
generic functions etc. I'm more interested in the comparative memory
and speed of a "closs" vs a struct.
Thanks,
Adlai
On 7 maio, 23:44, Adlai <·········@gmail.com> wrote:
> I realize that this might start a flame-war against either CLOS, or
> DEFSTRUCT.
>
> I am not to be held liable for any casualties inflicted in this flame
> war...
>
> My question is simple:
>
> I'm trying to write some code that should meet some minimal efficiency
> benchmarks, and I'm wondering what the differences are between a class
> and a struct. I'm aware of classes' fancy slot accessors etc, and
> generic functions etc. I'm more interested in the comparative memory
> and speed of a "closs" vs a struct.
If you are concerned with speed, then structs are your friends, at
least in SBCL. Take a look here:
http://www.sbcl.org/manual/Slot-access.html#Slot-access
Make sure you are not making a premature optimization, though. You can
start using classes and get everything done and, when you finally get
everything working, then you optimize your code.
>
> Thanks,
> Adlai
Thank you Kenneth, Barry, and gugamilare for the prompt and
informative replies.
In a way, this IS a premature optimization. However, given what you've
all told me about the comparative overhead between structs (nearly
none) and "closses" (a fair amount), it seems as though this
optimization is comparable to using Lisp lists instead of defining a
linked list as a struct, and manually implementing the data structure
each time you want to use it.
In other words, I have a fixed data structure in mind, which I could
just as easily implement with a list (as my current prototype does),
but wanted my code to be a bit more readable than lots of cadar soup,
or its decepitvely readable although equally inscrutable cousin,
ordinal soup (first, second, third, etc).
Thanks again!
Adlai
On May 8, 7:49 am, Adlai <·········@gmail.com> wrote:
> Thank you Kenneth, Barry, and gugamilare for the prompt and
> informative replies.
>
> In a way, this IS a premature optimization. However, given what you've
> all told me about the comparative overhead between structs (nearly
> none) and "closses" (a fair amount), it seems as though this
> optimization is comparable to using Lisp lists instead of defining a
> linked list as a struct, and manually implementing the data structure
> each time you want to use it.
>
> In other words, I have a fixed data structure in mind, which I could
> just as easily implement with a list (as my current prototype does),
> but wanted my code to be a bit more readable than lots of cadar soup,
> or its decepitvely readable although equally inscrutable cousin,
> ordinal soup (first, second, third, etc).
>
> Thanks again!
You are welcome. BTW. Have you also noted that you can do things like
(defstruct (my-thing (:type list) :named) a s d)
?
Cheers
--
Marco
ELS 2009 www.european-lisp-symposium.org
> On May 8, 7:49 am, Adlai <·········@gmail.com> wrote:
>> Thank you Kenneth, Barry, and gugamilare for the prompt and
>> informative replies.
>>
>> In a way, this IS a premature optimization. However, given what you've
>> all told me about the comparative overhead between structs (nearly
>> none) and "closses" (a fair amount), it seems as though this
>> optimization is comparable to using Lisp lists instead of defining a
>> linked list as a struct, and manually implementing the data structure
>> each time you want to use it.
>>
>> In other words, I have a fixed data structure in mind, which I could
>> just as easily implement with a list (as my current prototype does),
>> but wanted my code to be a bit more readable than lots of cadar soup,
>> or its decepitvely readable although equally inscrutable cousin,
>> ordinal soup (first, second, third, etc).
Adlai, you ignorant slut. You just wasted the earnest time of a bunch of
Lisp gods by asking for help with efficiency when you wanted help with
readability.
>> Thanks again!
Oh, shut up. Hey, I want a tennis date with Anna Kournikova so how can I
get this lawn mower started?
kt
I'm sorry that some of you wasted your time answering my questions.
I did however learn quite a bit from the earnest answers that people
gave, and I'm still grateful to them, regardless of Ken's comment.
-Adlai
On 9 May, 06:40, Adlai <·········@gmail.com> wrote:
> I'm sorry that some of you wasted your time answering my questions.
>
> I did however learn quite a bit from the earnest answers that people
> gave, and I'm still grateful to them, regardless of Ken's comment.
Don't mind Kenny. He's just grumpy because he can't
get laid.
--
Become a human being through great effort to purge
yourself of your hatred and insanity.
Erik Naggum
Spiros Bousbouras wrote:
> On 9 May, 06:40, Adlai <·········@gmail.com> wrote:
>> I'm sorry that some of you wasted your time answering my questions.
>>
>> I did however learn quite a bit from the earnest answers that people
>> gave, and I'm still grateful to them, regardless of Ken's comment.
>
> Don't mind Kenny. He's just grumpy because he can't
> get laid.
Never a problem as long as your Mom is down on the corner.
On 9 May, 20:36, Kenneth Tilton <·········@gmail.com> wrote:
> Spiros Bousbouras wrote:
> > On 9 May, 06:40, Adlai <·········@gmail.com> wrote:
> >> I'm sorry that some of you wasted your time answering my questions.
>
> >> I did however learn quite a bit from the earnest answers that people
> >> gave, and I'm still grateful to them, regardless of Ken's comment.
>
> > Don't mind Kenny. He's just grumpy because he can't
> > get laid.
>
> Never a problem as long as your Mom is down on the corner.
You know Mom ?!?! Hmmm, makes me wonder if it's only a
coincidence that we both like Lisp.
--
Please [...] provide evidence that your brain damage was a
preexisting condition and was not caused by what you suggest.
Erik Naggum
Spiros Bousbouras wrote:
> On 9 May, 20:36, Kenneth Tilton <·········@gmail.com> wrote:
>> Spiros Bousbouras wrote:
>>> On 9 May, 06:40, Adlai <·········@gmail.com> wrote:
>>>> I'm sorry that some of you wasted your time answering my questions.
>>>> I did however learn quite a bit from the earnest answers that people
>>>> gave, and I'm still grateful to them, regardless of Ken's comment.
>>> Don't mind Kenny. He's just grumpy because he can't
>>> get laid.
>> Never a problem as long as your Mom is down on the corner.
>
> You know Mom ?!?! Hmmm, makes me wonder if it's only a
> coincidence that we both like Lisp.
I hope your Mom likes Lisp. I would not want to share a pronoun with you.
>
> --
> Please [...] provide evidence that your brain damage was a
> preexisting condition and was not caused by what you suggest.
> Erik Naggum
Do you actually write any Lisp, or do you just like hitching your wagon
to notable c.l.l savages in a desperate attempt to appear interesting?
Adlai wrote:
> I realize that this might start a flame-war against either CLOS, or
> DEFSTRUCT.
>
> I am not to be held liable for any casualties inflicted in this flame
> war...
>
>
> My question is simple:
>
> I'm trying to write some code that should meet some minimal efficiency
> benchmarks, and I'm wondering what the differences are between a class
> and a struct. I'm aware of classes' fancy slot accessors etc, and
> generic functions etc. I'm more interested in the comparative memory
> and speed of a "closs" vs a struct.
uh, those GFs are part of the speed thing. anyway...
If efficiency is an issue use defstruct. especially if you are going to
be generating/dumping many instances. GFs are often nicely optimized,
but instantiation is different.
Were efficiency not a concern you could go with clos just to have the
extra features around if you need them, but with efficiency as a concern
the default flips to using defstruct until a violently compelling reason
to use clos comes along (and I am not sure there are any cuz you can
always find some other way to do things in Lisp).
kt
ps. btw, it might be fun to use CLOS and see if it meets the "minimum
benchmark". But defstruct would be faster. k
In article
<····································@q2g2000vbr.googlegroups.com>,
Adlai <·········@gmail.com> wrote:
> I realize that this might start a flame-war against either CLOS, or
> DEFSTRUCT.
>
> I am not to be held liable for any casualties inflicted in this flame
> war...
>
>
> My question is simple:
>
> I'm trying to write some code that should meet some minimal efficiency
> benchmarks, and I'm wondering what the differences are between a class
> and a struct. I'm aware of classes' fancy slot accessors etc, and
> generic functions etc. I'm more interested in the comparative memory
> and speed of a "closs" vs a struct.
Structure accessors will typically be faster than CLOS accessors.
They're often open-coded into simple vector offsets. Take a look at the
macro expansion of a DEFSTRUCT.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Adlai <·········@gmail.com> writes:
> I realize that this might start a flame-war against either CLOS, or
> DEFSTRUCT.
>
> I am not to be held liable for any casualties inflicted in this flame
> war...
>
>
> My question is simple:
>
> I'm trying to write some code that should meet some minimal efficiency
> benchmarks, and I'm wondering what the differences are between a class
> and a struct. I'm aware of classes' fancy slot accessors etc, and
> generic functions etc. I'm more interested in the comparative memory
> and speed of a "closs" vs a struct.
It's implementation dependant.
Structures (not of type list or vector) could be implemented as CLOS objects AFAIK.
So the structure accessor functions could be as fast as (slot-value s 'slot).
For structures with small number of slots, a list could even be faster.
(aref s slot-index) = (memory-ref (+ s (* size-of-struct-slot slot-index) some-offset))
(cadr s) = (memory-ref (+ (memory-ref s) 1))
So if the multiplication is slower than a memory reference, using a list will be faster.
Since you should meet some minimal efficiency benchmarks, what you
should do is to abstract away the implementation details, so you can
change them later, possibly at run-time.
When you load the program, you can have a benchmark function that
would compare the four different implementations (defstruct (:type
list)) (defstruct (:type vector)) (defstruct) and (defclass), and
choose the fastest one for the current processor (recompiling /
optimizing the program at run-time). Or you can just do that at
compilation time, if you compile on the target machine.
--
__Pascal Bourguignon__
Pascal J. Bourguignon wrote:
> Adlai <·········@gmail.com> writes:
>
>> I realize that this might start a flame-war against either CLOS, or
>> DEFSTRUCT.
>>
>> I am not to be held liable for any casualties inflicted in this flame
>> war...
>>
>>
>> My question is simple:
>>
>> I'm trying to write some code that should meet some minimal efficiency
>> benchmarks, and I'm wondering what the differences are between a class
>> and a struct. I'm aware of classes' fancy slot accessors etc, and
>> generic functions etc. I'm more interested in the comparative memory
>> and speed of a "closs" vs a struct.
>
> It's implementation dependant.
>
> Structures (not of type list or vector) could be implemented as CLOS objects AFAIK.
Yes, and they could be implemented by using a FAX utility to send a PO
to a tombstone engraving company. ECR* left as an exercise.
<sigh> The next thing you know Lisps will be built on the Java VM...
PWUAHAHAHAHAHHAHA... sorry, I know that's too silly to be funny.
hth,kt
* Engraved character recognition.
In article <··············@galatea.local>,
···@informatimago.com (Pascal J. Bourguignon) wrote:
> Structures (not of type list or vector) could be implemented as CLOS objects
> AFAIK.
Sure, and conses could be implemented as CLOS objects or as closures,
like in some of the exercises in SICP.
But no reasonable implementation would do any of these things. I think
it's safe to say that on any non-toy Lisp implementation, structures
will be noticeably faster than CLOS objects.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Barry Margolin <······@alum.mit.edu> writes:
> In article <··············@galatea.local>,
> ···@informatimago.com (Pascal J. Bourguignon) wrote:
>
>> Structures (not of type list or vector) could be implemented as CLOS objects
>> AFAIK.
>
> Sure, and conses could be implemented as CLOS objects or as closures,
> like in some of the exercises in SICP.
>
> But no reasonable implementation would do any of these things. I think
> it's safe to say that on any non-toy Lisp implementation, structures
> will be noticeably faster than CLOS objects.
On any non-toy implementation, CLOS objects would be fast enough.
--
__Pascal Bourguignon__
In article <··············@galatea.local>,
···@informatimago.com (Pascal J. Bourguignon) wrote:
> Barry Margolin <······@alum.mit.edu> writes:
>
> > In article <··············@galatea.local>,
> > ···@informatimago.com (Pascal J. Bourguignon) wrote:
> >
> >> Structures (not of type list or vector) could be implemented as CLOS
> >> objects
> >> AFAIK.
> >
> > Sure, and conses could be implemented as CLOS objects or as closures,
> > like in some of the exercises in SICP.
> >
> > But no reasonable implementation would do any of these things. I think
> > it's safe to say that on any non-toy Lisp implementation, structures
> > will be noticeably faster than CLOS objects.
>
> On any non-toy implementation, CLOS objects would be fast enough.
The flexibility that CLOS provides has inherent costs. Perhaps there
are optimizations that allow it to get close to DEFSTRUCT speeds, but I
don't think it can ever catch up. DEFSTRUCT is simply much easier to
implement efficiently, because it has so few requirements.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Barry Margolin <······@alum.mit.edu> writes:
> In article <··············@galatea.local>,
> ···@informatimago.com (Pascal J. Bourguignon) wrote:
>
>> Barry Margolin <······@alum.mit.edu> writes:
>>
>> > In article <··············@galatea.local>,
>> > ···@informatimago.com (Pascal J. Bourguignon) wrote:
>> >
>> >> Structures (not of type list or vector) could be implemented as CLOS
>> >> objects
>> >> AFAIK.
>> >
>> > Sure, and conses could be implemented as CLOS objects or as closures,
>> > like in some of the exercises in SICP.
>> >
>> > But no reasonable implementation would do any of these things. I think
>> > it's safe to say that on any non-toy Lisp implementation, structures
>> > will be noticeably faster than CLOS objects.
>>
>> On any non-toy implementation, CLOS objects would be fast enough.
>
> The flexibility that CLOS provides has inherent costs. Perhaps there
> are optimizations that allow it to get close to DEFSTRUCT speeds, but I
> don't think it can ever catch up. DEFSTRUCT is simply much easier to
> implement efficiently, because it has so few requirements.
A CLOS structure wouldn't have the same meta-class as a normal CLOS
object. I assume that with a different meta-class we can improve
efficiency. But I'm not the Pascal with the full and detailed
knowledge of CLOS ;-)
--
__Pascal Bourguignon__
In article <··············@galatea.local>,
···@informatimago.com (Pascal J. Bourguignon) wrote:
> Barry Margolin <······@alum.mit.edu> writes:
>
> > In article <··············@galatea.local>,
> > ···@informatimago.com (Pascal J. Bourguignon) wrote:
> >
> >> Barry Margolin <······@alum.mit.edu> writes:
> >>
> >> > In article <··············@galatea.local>,
> >> > ···@informatimago.com (Pascal J. Bourguignon) wrote:
> >> >
> >> >> Structures (not of type list or vector) could be implemented as CLOS
> >> >> objects
> >> >> AFAIK.
> >> >
> >> > Sure, and conses could be implemented as CLOS objects or as closures,
> >> > like in some of the exercises in SICP.
> >> >
> >> > But no reasonable implementation would do any of these things. I think
> >> > it's safe to say that on any non-toy Lisp implementation, structures
> >> > will be noticeably faster than CLOS objects.
> >>
> >> On any non-toy implementation, CLOS objects would be fast enough.
> >
> > The flexibility that CLOS provides has inherent costs. Perhaps there
> > are optimizations that allow it to get close to DEFSTRUCT speeds, but I
> > don't think it can ever catch up. DEFSTRUCT is simply much easier to
> > implement efficiently, because it has so few requirements.
>
> A CLOS structure wouldn't have the same meta-class as a normal CLOS
> object. I assume that with a different meta-class we can improve
> efficiency. But I'm not the Pascal with the full and detailed
> knowledge of CLOS ;-)
Even then, much of this requires run-time dispatching -- you have to
look up the metaclass while executing. DEFSTRUCT can implement its
accessors as open-coded functions, with little or no type dispatching
overhead.
My point is that structures are so simple that I can't imagine anything
more efficient than structure accessors. So the best you could
potentially achieve is parity.
And what it sounds like you're talking about is some
implementation-dependent metaclass that uses internal features to
achieve this. If an implementation of DEFSTRUCT does this behind the
scenes, it's not really very interesting for this discussion. The OP
was asking about whether he should use DEFCLASS or DEFSTRUCT in his
application. Unless the structure metaclass were available to him, it's
irrelevant.
Another possibility is that you're suggesting that the answer is "Use
CLOS, but first define a metaclass that makes it as efficient as
DEFSTRUCT, by foregoing all the nice features that CLOS provides
(multiple dispatch, method combinations, etc.)." That seems pretty
silly, it's using CLOS just so you can say you are. If you want
something that quacks like a structure, use a structure.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Barry Margolin <······@alum.mit.edu> writes:
> In article <··············@galatea.local>,
> ···@informatimago.com (Pascal J. Bourguignon) wrote:
>
>> Barry Margolin <······@alum.mit.edu> writes:
>>
>> > In article <··············@galatea.local>,
>> > ···@informatimago.com (Pascal J. Bourguignon) wrote:
>> >
>> >> Barry Margolin <······@alum.mit.edu> writes:
>> >>
>> >> > In article <··············@galatea.local>,
>> >> > ···@informatimago.com (Pascal J. Bourguignon) wrote:
>> >> >
>> >> >> Structures (not of type list or vector) could be implemented as CLOS
>> >> >> objects
>> >> >> AFAIK.
>> >> >
>> >> > Sure, and conses could be implemented as CLOS objects or as closures,
>> >> > like in some of the exercises in SICP.
>> >> >
>> >> > But no reasonable implementation would do any of these things. I think
>> >> > it's safe to say that on any non-toy Lisp implementation, structures
>> >> > will be noticeably faster than CLOS objects.
>> >>
>> >> On any non-toy implementation, CLOS objects would be fast enough.
>> >
>> > The flexibility that CLOS provides has inherent costs. Perhaps there
>> > are optimizations that allow it to get close to DEFSTRUCT speeds, but I
>> > don't think it can ever catch up. DEFSTRUCT is simply much easier to
>> > implement efficiently, because it has so few requirements.
>>
>> A CLOS structure wouldn't have the same meta-class as a normal CLOS
>> object. I assume that with a different meta-class we can improve
>> efficiency. But I'm not the Pascal with the full and detailed
>> knowledge of CLOS ;-)
>
> Even then, much of this requires run-time dispatching -- you have to
> look up the metaclass while executing. DEFSTRUCT can implement its
> accessors as open-coded functions, with little or no type dispatching
> overhead.
>
> My point is that structures are so simple that I can't imagine anything
> more efficient than structure accessors. So the best you could
> potentially achieve is parity.
>
> And what it sounds like you're talking about is some
> implementation-dependent metaclass that uses internal features to
> achieve this. If an implementation of DEFSTRUCT does this behind the
> scenes, it's not really very interesting for this discussion. The OP
> was asking about whether he should use DEFCLASS or DEFSTRUCT in his
> application. Unless the structure metaclass were available to him, it's
> irrelevant.
>
> Another possibility is that you're suggesting that the answer is "Use
> CLOS, but first define a metaclass that makes it as efficient as
> DEFSTRUCT, by foregoing all the nice features that CLOS provides
> (multiple dispatch, method combinations, etc.)." That seems pretty
> silly, it's using CLOS just so you can say you are. If you want
> something that quacks like a structure, use a structure.
No, this is not what I had in head.
For the OP, what I mean is that there are four easy ways to implement
a "structure" in CL:
- lists as structures (defstruct (:type list)),
- vectors as structures (defstruct (:type vector)),
- normal structures (defstruct),
- CLOS objects.
Barry we're having actually a discussion about what is a toy
implementation. I'd imagine that an implementation could use CLOS
objects (with a special "system" metaclass) to implement all the lisp
objects, including normal structures. It would make for a simple
implementation, and if running on an object virtual machine
(eg. Smalltalk), would be as fast than vectors.
But given that I know of no such implementation, it's still a thinking
experiment and therefore, I'll grant you that they'd be toy
implementations.
So it remains three ways to implement fast structures:
- lists as structures (defstruct (:type list)),
- vectors as structures (defstruct (:type vector)),
- normal structures (defstruct),
The last twos are probably identical. On some processor, and for
small structures, the first might be faster.
Anyways, my point to the OP is that he should write his own
"structure" defining macro, so he can change the kind of structure or
CLOS objects used once a benchmark in real situation is done, at the
latest possible time.
--
__Pascal Bourguignon__
In article <··············@galatea.local>,
···@informatimago.com (Pascal J. Bourguignon) wrote:
> Barry we're having actually a discussion about what is a toy
> implementation. I'd imagine that an implementation could use CLOS
> objects (with a special "system" metaclass) to implement all the lisp
> objects, including normal structures. It would make for a simple
> implementation, and if running on an object virtual machine
> (eg. Smalltalk), would be as fast than vectors.
What I meant by "toy" was a simple implementation that doesn't have lots
of optimizations. Structure accessors wouldn't be open-coded, and CLOS
wouldn't cache method dispatching; perhaps it doesn't even compile to
machine code or byte codes for a VM. These are implementations you see
in academic exercises, or version 0.x of a new dialect. As a result,
both CLOS and DEFSTRUCT would be slow, although I expect CLOS would be
significantly slower.
But anyone concerned with performance would not even consider such an
application as a possibility.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Pascal J. Bourguignon wrote:
> Barry Margolin <······@alum.mit.edu> writes:
>
>> In article <··············@galatea.local>,
>> ···@informatimago.com (Pascal J. Bourguignon) wrote:
>>
>>> Barry Margolin <······@alum.mit.edu> writes:
>>>
>>>> In article <··············@galatea.local>,
>>>> ···@informatimago.com (Pascal J. Bourguignon) wrote:
>>>>
>>>>> Structures (not of type list or vector) could be implemented as CLOS
>>>>> objects
>>>>> AFAIK.
>>>> Sure, and conses could be implemented as CLOS objects or as closures,
>>>> like in some of the exercises in SICP.
>>>>
>>>> But no reasonable implementation would do any of these things. I think
>>>> it's safe to say that on any non-toy Lisp implementation, structures
>>>> will be noticeably faster than CLOS objects.
>>> On any non-toy implementation, CLOS objects would be fast enough.
>> The flexibility that CLOS provides has inherent costs. Perhaps there
>> are optimizations that allow it to get close to DEFSTRUCT speeds, but I
>> don't think it can ever catch up. DEFSTRUCT is simply much easier to
>> implement efficiently, because it has so few requirements.
>
> A CLOS structure wouldn't have the same meta-class as a normal CLOS
> object. I assume that with a different meta-class we can improve
> efficiency.
There are actually a number of implementation-dependent extensions in
different CLOS implementations to get closer to the speed of structs.
The main ones are: restricting inheritance to single-inheritance, which
makes it easier to assign fixed allocations to particular slots; making
slots 'mandatory', such that they cannot be unbound anymore, which
removes the extra check for unbound slots on each access; and finally,
restricting class redefinition, such that slot allocations don't change
at runtime.
I am convinced that it should be possible to be on par with structs even
without having any of these restrictions, but this would require a
serious effort. (It would basically be based on some dynamic compilation
techniques that you can find in the Java world...)
Pascal
--
ELS'09: http://www.european-lisp-symposium.org/
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/