Smalltalk>>at:, vs direct reference.

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Smalltalk>>at:, vs direct reference.

Esteban A. Maringolo
Hi all:

How much performance do you lose when using Smalltalk at: #ClassName
instead of direct referencing the class?

Small suggestion to OA*:
It would help a lot if you could load a package (from .pac or STS),
and instead of ignoring the methods that don't compile (because of a
reference to an non-existent global/class, for example), the system
loads them anyway, and flag it somehow.
And thereafter when you load the missing global, the non-compiled
method re-compiles itself and fixes the missing reference(s).

It will help a lot when porting something that uses a diferent
packaging strategy (such as VW parcels/bundles), allowing you to
load everything, and then repackage properly.

*I recall this was requested during the D6 beta phase

Regards,

--
Esteban.


Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk>>at:, vs direct reference.

Esteban A. Maringolo
Esteban A. Maringolo escribió:
> Hi all:
>
> How much performance do you lose when using Smalltalk at: #ClassName
> instead of direct referencing the class?

Answering myself... Smalltalk at: is about 10% slower than direct class
reference.

Regards,

--
Esteban.


Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk>>at:, vs direct reference.

Chris Uppal-3
Esteban,

> > How much performance do you lose when using Smalltalk at: #ClassName
> > instead of direct referencing the class?
>
> Answering myself... Smalltalk at: is about 10% slower than direct class
> reference.

That doesn't sound right.  On this 1.5 GHz machine, evaluating:
    Cursor
takes around 4 nanoseconds; evaluating:
    Smalltalk at: #Cursor
takes around 1 microsecond.  It's around 250 times slower ;-)

Of course, that is meaningless without knowing what the evaluation is part of.

In practise it would be silly to put:
    Smalltalk at: #Cursor
into the middle of a loop so tight that 1 usec made a difference to the overall
execution speed  -- for exactly the same reason as it would be silly to put
    anArray at: someFixedNumber
into such a loop.  You'd naturally pull the constant-valued expression out of
the loop, and so the difference between:
    Cursor
and:
    Smalltalk at: #Cursor
would be irrelevant.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk>>at:, vs direct reference.

Chris Uppal-3
In reply to this post by Esteban A. Maringolo
Esteban,

> It would help a lot if you could load a package (from .pac or STS),
> and instead of ignoring the methods that don't compile (because of a
> reference to an non-existent global/class, for example), the system
> loads them anyway, and flag it somehow.
> And thereafter when you load the missing global, the non-compiled
> method re-compiles itself and fixes the missing reference(s).

This is something that I'm starting to want too, although in may case what I
want is the ability to define methods /of/ classes which don't exist -- which
would have a very similar implementation, I'd imagine.

For me it's a packaging issue.  I have quite often recently found myself in a
position where some package adds some feature to some other package.  Logically
that feature should /also/ be added to some third package, but that would
create an undesirable dependency.  Alternatively, I could split the problematic
package into two, which would remove the unwanted part of the dependency, but
at the cost of fragmenting what /should/ be a coherent whole.

Here's an example from my published code.  I have a package 'CU Stream
Extensions' which adds things like #nextFLOAT and #nextQWORD (plus big-endian
equivalents) to the standard Streams -- that is one coherent unit of
functionality.  I also have a package 'CU Abstract Streams' which provides a
base from which to derive custom stream implementations -- also one coherent
unit of functionality.  But, and this is the problem, where does the abstract
equivalent of #nextQWORD go ?   If I put it into 'CU Abstract Streams' then I'm
scrambling the package boundaries.  If I put it into 'CU Stream Extensions'
then I'm creating an unwanted dependency.  If I split 'CU Stream Extensions'
then -- at best -- that's inconvenient.

That is only one example, I have several more.

I don't know whether the feature would be useful enough to justify the extra
complication and development time, that's for OA to decide, but I /do/ know
that if it did exist then I'd have used it several times already.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk>>at:, vs direct reference.

Esteban A. Maringolo
In reply to this post by Chris Uppal-3
Chris Uppal escribió:

