Quantcast

Re: [Vm-dev] [Pharo-project] Plan/discussion/communication around new object format

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

Re: [Vm-dev] [Pharo-project] Plan/discussion/communication around new object format

Chris Muller-4
(discussion branch moved to Magma list).

Well, I doubt it's faster than just using Avi's regular WriteBarrier.
Understand the overrides are only compiled once per class, not once
per object.  In the real world compilation is not a significant factor
on performance.

The overridden methods follow the pattern:

someMethod
  | t1 t2 newT1 newT2 returnValue |
  t1 := self instVarAt: 1.
  t2 := self instVarAt: 2.
  returnValue := super someMethod.
  newT1==t1 ifFalse: [ self modified. ^ returnValue ].
  newT2==t2 ifFalse: [ self modified.  ^ returnValue ].
  ^ returnValue

which is probably even faster than unwinding stack all the way to the
Immutable handler every time an attribute is set.  Not sure, but the
above is fast enough to accomplish the overall goal and substantially
improve app performance.



> Ok, what if we call it a "fast write-barrier provided by the VM".
> Would that change your view? Igor?
_______________________________________________
Magma mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/magma
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Vm-dev] [Pharo-project] Plan/discussion/communication around new object format

Igor Stasenko
in your case (Magma) you can do even better:
at the beginning of transaction make a deep copy of object graph.
Upon finishing transaction, you walk the modified graph and compare
objects if they are changed or not.
This could be somewhat memory-hungry (but do we care?), but you don't
have to use anything like
write barrier or overriding compiled methods.

And with having a per-object properties, it just another piece of cake:

Object>>maIsChanged
   ^ (self propertyAt: #originalCopy) = self

and for nested transactions, you can make it even more hungry

Object>>maIsChangedIn: transaction
   ^ (self propertyAt: transaction) = self

:)
but nested (and not even) transactions implying anyways that you hold
the original somewhere,
to be able to roll back the changes.

So in case of rollback, all you need to do is to send #restore to the
root object:

Object>>restore
   self befomeForward: (self propertyAt:#originalCopy).
   self allIvarsDo: [:each | each restore]

Now, add there a VM primitive which can quickly mark a graph starting
from your roots,
and stockpile marked objects into some array, and you will have a
super fast thingy :)


On 12 June 2012 00:00, Chris Muller <[hidden email]> wrote:

> (discussion branch moved to Magma list).
>
> Well, I doubt it's faster than just using Avi's regular WriteBarrier.
> Understand the overrides are only compiled once per class, not once
> per object.  In the real world compilation is not a significant factor
> on performance.
>
> The overridden methods follow the pattern:
>
> someMethod
>  | t1 t2 newT1 newT2 returnValue |
>  t1 := self instVarAt: 1.
>  t2 := self instVarAt: 2.
>  returnValue := super someMethod.
>  newT1==t1 ifFalse: [ self modified. ^ returnValue ].
>  newT2==t2 ifFalse: [ self modified.  ^ returnValue ].
>  ^ returnValue
>
> which is probably even faster than unwinding stack all the way to the
> Immutable handler every time an attribute is set.  Not sure, but the
> above is fast enough to accomplish the overall goal and substantially
> improve app performance.
>
>
>
>> Ok, what if we call it a "fast write-barrier provided by the VM".
>> Would that change your view? Igor?
> _______________________________________________
> Magma mailing list
> [hidden email]
> http://lists.squeakfoundation.org/mailman/listinfo/magma



--
Best regards,
Igor Stasenko.
_______________________________________________
Magma mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/magma
cbc
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Vm-dev] [Pharo-project] Plan/discussion/communication around new object format

cbc
On Tue, Jun 12, 2012 at 8:13 PM, Igor Stasenko <[hidden email]> wrote:
[snip]
> This could be somewhat memory-hungry (but do we care?), but you don't
[snip]

As long as the Windows VM is severely limited in how much memory it
can handle, some of us care a lot.  It just depends on how
memory-hungry it is, and how much memory we're already using.
_______________________________________________
Magma mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/magma
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Vm-dev] [Pharo-project] Plan/discussion/communication around new object format

Igor Stasenko
On 13 June 2012 18:13, Chris Cunningham <[hidden email]> wrote:
> On Tue, Jun 12, 2012 at 8:13 PM, Igor Stasenko <[hidden email]> wrote:
> [snip]
>> This could be somewhat memory-hungry (but do we care?), but you don't
> [snip]
>
> As long as the Windows VM is severely limited in how much memory it
> can handle, some of us care a lot.  It just depends on how
> memory-hungry it is, and how much memory we're already using.

no, it just about keeping a copy of working set of your transaction.
And nothing will save you from memory problems if you start to abuse DB to load
huge blobs of data, required for your working set..

and as i said, you have to use the copy anyways in case if you need to
rollback transaction.

and nobody said that you cannot employ a hybrid approach: you can keep
a copies of objects
up to certain size/or for certain kind of classes and for the large
ones you can still use the same write barrier approach.
so you will have a best of both worlds :)

