FFILibrary uniqueInstance

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

FFILibrary uniqueInstance

Nicolas Cellier
Hi all,
I wanted to know if the moduleName was cached somewhere or recomputed at each function call...
It seems to be recomputed.

We could have a different scheme:
moduleName is cached in a class inst var of FFILibrary.
FFILibrary is then added to startup list and moduleName is reset when resuming on a different platform.
instance side moduleName calls class side moduleName.

Or moduleName becomes an inst var, set during uniqueInstance construction, and uniqueInstance is nilled out when resuming.

What do you think?

Reply | Threaded
Open this post in threaded view
|

Re: FFILibrary uniqueInstance

Guillermo Polito
Hi Nicolas,
On Fri, Jan 11, 2019 at 12:09 PM Nicolas Cellier <[hidden email]> wrote:
Hi all,
I wanted to know if the moduleName was cached somewhere or recomputed at each function call...
It seems to be recomputed.

Do you mean when using a symbol/string as module like...?

ioFindSurface: id dispatch: dispPtr handle: handlePtr
self ffiCall: #( bool ioFindSurface(int id, void * dispPtr, int *handlePtr) ) module: #SurfacePlugin
 

We could have a different scheme:
moduleName is cached in a class inst var of FFILibrary.
FFILibrary is then added to startup list and moduleName is reset when resuming on a different platform.
instance side moduleName calls class side moduleName.

Or moduleName becomes an inst var, set during uniqueInstance construction, and uniqueInstance is nilled out when resuming.

What do you think?

As I see it, there are two (basic) schemas to do FFI calls using UFFI
 - using a library object. Library objects are actual singletons stored in class instance variables

FFILibrary class >> uniqueInstance 
self = FFILibrary 
ifTrue: [ self error: 'I''m an abstract class, use one of my children.' ].
^ uniqueInstance ifNil: [ uniqueInstance := super new ]

- using a symbol/string, then a module is created dynamically

String >> asFFILibrary 
^ FFIUnknownLibrary name: self
 
But, but :) the thing is that ffi calls in UFFI are lazily compiled using bytecode transformations and there (if I'm not mistaken) the library instances created are cached on the callout object stored as a literal in the method.
So there is a cache, but per ffi call. And then, at shutdown, all the generated methods (bound to a specific external function) are wiped out.

All this process is of course perfectible and probably a "coup de" profiling could be nice ^^.

HTH,
Guille
Reply | Threaded
Open this post in threaded view
|

Re: FFILibrary uniqueInstance

EstebanLM
Hi,

On 14 Jan 2019, at 09:46, Guillermo Polito <[hidden email]> wrote:

Hi Nicolas,
On Fri, Jan 11, 2019 at 12:09 PM Nicolas Cellier <[hidden email]> wrote:
Hi all,
I wanted to know if the moduleName was cached somewhere or recomputed at each function call...
It seems to be recomputed.

Do you mean when using a symbol/string as module like...?

ioFindSurface: id dispatch: dispPtr handle: handlePtr
self ffiCall: #( bool ioFindSurface(int id, void * dispPtr, int *handlePtr) ) module: #SurfacePlugin
 

We could have a different scheme:
moduleName is cached in a class inst var of FFILibrary.
FFILibrary is then added to startup list and moduleName is reset when resuming on a different platform.
instance side moduleName calls class side moduleName.

Or moduleName becomes an inst var, set during uniqueInstance construction, and uniqueInstance is nilled out when resuming.

What do you think?

As I see it, there are two (basic) schemas to do FFI calls using UFFI
 - using a library object. Library objects are actual singletons stored in class instance variables

FFILibrary class >> uniqueInstance 
self = FFILibrary 
ifTrue: [ self error: 'I''m an abstract class, use one of my children.' ].
^ uniqueInstance ifNil: [ uniqueInstance := super new ]

- using a symbol/string, then a module is created dynamically

String >> asFFILibrary 
^ FFIUnknownLibrary name: self
 
But, but :) the thing is that ffi calls in UFFI are lazily compiled using bytecode transformations and there (if I'm not mistaken) the library instances created are cached on the callout object stored as a literal in the method.
So there is a cache, but per ffi call. And then, at shutdown, all the generated methods (bound to a specific external function) are wiped out.

All this process is of course perfectible and probably a "coup de" profiling could be nice ^^.

Well, when I designed the FFILibrary I first thought: let’s the user decide if they want to cache or not (because most of the time is not worthy, since as Guille says it is cached on each method and usually is straightforward)
Then I thought that maybe I should add a generic cache mechanism, for those cases where you need to perform complicated locates. But I did not had the time to do it.

So, I would say: yes, it would be good to have a cache mechanism, but most of the time is not needed (and caches are dangerous things so better to reduce their usage at max).
If someone wants to implement that for their library, they can. 
If someone wants to implement a generic mechanism and contribute it, it would be also welcomed :)

Esteban



HTH,
Guille

Reply | Threaded
Open this post in threaded view
|

Re: FFILibrary uniqueInstance

ducasse
Esteban

Do you know if this points is documented in the FFILibrary class comments?
Can you add a bug entry so that we do not forget?

TX
Stef

On 14 Jan 2019, at 10:09, Esteban Lorenzano <[hidden email]> wrote:

Hi,

On 14 Jan 2019, at 09:46, Guillermo Polito <[hidden email]> wrote:

Hi Nicolas,
On Fri, Jan 11, 2019 at 12:09 PM Nicolas Cellier <[hidden email]> wrote:
Hi all,
I wanted to know if the moduleName was cached somewhere or recomputed at each function call...
It seems to be recomputed.

Do you mean when using a symbol/string as module like...?

ioFindSurface: id dispatch: dispPtr handle: handlePtr
self ffiCall: #( bool ioFindSurface(int id, void * dispPtr, int *handlePtr) ) module: #SurfacePlugin
 

We could have a different scheme:
moduleName is cached in a class inst var of FFILibrary.
FFILibrary is then added to startup list and moduleName is reset when resuming on a different platform.
instance side moduleName calls class side moduleName.

Or moduleName becomes an inst var, set during uniqueInstance construction, and uniqueInstance is nilled out when resuming.

What do you think?

As I see it, there are two (basic) schemas to do FFI calls using UFFI
 - using a library object. Library objects are actual singletons stored in class instance variables

FFILibrary class >> uniqueInstance 
self = FFILibrary 
ifTrue: [ self error: 'I''m an abstract class, use one of my children.' ].
^ uniqueInstance ifNil: [ uniqueInstance := super new ]

- using a symbol/string, then a module is created dynamically

String >> asFFILibrary 
^ FFIUnknownLibrary name: self
 
But, but :) the thing is that ffi calls in UFFI are lazily compiled using bytecode transformations and there (if I'm not mistaken) the library instances created are cached on the callout object stored as a literal in the method.
So there is a cache, but per ffi call. And then, at shutdown, all the generated methods (bound to a specific external function) are wiped out.

All this process is of course perfectible and probably a "coup de" profiling could be nice ^^.

Well, when I designed the FFILibrary I first thought: let’s the user decide if they want to cache or not (because most of the time is not worthy, since as Guille says it is cached on each method and usually is straightforward)
Then I thought that maybe I should add a generic cache mechanism, for those cases where you need to perform complicated locates. But I did not had the time to do it.

So, I would say: yes, it would be good to have a cache mechanism, but most of the time is not needed (and caches are dangerous things so better to reduce their usage at max).
If someone wants to implement that for their library, they can. 
If someone wants to implement a generic mechanism and contribute it, it would be also welcomed :)

Esteban



HTH,
Guille

Reply | Threaded
Open this post in threaded view
|

Re: FFILibrary uniqueInstance

Pharo Smalltalk Developers mailing list
In reply to this post by EstebanLM


On Mon, 14 Jan 2019 at 17:12, Esteban Lorenzano <[hidden email]> wrote:
Hi,

On 14 Jan 2019, at 09:46, Guillermo Polito <[hidden email]> wrote:

Hi Nicolas,
On Fri, Jan 11, 2019 at 12:09 PM Nicolas Cellier <[hidden email]> wrote:
Hi all,
I wanted to know if the moduleName was cached somewhere or recomputed at each function call...
It seems to be recomputed.

Do you mean when using a symbol/string as module like...?

ioFindSurface: id dispatch: dispPtr handle: handlePtr
self ffiCall: #( bool ioFindSurface(int id, void * dispPtr, int *handlePtr) ) module: #SurfacePlugin
 

We could have a different scheme:
moduleName is cached in a class inst var of FFILibrary.
FFILibrary is then added to startup list and moduleName is reset when resuming on a different platform.
instance side moduleName calls class side moduleName.

Or moduleName becomes an inst var, set during uniqueInstance construction, and uniqueInstance is nilled out when resuming.

What do you think?

As I see it, there are two (basic) schemas to do FFI calls using UFFI
 - using a library object. Library objects are actual singletons stored in class instance variables

FFILibrary class >> uniqueInstance 
self = FFILibrary 
ifTrue: [ self error: 'I''m an abstract class, use one of my children.' ].
^ uniqueInstance ifNil: [ uniqueInstance := super new ]

- using a symbol/string, then a module is created dynamically

String >> asFFILibrary 
^ FFIUnknownLibrary name: self
 
But, but :) the thing is that ffi calls in UFFI are lazily compiled using bytecode transformations and there (if I'm not mistaken) the library instances created are cached on the callout object stored as a literal in the method.
So there is a cache, but per ffi call. And then, at shutdown, all the generated methods (bound to a specific external function) are wiped out.

All this process is of course perfectible and probably a "coup de" profiling could be nice ^^.

Well, when I designed the FFILibrary I first thought: let’s the user decide if they want to cache or not (because most of the time is not worthy, since as Guille says it is cached on each method and usually is straightforward)
Then I thought that maybe I should add a generic cache mechanism, for those cases where you need to perform complicated locates. But I did not had the time to do it.

So, I would say: yes, it would be good to have a cache mechanism, but most of the time is not needed (and caches are dangerous things so better to reduce their usage at max).

One thing that was get easily confusing is when when the moduleName is not found it seems to cache that error,
so that even when the C-library is installed into the correct location it continues to not find the function.
I should have added this to the bug tracker a while ago, but I haven't checked for a while so I don't know if this is still the case.
I'll wait your response and if agreeable I'll add it to the P8 bug tracker.

cheers -ben 


 
If someone wants to implement that for their library, they can. 
If someone wants to implement a generic mechanism and contribute it, it would be also welcomed :)

Esteban



HTH,
Guille