> Esteban,
>
>>> How much performance do you lose when using Smalltalk at: #ClassName
>>> instead of direct referencing the class?
>> Answering myself... Smalltalk at: is about 10% slower than direct class
>> reference.
>
> That doesn't sound right.  On this 1.5 GHz machine, evaluating:
>     Cursor
> takes around 4 nanoseconds; evaluating:
>     Smalltalk at: #Cursor
> takes around 1 microsecond.  It's around 250 times slower ;-)

Uhm... it's odd.
I ran the following expressions on a 1.7GHz centrino and obtained the
results in comments:

Time microsecondsToRun: [
        1000 timesRepeat: [SwazooURI]] "30 µs"

Time microsecondsToRun: [
        1000 timesRepeat: [Smalltalk at: #SwazooURI]]. "1131 µs"

Time microsecondsToRun: [
        1000 timesRepeat: [SwazooURI fromString: '/']] "24569 µs"

Time microsecondsToRun: [
        1000 timesRepeat: [(Smalltalk at: #SwazooURI) fromString: '/']] "32511 µs"

Time microsecondsToRun: [
        10000 timesRepeat: [SwazooURI fromString: '/']] "268055 µs"

Time microsecondsToRun: [
        10000 timesRepeat: [(Smalltalk at: #SwazooURI) fromString: '/'] ]
"304880 µs"

Then if you add repetitions of 10^5 or more, the results of indirect
access are about 25% slower than direct reference.

Best regards,

ps: how do you measure nanoseconds?

--
Esteban.


Reply | Threaded
Open this post in threaded view
|

Re: Smalltalk>>at:, vs direct reference.

Chris Uppal-3
Esteban,

[me:]

> > [...]  On this 1.5 GHz machine, evaluating:
> >     Cursor
> > takes around 4 nanoseconds; evaluating:
> >     Smalltalk at: #Cursor
> > takes around 1 microsecond.  It's around 250 times slower ;-)
>
> Uhm... it's odd.
> I ran the following expressions on a 1.7GHz centrino and obtained the
> results in comments:
>
> Time microsecondsToRun: [
> 1000 timesRepeat: [SwazooURI]] "30 µs"

OK, around 3 nanoseconds each (or less since some of that will be loop
overhead).


> Time microsecondsToRun: [
> 1000 timesRepeat: [Smalltalk at: #SwazooURI]]. "1131 µs"

Around 1 usec each.  Pretty similar to my figures.


> Time microsecondsToRun: [
> 1000 timesRepeat: [SwazooURI fromString: '/']] "24569 µs"

So the fromString: but is taking the bulk of the time -- around 25 usecs each.


> Time microsecondsToRun: [
> 1000 timesRepeat: [(Smalltalk at: #SwazooURI) fromString: '/']] "32511 µs"


But that is odd.  You'd expect it to take around 26 usecs each time, but it's
taking rather longer than that.  If it /was/ behaving as expected then it this
case would be about 5% slower, but it's actually more like 30%.  I don't know
why.

I tried the same thing on my machine (actually slightly different because my
version of Swazoo doesn't have the class-side method).  I get:

    [SwazooURI new  parseURI: '/']
        26.5 usecs

    [(Smalltalk at: #SwazooURI) new  parseURI: '/']
        29.2 usecs

    [Smalltalk at: #SwazooURI]
        1.36 (+/-0.05) usecs

    [SwazooURI]
        4.0 (+/-0.3) nanosecs

So I'm seeing the same effect but not nearly as extreme (10% slower for that
expression when the raw figures would lead me to expect 5%).   I took a look at
the bytecode for the various blocks, but it seems there's no difference
between:
    [SwazooURI new  parseURI: '/']
    [(Smalltalk at: #SwazooURI) new  parseURI: '/']

which isn't just a parallel of the difference between:
    [Smalltalk at: #SwazooURI]
    [SwazooURI]

Possibly there is an optimisation in the VM for methods which return a
constant, and that is available only for the last form, so it shows up as being
unrepresentatively cheap -- but I haven't been able to find any real evidence
to support that.

> ps: how do you measure nanoseconds?

With the little timing framework I have used for years and years.  It's on my
website: 'CU Expression Timer' under 'Experiments'.

    -- chris