In terms of implementation, this is quite easy to do: since graph
comes from database in serialized form, creating an initial copy is
just about materializing same object twice (or materializing and then
copying) instead of once.
One will be used in working set,
and another will be used to detect the changes upon committing transaction.

--
Best regards,
Igor Stasenko.
_______________________________________________
Magma mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/magma
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Vm-dev] [Pharo-project] Plan/discussion/communication around new object format

Chris Muller-4
> In terms of implementation, this is quite easy to do: since graph
> comes from database in serialized form, creating an initial copy is
> just about materializing same object twice (or materializing and then
> copying) instead of once.
> One will be used in working set,
> and another will be used to detect the changes upon committing transaction.

Magma essentially does this today.  Back in the early 2000's, it made
shallow copies of each materialized object and identity-mapped them to
the "working copy" of the object.  It would compare them upon
transaction commit to see if they should be part of the commit
package.

Since then, it was changed to just keep the original buffers that were
already part of the materialization (so not making copies when just
reading from the db).  On transaction commit it now compares the
referenced oids of each to determine if different.

BTW:  I just realized a BIG problem with the WriteBarrier approach to
change-detection:  If the method which modifies the inst-variable ALSO
happens to perform the commit, then the commit will not notice the
changes!

For example, consider a simple setter:

    name: aString
        myDbSession commit: [ name = aString ]

WB will override this method in its generated anonymous subclass to:

    name: aString
        | t1 |
        t1 := name.
        returnVal := super name: aString.
        t1 == name ifFalse: [ self writeBarrier modified ].
        ^ returnVal

Do you see the problem?  Super call already tried the commit before it
even knew it was changed.  It emphasizes the limitation of WB:  That
it can only work via method calls, not direct assignments like a
immutability-bit could.

The only solution is to NEVER co-locate the updating of a persistent
inst-var in the same method as performing/signaling the commit.  That
sucks bad enough that I've made Magma sessions now default
allowWriteBarrier to false.   :-(
_______________________________________________
Magma mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/magma
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Vm-dev] [Pharo-project] Plan/discussion/communication around new object format

Igor Stasenko
On 15 June 2012 17:57, Chris Muller <[hidden email]> wrote:

>> In terms of implementation, this is quite easy to do: since graph
>> comes from database in serialized form, creating an initial copy is
>> just about materializing same object twice (or materializing and then
>> copying) instead of once.
>> One will be used in working set,
>> and another will be used to detect the changes upon committing transaction.
>
> Magma essentially does this today.  Back in the early 2000's, it made
> shallow copies of each materialized object and identity-mapped them to
> the "working copy" of the object.  It would compare them upon
> transaction commit to see if they should be part of the commit
> package.
>
Ah.. cool.. so even less work.
So, i presume you miss one little primitive which scans the memory
subgraph from the roots which you provide
and gives you back all objects which inside it.
Like that you can very quickly discover what is a new shape of a working set
and then iterate over it and see what objects were changed and which
were added/removed.

> Since then, it was changed to just keep the original buffers that were
> already part of the materialization (so not making copies when just
> reading from the db).  On transaction commit it now compares the
> referenced oids of each to determine if different.
>
> BTW:  I just realized a BIG problem with the WriteBarrier approach to
> change-detection:  If the method which modifies the inst-variable ALSO
> happens to perform the commit, then the commit will not notice the
> changes!
>
> For example, consider a simple setter:
>
>    name: aString
>        myDbSession commit: [ name = aString ]
>
> WB will override this method in its generated anonymous subclass to:
>
>    name: aString
>        | t1 |
>        t1 := name.
>        returnVal := super name: aString.
>        t1 == name ifFalse: [ self writeBarrier modified ].
>        ^ returnVal
>
> Do you see the problem?

yes, i do :)
A correct implementation should modify the existing methods, but
not use subclassing. But that's of course harder to do without decent
support from tools
(btw Opal Compiler will allow to do that easily).

but i think you can easily fix it by implementing #maValue in block
and use
aBlock maValue
in commit method, instead of #value.

A sketch implementaiton of #maValue is something like:

maValue
  | rcvr receiverStateBefore result |
  rcvr := self home receiver.
  receiverStateBefore :=rcrvr copyState.
  result := self value.
  (rcvr isSameAs: receiverStateBefore) ifFalse: [ rcvr writeBarrier modified ].
  ^ result

> Super call already tried the commit before it
> even knew it was changed.  It emphasizes the limitation of WB:  That
> it can only work via method calls, not direct assignments like a
> immutability-bit could.
>
> The only solution is to NEVER co-locate the updating of a persistent
> inst-var in the same method as performing/signaling the commit.  That
> sucks bad enough that I've made Magma sessions now default
> allowWriteBarrier to false.   :-(



--
Best regards,
Igor Stasenko.
_______________________________________________
Magma mailing list
[hidden email]
http://lists.squeakfoundation.org/mailman/listinfo/magma
Loading...