Cog Primitive Performance

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

Re: Cog Primitive Performance

Bert Freudenberg
 
On Tue, Apr 18, 2017 at 9:04 PM, Eliot Miranda <[hidden email]> wrote:
 
Hi Bert, Hi All,

On Tue, Apr 18, 2017 at 10:55 AM, Bert Freudenberg <[hidden email]> wrote:
 
On Tue, Apr 18, 2017 at 6:09 PM, Nicolas Cellier <[hidden email]> wrote:

Concerning the specific case of hashMultiply, since it's just an imul and a bitAnd, the primitive should be inlined by the VM just like other basic arithmetic operations IMO.
So the remarks of Andres makes sense, even if we can't generalize to other Misc primitives.

Yes, code optimized by Sista should be pretty much as fast as a primitive, so we could hopefully get rid of many primitives that are just there to improve performance.

The problem to think through carefully is the impact on the ContextInterpreter, StackInterpreter and SqueakJS VMs.  I have a gut feeling that the right thing to do is to keep the primitives for the benefit of these VMs and to have Cog ignore them. 

Ah, good point.
 
That implies that the primitive failure code can be what one would like to execute and have Sista optimize.  That means that translated primitives are an obstacle.

Agreed. 
 
Rewriting the translated primitives as conventional primitives in MiscPrimitivePlugin and not including the MiscPrimitivePlugin in Cog (JIT) VMs (o including one which provides no primitives) would allow the primitive failure code in the various Collection methods to be written optimally, allow the interpreter VMs to keep using the primitives, allow Cog VMs to ignore the primitives easily, and would allow putting the primitives closer to the receivers.  Redirecting through to the class side wastes cycles.

Yep :)

- Bert -
 
Reply | Threaded
Open this post in threaded view
|

Numbered primitives (was: Cog Primitive Performance)

David T. Lewis
In reply to this post by Clément Béra
 
On Tue, Apr 18, 2017 at 09:57:54AM -0700, Cl??ment Bera wrote:
>

<snip>

> For each primitive, we need to evaluate the performance with and without
> the primitive. In each case, we either move the primitive to numbered
> primitive or we just use normal Smalltalk code.

Please no more numbered primitives. We should be eliminating numbered primitives,
not adding more.

The only justification I can see for a numbered primitive today is to identify
it as one of the small number of primitives that absolutely must be available
when porting the VM to a new platform, especially if that platform may not
easily support the loading of functions by name. Aside from that, we should
insist that /all/ primitives be named primitives.

Dave
Reply | Threaded
Open this post in threaded view
|

Re: Cog Primitive Performance

Ben Coman
In reply to this post by Bert Freudenberg
 


On Wed, Apr 19, 2017 at 3:42 AM, Bert Freudenberg <[hidden email]> wrote:
 
On Tue, Apr 18, 2017 at 9:04 PM, Eliot Miranda <[hidden email]> wrote:
 
Hi Bert, Hi All,

On Tue, Apr 18, 2017 at 10:55 AM, Bert Freudenberg <[hidden email]> wrote:
 
On Tue, Apr 18, 2017 at 6:09 PM, Nicolas Cellier <[hidden email]> wrote:

Concerning the specific case of hashMultiply, since it's just an imul and a bitAnd, the primitive should be inlined by the VM just like other basic arithmetic operations IMO.
So the remarks of Andres makes sense, even if we can't generalize to other Misc primitives.

Yes, code optimized by Sista should be pretty much as fast as a primitive, so we could hopefully get rid of many primitives that are just there to improve performance.

The problem to think through carefully is the impact on the ContextInterpreter, StackInterpreter and SqueakJS VMs.  I have a gut feeling that the right thing to do is to keep the primitives for the benefit of these VMs and to have Cog ignore them. 

Ah, good point.

By ignore, do you mean excluded from the built binary by conditional compilation, to minimise VM size for embedded platforms? 

cheers -ben 
 
 
That implies that the primitive failure code can be what one would like to execute and have Sista optimize.  That means that translated primitives are an obstacle.

