Re: immutibility

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

Re: immutibility

Bert Freudenberg
On 31.03.2010, at 20:45, Denis Kudriashov wrote:


2010/3/31 Bert Freudenberg <[hidden email]>
On 31.03.2010, at 18:15, Igor Stasenko wrote:
>
> On 31 March 2010 18:24, Bert Freudenberg <[hidden email]> wrote:
>> On 31.03.2010, at 17:23, Andreas Raab wrote:
>>>
>>> On 3/31/2010 8:13 AM, Bert Freudenberg wrote:
>>>> Show me a single place that would break in a real-world use-case.
>>>>
>>>> In fact, #become: is rarely used in Squeak because of its inherent slowness caused by our direct-pointer object model. And those rare places I can think of would work just fine.
>>>
>>> I think there is one, and only one, place where #become: is intrinsically required: Changing class shape.
>>
>> Thought about that. Should be fine.
>>
> Magma using a forwarding proxies to indicate a not-yet reified objects
> in memory.
>
> Suppose that you having multiple different objects, which referencing
> such proxy.
> Proxy is not reified before a first message sent to it and used as a
> simple reference.
> Nothing prevents you from having many other objects, which pointing to
> that proxy without reifying a real object.
> And now, think about that with introduction of immutability, some of
> these objects is immutable. This means that it is now possible to have
> an immutable object, which having a reference to forwarding proxy.
> (even more than that, this is more than likely, because Magma will use
> an immutability for own purposes, to track changes to objects which
> belong to DB graph).
> At some stage, your model sending a message to forwarding proxy, and
> therefore magma needs to reify a real object
> in memory and replace all references to proxy with it.
> This is easy to implement by using a #becomeForward:, but if you
> change the  #becomeForward: semantics to not replace the references in
> immutable objects, you will efficiently break this scheme , and it
> can't be used reliably anymore.

Not at all. Of course you should not make an object immutable that you want to mutate later. That's the whole point really.


With your "become logic" reference to proxy (like proxy in magma and glorp) will never materialized if immutability used for object modification tracking.

You are talking about a write barrier. I'm talking about immutability.

As mentioned previously in this thread, these two are related, but not identical.

A write barrier might be more useful for current applications indeed. I simply wouldn't call that immutability.

And it will break this frameworks (magma, glorp)

Well if you make objects immutable you should be aware of what you are doing ;) 

IMHO hard immutability would be a valid and consistent model. Whether it would actually be practical and useful in Squeak I'm not sure. There seems to be no  compelling use case for it yet. OTOH, soft "almost-immutability" can be implemented in the image, so what would be the compelling reason to make this a VM feature, which almost certainly will come at a price?

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Igor Stasenko
On 1 April 2010 02:31, Bert Freudenberg <[hidden email]> wrote:

> On 31.03.2010, at 20:45, Denis Kudriashov wrote:
>
> 2010/3/31 Bert Freudenberg <[hidden email]>
>>
>> On 31.03.2010, at 18:15, Igor Stasenko wrote:
>> >
>> > On 31 March 2010 18:24, Bert Freudenberg <[hidden email]> wrote:
>> >> On 31.03.2010, at 17:23, Andreas Raab wrote:
>> >>>
>> >>> On 3/31/2010 8:13 AM, Bert Freudenberg wrote:
>> >>>> Show me a single place that would break in a real-world use-case.
>> >>>>
>> >>>> In fact, #become: is rarely used in Squeak because of its inherent
>> >>>> slowness caused by our direct-pointer object model. And those rare places I
>> >>>> can think of would work just fine.
>> >>>
>> >>> I think there is one, and only one, place where #become: is
>> >>> intrinsically required: Changing class shape.
>> >>
>> >> Thought about that. Should be fine.
>> >>
>> > Magma using a forwarding proxies to indicate a not-yet reified objects
>> > in memory.
>> >
>> > Suppose that you having multiple different objects, which referencing
>> > such proxy.
>> > Proxy is not reified before a first message sent to it and used as a
>> > simple reference.
>> > Nothing prevents you from having many other objects, which pointing to
>> > that proxy without reifying a real object.
>> > And now, think about that with introduction of immutability, some of
>> > these objects is immutable. This means that it is now possible to have
>> > an immutable object, which having a reference to forwarding proxy.
>> > (even more than that, this is more than likely, because Magma will use
>> > an immutability for own purposes, to track changes to objects which
>> > belong to DB graph).
>> > At some stage, your model sending a message to forwarding proxy, and
>> > therefore magma needs to reify a real object
>> > in memory and replace all references to proxy with it.
>> > This is easy to implement by using a #becomeForward:, but if you
>> > change the  #becomeForward: semantics to not replace the references in
>> > immutable objects, you will efficiently break this scheme , and it
>> > can't be used reliably anymore.
>>
>> Not at all. Of course you should not make an object immutable that you
>> want to mutate later. That's the whole point really.
>>
>
> With your "become logic" reference to proxy (like proxy in magma and glorp)
> will never materialized if immutability used for object modification
> tracking.
>
> You are talking about a write barrier. I'm talking about immutability.
> As mentioned previously in this thread, these two are related, but not
> identical.
> A write barrier might be more useful for current applications indeed. I
> simply wouldn't call that immutability.
>
> And it will break this frameworks (magma, glorp)
>
> Well if you make objects immutable you should be aware of what you are doing
> ;)
> IMHO hard immutability would be a valid and consistent model. Whether it
> would actually be practical and useful in Squeak I'm not sure. There seems
> to be no  compelling use case for it yet. OTOH, soft "almost-immutability"
> can be implemented in the image, so what would be the compelling reason to
> make this a VM feature, which almost certainly will come at a price?

Yep. IMO we should think more about models, which could help us to improve
a real, existing use cases (like Magma or GLORP).
IMO, an immutability as a separate model seems not very useful,
especially in 'hard' form, when it propagating through references.
So far, Squeak system is built without the need of immutability, and
it works well. And hence, it raising a logical question: how much we
really need an immutability as a core concept in object model?
In what areas it would simplify implementation and/or make it more robust?

> - Bert -
>


--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Colin Putney
In reply to this post by Bert Freudenberg

On 2010-03-31, at 8:24 AM, Bert Freudenberg wrote:

> On 31.03.2010, at 17:23, Andreas Raab wrote:
>>
>> On 3/31/2010 8:13 AM, Bert Freudenberg wrote:
>>> Show me a single place that would break in a real-world use-case.
>>>
>>> In fact, #become: is rarely used in Squeak because of its inherent slowness caused by our direct-pointer object model. And those rare places I can think of would work just fine.
>>
>> I think there is one, and only one, place where #become: is intrinsically required: Changing class shape.
>
> Thought about that. Should be fine.

So you're saying you think it's OK that immutable objects don't get migrated to the new version of the class? I suppose that conforms to a strict interpretation of the of the term "immutable" - neither state nor behaviour may be change.

At some point though, such a strict interpretation isn't very useful. An object that can't change state, can't change behaviour, can't refer to mutable objects, and can't become mutable again is certainly worth of the term, but it's also useless from a practical point of view. Has anyone proposed a use case for this sort of immutability? If not, why insist on defining the term so tightly?

As far as I'm aware, the use cases for immutability, loosely defined, are as follows:

(a) Literals. If the compiler makes objects immutable before putting them in the literal frame of a method, we can be sure that the state of the object when the method is activated is the same as what appears in the source code. This is certainly nice. Mutability of literals hasn't been a problem so far, though, so it's not crucial.

(b) Write Barrier. Immutability as implemented in, for example VW, allows object mutation to be efficiently tracked, which is handy for persisting objects outside the image, or synchronizing their state between images.

