Robin suggests a mechanism for implementing persistence:
> If programs are constrained to not using fast_...
> procedures, and the mishap mechanism is appropriately disciplined (upon
> which I have in the past addressed the pop-forum) then it can be used to
> trap access to data-objects that are not in main memory. Any POP object
> could be "kicked upstairs" to backing store leaving just a stub in main
> memory, containing a backing-store reference.. Trying to apply a selector
> function to such a stub would then cause the object to be read into
> main-memory ...
A problem with this as a general idea is that recognisers (i.e. isXXX
procedures) need to be modified to spot when they applied to objects
that are ``out'' on disc. There are several approaches to solve this
problem but they aren't very elegant.
The problem is that you would like to avoid paying a performance cost
when you don't use persistence. Unfortunately, recogniser code now has to
perform at least an extra tag check before it can return <false>. But in
practice this may well be tolerable.
If you are going to introduce another tag code, then why waste it on
something special purpose like persistence? :-)
Instead, the extra tag code can mean that the value has been delayed.
This is a wider meaning than persistence, which is a special case. A
delayed value might be one that requires an arbitrary amount more computation.
In general, I suggest that delayed-value can be fetched or forced by
applying one of its fields. This field might be a record-class with a
user-defined class-apply, for example.
The concept of delayed values is immensely powerful. It is something
I've wanted for years and years and years in POPLOG. Persistence isn't
so important for the work that I do -- I want a controlled version of
lazy evaluation -- but the same underlying mechanism can be used to
implement both. And Robin's remarks about the garbage collector mostly
apply to both.
The key difference is that with persistent objects you want the ability
to automatically page them back out to store under some circumstances.
A typical example of this is when the garbage collector decides that
the proportion of its heap that is consumed by persistent objects is too
great. At that point, it may choose to push all persistent objects back
onto disc. If the garbage collector eliminates the indirection pointer
then becomes awkward. Another example is when the garbage collector is
invoked because more store is needed and the OS denied the request to
expand the heap. The Garbage collector should reserve the right to
boot the persistent objects onto disc before it fails the test.
The modification that is required is that delayed objects need to have
extra flags associated with them -- whether they should be indirected by
the garbage collector -- whether they have been expanded -- whether they
can be compressed to regain main memory -- and so on.
This question gets more complex when the considerations of rollback are
factored in. We don't want to corrupt our persistent store by crashing in
the middle of a garbage collection after pushing persistent data back to
disc. In this case, the system needs to rollback the state of the database
to the last checkpoint before crashing.
Steve
|