Agreed. 
 
Rewriting the translated primitives as conventional primitives in MiscPrimitivePlugin and not including the MiscPrimitivePlugin in Cog (JIT) VMs (o including one which provides no primitives) would allow the primitive failure code in the various Collection methods to be written optimally, allow the interpreter VMs to keep using the primitives, allow Cog VMs to ignore the primitives easily, and would allow putting the primitives closer to the receivers.  Redirecting through to the class side wastes cycles.

Yep :)

- Bert -
 


Reply | Threaded
Open this post in threaded view
|

Re: Cog Primitive Performance

David T. Lewis
 
On Wed, Apr 19, 2017 at 07:51:06AM +0800, Ben Coman wrote:

>  
> On Wed, Apr 19, 2017 at 3:42 AM, Bert Freudenberg <[hidden email]>
> wrote:
>
> >
> > On Tue, Apr 18, 2017 at 9:04 PM, Eliot Miranda <[hidden email]>
> > wrote:
> >
> >>
> >> Hi Bert, Hi All,
> >>
> >> On Tue, Apr 18, 2017 at 10:55 AM, Bert Freudenberg <[hidden email]>
> >> wrote:
> >>
> >>>
> >>> On Tue, Apr 18, 2017 at 6:09 PM, Nicolas Cellier <
> >>> [hidden email]> wrote:
> >>>
> >>>>
> >>>> Concerning the specific case of hashMultiply, since it's just an imul
> >>>> and a bitAnd, the primitive should be inlined by the VM just like other
> >>>> basic arithmetic operations IMO.
> >>>> So the remarks of Andres makes sense, even if we can't generalize to
> >>>> other Misc primitives.
> >>>>
> >>>
> >>> Yes, code optimized by Sista should be pretty much as fast as a
> >>> primitive, so we could hopefully get rid of many primitives that are just
> >>> there to improve performance.
> >>>
> >>
> >> The problem to think through carefully is the impact on the
> >> ContextInterpreter, StackInterpreter and SqueakJS VMs.  I have a gut
> >> feeling that the right thing to do is to keep the primitives for the
> >> benefit of these VMs and to have Cog ignore them.
> >>
> >
> > Ah, good point.
> >
>
> By ignore, do you mean excluded from the built binary by conditional
> compilation, to minimise VM size for embedded platforms?
>

No, the primitives continue to exist and are invoked if and only if the
image wants to use them. The image can be smart enough to know if it wants
to use the primitives. And an older image that is not aware of this discussion
will continue to use the old primitives because they still exist in the VM,
even if they are no longer used or required by newer images.

Regarding VM size, the VM is designed to support named primitives that can
live in separately compiled modules ("external plugins"). The primitives
that we have been discussing here are one such example. They live in the
MiscPrimitivePlugin module, which can be compiled as a separate loadable
plugin module and excluded (or just deleted) if space is a concern.

Dave
Reply | Threaded
Open this post in threaded view
|

Re: Numbered primitives (was: Cog Primitive Performance)

Clément Béra
In reply to this post by David T. Lewis
 


On Tue, Apr 18, 2017 at 3:41 PM, David T. Lewis <[hidden email]> wrote:

On Tue, Apr 18, 2017 at 09:57:54AM -0700, Cl??ment Bera wrote:
>

<snip>

> For each primitive, we need to evaluate the performance with and without
> the primitive. In each case, we either move the primitive to numbered
> primitive or we just use normal Smalltalk code.

Please no more numbered primitives. We should be eliminating numbered primitives,
not adding more.

The only justification I can see for a numbered primitive today is to identify
it as one of the small number of primitives that absolutely must be available
when porting the VM to a new platform, especially if that platform may not
easily support the loading of functions by name. Aside from that, we should
insist that /all/ primitives be named primitives.

Ok.

The problem is that right now the JIT compiles to machine code only numbered primitives (in fact only numbered primitives specifically annotated in the primitive descriptors of Cogit). Other primitives require the VM to switch to the interpreter C stack to be called. If someone extends the JIT to compile named primitive then we could consider doing it that way.
 