(c) Concurrency. The tricky thing about concurrency is shared mutable state. If it's possible to make objects immutable, it's then possible to share them safely between units of concurrency - Processes, Islands, images etc. When sending state between units of concurrency, immutable objects can often be transmitted more efficiently.

(d) Garbage Collection. If there are enough immutable objects in the image, it might be possible to improve the efficiency of the garbage collector. Have an "immutable space" and cache all the pointers back into mutable space. Or something. Or the "Shared Perm Space" thing that VW used to have.

Any other ideas?

For me, (b) and (c) are the interesting cases. Seaside apps almost always need to persist data in some way, and (b) would make this a lot easier and more efficient. (c) is maybe less clear cut, but in a lot of ways it's more interesting. I like the general trend in Squeak toward event loop concurrency, rather than classical Processes & Semaphores. Immutability would enable more experimentation in this area.

Perhaps if we focused on these use cases, we'd have a more productive discussion. It may be that VM-level immutability isn't useful enough to be worth the effort to implement and support. But if it *is* worthwhile, it'll be because of what it let's us do, rather than how semantically correct our definition of immutability is.

Colin
Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Igor Stasenko
On 1 April 2010 06:06, Colin Putney <[hidden email]> wrote:

>
> On 2010-03-31, at 8:24 AM, Bert Freudenberg wrote:
>
>> On 31.03.2010, at 17:23, Andreas Raab wrote:
>>>
>>> On 3/31/2010 8:13 AM, Bert Freudenberg wrote:
>>>> Show me a single place that would break in a real-world use-case.
>>>>
>>>> In fact, #become: is rarely used in Squeak because of its inherent slowness caused by our direct-pointer object model. And those rare places I can think of would work just fine.
>>>
>>> I think there is one, and only one, place where #become: is intrinsically required: Changing class shape.
>>
>> Thought about that. Should be fine.
>
> So you're saying you think it's OK that immutable objects don't get migrated to the new version of the class? I suppose that conforms to a strict interpretation of the of the term "immutable" - neither state nor behaviour may be change.
>
> At some point though, such a strict interpretation isn't very useful. An object that can't change state, can't change behaviour, can't refer to mutable objects, and can't become mutable again is certainly worth of the term, but it's also useless from a practical point of view. Has anyone proposed a use case for this sort of immutability? If not, why insist on defining the term so tightly?
>
> As far as I'm aware, the use cases for immutability, loosely defined, are as follows:
>
> (a) Literals. If the compiler makes objects immutable before putting them in the literal frame of a method, we can be sure that the state of the object when the method is activated is the same as what appears in the source code. This is certainly nice. Mutability of literals hasn't been a problem so far, though, so it's not crucial.
>
> (b) Write Barrier. Immutability as implemented in, for example VW, allows object mutation to be efficiently tracked, which is handy for persisting objects outside the image, or synchronizing their state between images.
>
> (c) Concurrency. The tricky thing about concurrency is shared mutable state. If it's possible to make objects immutable, it's then possible to share them safely between units of concurrency - Processes, Islands, images etc. When sending state between units of concurrency, immutable objects can often be transmitted more efficiently.
>
> (d) Garbage Collection. If there are enough immutable objects in the image, it might be possible to improve the efficiency of the garbage collector. Have an "immutable space" and cache all the pointers back into mutable space. Or something. Or the "Shared Perm Space" thing that VW used to have.
>
> Any other ideas?
>
> For me, (b) and (c) are the interesting cases. Seaside apps almost always need to persist data in some way, and (b) would make this a lot easier and more efficient. (c) is maybe less clear cut, but in a lot of ways it's more interesting. I like the general trend in Squeak toward event loop concurrency, rather than classical Processes & Semaphores. Immutability would enable more experimentation in this area.
>
> Perhaps if we focused on these use cases, we'd have a more productive discussion. It may be that VM-level immutability isn't useful enough to be worth the effort to implement and support. But if it *is* worthwhile, it'll be because of what it let's us do, rather than how semantically correct our definition of immutability is.
>