Dave

Reply | Threaded
Open this post in threaded view
|

Re: Numbered primitives (was: Cog Primitive Performance)

Eliot Miranda-2
In reply to this post by David T. Lewis
 
Hi David,

On Tue, Apr 18, 2017 at 3:41 PM, David T. Lewis <[hidden email]> wrote:

On Tue, Apr 18, 2017 at 09:57:54AM -0700, Cl??ment Bera wrote:
>

<snip>

> For each primitive, we need to evaluate the performance with and without
> the primitive. In each case, we either move the primitive to numbered
> primitive or we just use normal Smalltalk code.

Please no more numbered primitives. We should be eliminating numbered primitives,
not adding more.

The only justification I can see for a numbered primitive today is to identify
it as one of the small number of primitives that absolutely must be available
when porting the VM to a new platform, especially if that platform may not
easily support the loading of functions by name. Aside from that, we should
insist that /all/ primitives be named primitives.

I beg to differ.  First one cannot eliminate numbered primitives because named primitives are built upon them, i.e. primitive 117, primitiveExternalCall, provides the linkage machinery that named primitives use.  Then...

- numbered primitives are compact in terms of metadata (3 bytes per method); named primitives need the 4 slot literal to hold them, the name symbol and the module name.  In the VM they also add overhead with the various string tables to refer to them.  These tables are compact for numbered primitives, and there is a table in the interpreter and a different table in the JIT; the tables for named primitives are much less compact, and tedious to search, bulking up the code still further.

- the named primitive mechanism nicely defines primitive modules for functionality outside the language, but otherwise doesn't offer much.  Both named and numbered primitives are opaque.

Instead I would like to see numbered primitives used for core language facilities; those needed in a headless image, and see some numbered primitives (for example primitiveMousePoint primitiveTestDisplayDepth primitiveSetDisplayMode primitiveInputSemaphore primitiveGetNextEvent primitiveInputWord primitiveBeCursor primitiveBeDisplay primitiveScanCharacters primitiveScreenSize primitiveMouseButtons primitiveKbdNext primitiveKbdPeek) be moved out into suitable modules (GUIPlugin for example).  I would also like the linking machinery to be lifted out of the VM into the image.  The machinery for searching for libraries and plugins is convoluted with the machinery for searching the tables of named primitives within plugins.  All would be much cleaner and transparent if reimplemented in terms of a handful of primitives, imagine loadLibraryOrPlugin, getPluginNameTable, and these being handled in a primitiveFailFor: with named primitives answering an error code such as #'not yet linked' on first invocation.
_,,,^..^,,,_
best, Eliot
Reply | Threaded
Open this post in threaded view
|

Re: Numbered primitives (was: Cog Primitive Performance)

timrowledge
 

> On 18-04-2017, at 6:46 PM, Eliot Miranda <[hidden email]> wrote:
>
>
> I beg to differ.  First one cannot eliminate numbered primitives because named primitives are built upon them, i.e. primitive 117, primitiveExternalCall, provides the linkage machinery that named primitives use.  Then…

I don’t *think* anyone was arguing for removing number prims as a concept (although I have in the past tried to work out how one might do that, without success of course) but for cutting them back as much as possible and using the name mechanism as the default whenever possible. Which seems pretty sensible to me.

Whilst it is true that a numbered prim costs less space in the calling method, we don’t have a huge number of them to worry about unless a large glob of code that makes use of a lot gets loaded. In which case, that’s good and proper and obviously we wouldn’t want a gazillion prims in the default vm (despite which we have a large number of plugins generally compiled in as internal plugins in most VM builds!) and paying the cost only when they’re used is smart.
>

> - the named primitive mechanism nicely defines primitive modules for functionality outside the language, but otherwise doesn't offer much.  Both named and numbered primitives are opaque.

The reason Andreas & I originally did the module/plugin stuff was the huge spread of extra prims that bloomed back in the dawning of the age of dinosaurs. It was a way to easily configure the vm environment to suit your needs. Actually named prims are a tiny smidge less opaque in that you do at least get to see the name of the bit of code you need to grep for!

>
> Instead I would like to see numbered primitives used for core language facilities; those needed in a headless image, and see some numbered primitives

> [snippety-snip]

>  be moved out into suitable modules (GUIPlugin for example).

Yes. Numbered prims ought to be those that make the barest system run and that make it possible to expand.

>  I would also like the linking machinery to be lifted out of the VM into the image.  The machinery for searching for libraries and plugins is convoluted with the machinery for searching the tables of named primitives within plugins.  All would be much cleaner and transparent if reimplemented in terms of a handful of primitives, imagine loadLibraryOrPlugin, getPluginNameTable, and these being handled in a primitiveFailFor: with named primitives answering an error code such as #'not yet linked' on first invocation.

We’d probably have to have a single rather monstrous prim that could do the simplest form of plugin load/hookup in order to get started; since using any file prims would require a file plugin to be loaded which… .etc. Once you get to deciding to load a proper filesystem you can use those prims to do any clever searching for plugins around your disc or network. It would probably mean requiring that plugin files are kept in one and only one place so as to avoid the search-two-thousand-places-depending-on-PATH-and-Moon code within the vm code.

Like so many other subjects (graphics, anyone?) we’ve discussed this a fair  few times in the past and if we have a good plan for actually doing it I’m all for it.


tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Strange OpCodes: LOW: Launch on Warning


Reply | Threaded
Open this post in threaded view
|

Re: Numbered primitives (was: Cog Primitive Performance)

David T. Lewis
 
On Wed, Apr 19, 2017 at 02:58:44PM -0700, tim Rowledge wrote:
>
> > On 18-04-2017, at 6:46 PM, Eliot Miranda <[hidden email]> wrote:
> >
> > I beg to differ.  First one cannot eliminate numbered primitives because named primitives are built upon them, i.e. primitive 117, primitiveExternalCall, provides the linkage machinery that named primitives use.  Then???
>
> I don???t *think* anyone was arguing for removing number prims as a concept (although I have in the past tried to work out how one might do that, without success of course) but for cutting them back as much as possible and using the name mechanism as the default whenever possible. Which seems pretty sensible to me.
>

Yes that is what I meant. Use the name mechanism as the default whenever possible.

My view: Primitives should be referenced by name, not number, unless there is a really
good reason for doing otherwise. By that I mean meeting one of these two conditions:

1) If, when the primitive cannot be invoked through a numeric primitive lookup, it is
difficult or impossible to port the VM to a new platform. In that case, the primitive
deserves a number in the primitive table.

2) If giving the primitive a number results in an measurable performance improvement
that would be noticed by a real user, then it should get a number.

Otherwise: Reference the primitive by name rather than by number.

> > - the named primitive mechanism nicely defines primitive modules for functionality outside the language, but otherwise doesn't offer much.  Both named and numbered primitives are opaque.
>
> The reason Andreas & I originally did the module/plugin stuff was the huge spread of extra prims that bloomed back in the dawning of the age of dinosaurs. It was a way to easily configure the vm environment to suit your needs. Actually named prims are a tiny smidge less opaque in that you do at least get to see the name of the bit of code you need to grep for!
>

In that case, I think that you and Andreas had it exactly right. Named primitives are
easier to grep for, and they are easier to reference in the VMMaker code. More importantly,
I can say from recent experience that trying to make sense of the variations in primitive
table assignments over time is a huge PITA that is completely avoidable through the
use of named primitives.

If this was just a VM issue, I would not worry about it one way or the other. But
numbered primitive references appear in the image, and this can (and most definitely
does) result in images that can only run on a certain specific range of VMs that
may not be easily reproduced 5 or 10 years in the future. I see this as a Very Bad
Thing, and I think that it is well worth the discipline of restricting numbered
primitives usage to prevent it happening.

Dave

12