For concurrency.. perhaps.
But i'd say that most problems of concurrency is sharing a mutable
state, not immutable one, because in most cases its trivial to define
a shared static state in your application and make sure it doesn't
mutating unexpectably.
Yes, it would help detecting a *trivial* problems at initial stages of
development, and exchange the immutable data more efficiently, but
again, most of computational tasks anyways dealing with mutable state,
and i don't see how immutability could help in this regard.
What i mean that once you detect immutable object - you can simply
pass a pointer (or copy data, whatever). Cool! But once you detect
that you wanna share a mutable object between islands/images/threads -
you still having the very same concurrency problems as before. And so,
a real problem still is yours :)


Perm space.
I see it as a form of generational GC specialization. Yes, it could
improve GC performance. But why only for immutables?
I think that you could achive nearly same effect by simply adding 1
more generation to GC model without need of separating objects on
ones, which can mutate and ones which can't.

So, for me,  there is only (a) and (b) seem useful with an easily
foreseen impact.

> Colin
>

--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Colin Putney

On 2010-03-31, at 9:31 PM, Igor Stasenko wrote:

> For concurrency.. perhaps.
> But i'd say that most problems of concurrency is sharing a mutable
> state, not immutable one, because in most cases its trivial to define
> a shared static state in your application and make sure it doesn't
> mutating unexpectably.
> Yes, it would help detecting a *trivial* problems at initial stages of
> development, and exchange the immutable data more efficiently, but
> again, most of computational tasks anyways dealing with mutable state,
> and i don't see how immutability could help in this regard.
> What i mean that once you detect immutable object - you can simply
> pass a pointer (or copy data, whatever). Cool! But once you detect
> that you wanna share a mutable object between islands/images/threads -
> you still having the very same concurrency problems as before. And so,
> a real problem still is yours :)

IMO the interesting possibilities here are all about concurrency *without* shared mutable state. If objects can be made immutable, the code that manages communication between islands, images, vats etc, can be intelligent about how it handles them. Application-level code still has to manage communications between units of isolation, but its interface with the runtime can get simpler if the runtime can tell what's mutable and what's not. It's about making it easier to implement Islands, etc. in Squeak, not (directly) about making it easier to write an app with such an implementation.

Admittedly, it's not as easy to predict how much of an impact immutability would have in this realm, especially when compared with (b). But I do think it's one of the basic building blocks that would enable experimentation here.

> Perm space.
> I see it as a form of generational GC specialization. Yes, it could
> improve GC performance. But why only for immutables?
> I think that you could achive nearly same effect by simply adding 1
> more generation to GC model without need of separating objects on
> ones, which can mutate and ones which can't.

<shrug> Yeah, I was scraping the bottom of the barrel with this one. It's a stretch no matter how you look at it.

> So, for me,  there is only (a) and (b) seem useful with an easily
> foreseen impact.

Fair enough, though (c) may have unforeseen impact.

Colin
Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Denis Kudriashov
I think usage of immutability for object modification tracking is not very well solution and not simple solution. With that you must put every code with your objects in block that catch ModificationException. You can't track arbitrarily object modifications in any other places of system.

I think more general approach is registering arbitrary modification handler on object mutation like

object handleMutationBy: [:mutation | ]
and
object resetMutationTracking

And maybe it can be implemented like immutability approach. with single bit in object header. VM check this bit for #at:put: like primitives and send message #handleMutation: to target object if It set.

And now immutability logic with ModificationException has very simple implementation in language side

Object>>handleMutation: aMutation
   self raise: (ModificationException new mutation: aMutation)

Implementation of my messages:

Object>>handleMutation: aMutation
  self trackMutation.
  ^mutationHandler value: aMutation

And VM needs two primitives: #trackMutation and #resetMutationTracking





Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Igor Stasenko
In reply to this post by Colin Putney
On 1 April 2010 08:02, Colin Putney <[hidden email]> wrote:

>
> On 2010-03-31, at 9:31 PM, Igor Stasenko wrote:
>
>> For concurrency.. perhaps.
>> But i'd say that most problems of concurrency is sharing a mutable
>> state, not immutable one, because in most cases its trivial to define
>> a shared static state in your application and make sure it doesn't
>> mutating unexpectably.
>> Yes, it would help detecting a *trivial* problems at initial stages of
>> development, and exchange the immutable data more efficiently, but
>> again, most of computational tasks anyways dealing with mutable state,
>> and i don't see how immutability could help in this regard.
>> What i mean that once you detect immutable object - you can simply
>> pass a pointer (or copy data, whatever). Cool! But once you detect
>> that you wanna share a mutable object between islands/images/threads -
>> you still having the very same concurrency problems as before. And so,
>> a real problem still is yours :)
>
> IMO the interesting possibilities here are all about concurrency *without* shared mutable state. If objects can be made immutable, the code that manages communication between islands, images, vats etc, can be intelligent about how it handles them. Application-level code still has to manage communications between units of isolation, but its interface with the runtime can get simpler if the runtime can tell what's mutable and what's not. It's about making it easier to implement Islands, etc. in Squeak, not (directly) about making it easier to write an app with such an implementation.
>
> Admittedly, it's not as easy to predict how much of an impact immutability would have in this realm, especially when compared with (b). But I do think it's one of the basic building blocks that would enable experimentation here.
>

Maybe. I still thinking, that OO approach is much more powerful and flexible.
As easy as,
object replicateIn: island
lets an object to decide how to replicate itself in given
island/environment, whether create a copy or pass as a reference (or
any other form),
without a need of introducing any magic from VM side.
This gives you a direct control over what happens and when.
Bug again, we don't have a model, already implemented and widely used
which employs an immutability in a way you suggested. So, this still
lies in experimental area.
While with DB replication schemes, we already having a real use
examples. So, logically would be to focus on this ones instead.

>> Perm space.
>> I see it as a form of generational GC specialization. Yes, it could
>> improve GC performance. But why only for immutables?
>> I think that you could achive nearly same effect by simply adding 1
>> more generation to GC model without need of separating objects on
>> ones, which can mutate and ones which can't.
>
> <shrug> Yeah, I was scraping the bottom of the barrel with this one. It's a stretch no matter how you look at it.
>
>> So, for me,  there is only (a) and (b) seem useful with an easily
>> foreseen impact.
>
> Fair enough, though (c) may have unforeseen impact.
>
> Colin
>



--
Best regards,
Igor Stasenko AKA sig.

Reply | Threaded
Open this post in threaded view
|

Re: immutibility

Denis Kudriashov
In reply to this post by Denis Kudriashov
2010/4/1 Denis Kudriashov <[hidden email]>
I think usage of immutability for object modification tracking is not very well solution and not simple solution. With that you must put every code with your objects in block that catch ModificationException. You can't track arbitrarily object modifications in any other places of system.

I think more general approach is registering arbitrary modification handler on object mutation like

object handleMutationBy: [:mutation | ]
and
object resetMutationTracking

And maybe it can be implemented like immutability approach. with single bit in object header. VM check this bit for #at:put: like primitives and send message #handleMutation: to target object if It set.

And now immutability logic with ModificationException has very simple implementation in language side

Object>>handleMutation: aMutation
   self raise: (ModificationException new mutation: aMutation)

Implementation of my messages:

Object>>handleMutation: aMutation
  self trackMutation.
  ^mutationHandler value: aMutation

And VM needs two primitives: #trackMutation and #resetMutationTracking


Sorry, I little mistake. What I try wrote is:

Object>>handleMutation: aMutation
  ^mutationHandler value: aMutation

Object>>handleMutationBy: aBlock
  self trackMutation.
  mutationHandler := aBlock

And immutable logic can be like that:

Object>>beImmutable
  self handleMutationBy: [:mutation | self raise: (ModificationException new mutation: aMutation)]

Object>>beMuttable
  self resetMutationTracking


 


123