mutate an object or create a new one?

Discussion in 'Java' started by toton, Oct 24, 2006.

  1. toton

    toton Guest

    Hi,
    I have a typical situation for the main backbone of the program. In
    my program, lots of new objects gets created, added in the processing
    queue ,used and removed from the queue. Something like a air-traffic
    control system or moving average.
    The objects added to the queue, are by nature immutable, and that
    "may help" in a threaded environment (but not very much as the
    processing queues are seperate). However added immutability cause them
    to be use-and throw objects. While mutability cause them to be reused.
    I am trying to demonstrate the problem with a short example. While
    the original problem is much complex, but the underlying working
    principle is more or less same.
    public class TestProcess{
    public static void main(String[] args){
    Deque<ObjectTobeProcessed> queue = new
    ArrayDeque<ObjectTobeProcessed>(10);
    for(int i = 0; i <10; ++i){///pre existing objects.
    queue.addFirst(new ObjectTobeProcessed());
    }
    long time1 = System.currentTimeMillis();
    for(int i = 0; i <10000000; i++){
    queue.removeLast();///remove the last one.
    queue.addFirst(new ObjectTobeProcessed());///add a new at the first.
    process(queue);
    }
    long time2 = System.currentTimeMillis();
    System.out.println ("time "+(time2-time1)*0.001);

    Deque<MutableObjectTobeProcessed> queue1 = new
    ArrayDeque<MutableObjectTobeProcessed>(10);
    for(int i = 0; i <10; ++i){///pre-existing objects.
    queue1.addFirst(new MutableObjectTobeProcessed());
    }
    time1 = System.currentTimeMillis();
    for(int i = 0; i <10000000; i++){
    queue1.getLast().setValue();
    process(queue);
    }
    time2 = System.currentTimeMillis();
    System.out.println ("time "+(time2-time1)*0.001);
    }
    public static void process(Deque<ObjectTobeProcessed> queue){
    double sum = 0;
    for(ObjectTobeProcessed o: queue ){
    sum+= o.getValue();
    }
    }
    }
    class ObjectTobeProcessed{
    private double value;
    public ObjectTobeProcessed(){
    value = Math.random();
    }
    public double getValue(){
    return value;
    }
    }
    class MutableObjectTobeProcessed{
    private double value;
    public MutableObjectTobeProcessed(){
    value = Math.random();
    }
    public double getValue(){
    return value;
    }
    public void setValue(){
    value = Math.random();
    }
    }
    Here two class creates some random number, while one allows to reset
    its state , the other do not.
    In the first case one number is removed from last, one created at
    first, and some process is called (here a moving average! ) . Here a
    large numver of objects created, used and thrown away. In the second
    case, it mutates the last object (which is supposed to be thrown away)
    to the new state. Here no object gets created and destroyed at all!.
    Here the queue sequence is not the same (that don not affect the
    moving average though), but that can be solved using a wrapped version
    of deque (with a modulo wrapping).
    There is a difference for first case and second case, and difference
    increases considerabily when the objects becomes complex and stores
    more than premitive types.
    In the actual problem, the existing size is not fixed (as 10 here) but
    nearly fixed within certain limit.
    And the objects come & go from the processing queue are not so small.
    And the system is supposed to be on for ever and process things as come
    and go away.
    The things I notice,
    1) Both version has clear hotspot for processing.
    2) only the second verson has hotspot for processing over same data.
    3) For second version GC has very less job compared to first one.
    In actual case, the objects are characters (handwritten, not printed ,
    thus they can not be formed from same set of objects). Mutating them
    means one can unknowingly or by mistake form a B from and A! Making
    them immutable means an easier and cleaner code, but error prone (as
    Java doesn't have a const , so I even can't constantify an mutable
    object when needed)
    Also I use Mysaifu JVM for PocketPC, which may not have as
    sophisticated GC as sun's one .Though still I hadn't tested the code
    there with a performance difference , I will do it in near future (my
    friend had take my iPAQ :( , sure he will return it by this weekend.
    Can anyone give a little more insight, and the best way to do such job?
    (The processing is pretty computational gemetry related and also has
    some signal processing aspect. in short instead of moving average, it
    is some sot of complex mathematical calculation comes into process).
    Any alternate / better way to do such job ? Something like I can have a
    mutable object but selectively constantify it when needed?

    Thanks for any kinds of suggestion / advice
     
    toton, Oct 24, 2006
    #1
    1. Advertising

  2. toton

    Chris Uppal Guest

    toton wrote:

    > Also I use Mysaifu JVM for PocketPC, which may not have as
    > sophisticated GC as sun's one .Though still I hadn't tested the code
    > there with a performance difference , I will do it in near future (my
    > friend had take my iPAQ :( , sure he will return it by this weekend.
    > Can anyone give a little more insight, and the best way to do such job?
    > (The processing is pretty computational gemetry related and also has
    > some signal processing aspect. in short instead of moving average, it
    > is some sot of complex mathematical calculation comes into process).


    It sounds as if you are doing a lot of computation which isn't related to the
    creation/GCing of objects. As such the potential gains of avoiding GC (even in
    an environment where GC is slow) are going to be small at best. I.e it doesn't
    sound as if the extra complication would be worth it.

    Remember, too, that recyling the objects is not free -- there are the extra
    costs involved in resetting the obejct's states, adding them to free lists
    (which would probably involve synchronised code), any additional runtime checks
    you have to ensure that you are not changing objects when you shouldnt and so
    on.

    -- chris
     
    Chris Uppal, Oct 24, 2006
    #2
    1. Advertising

  3. toton

    toton Guest

    Chris Uppal wrote:
    > toton wrote:
    >
    > > Also I use Mysaifu JVM for PocketPC, which may not have as
    > > sophisticated GC as sun's one .Though still I hadn't tested the code
    > > there with a performance difference , I will do it in near future (my
    > > friend had take my iPAQ :( , sure he will return it by this weekend.
    > > Can anyone give a little more insight, and the best way to do such job?
    > > (The processing is pretty computational gemetry related and also has
    > > some signal processing aspect. in short instead of moving average, it
    > > is some sot of complex mathematical calculation comes into process).

    >
    > It sounds as if you are doing a lot of computation which isn't related to the
    > creation/GCing of objects. As such the potential gains of avoiding GC (even in
    > an environment where GC is slow) are going to be small at best. I.e it doesn't
    > sound as if the extra complication would be worth it.
    >
    > Remember, too, that recyling the objects is not free -- there are the extra
    > costs involved in resetting the obejct's states, adding them to free lists
    > (which would probably involve synchronised code), any additional runtime checks
    > you have to ensure that you are not changing objects when you shouldnt and so
    > on.

    1) Actual case, there are one such queue per user. Say a new user
    starts writing, and a new deque is created, which are attached to each
    one's Session. And one's computation doesn't access or modify to
    other's data. So I don't do any synchronization there.
    2) Only thing I like immutable object, as it protects from accidentally
    modifying data. Not that much for thread safety (as that comes
    relatively free to me, as I have separate Session for each user).
    However as Java doesn't have a const keyword ( which I use heavily in
    C++, and miss very much in Java) I try to have immutable object as
    much as possible. It makes a lots of thing simpler. Only this kind of
    cases I get little confused. It is a typical class of programs !
    Resetting an object is not free, neither memory allocation. But what is
    the cost comparison for Java (in C++ resetting an object is cheap,
    memory allocation in heap is costly. Thus STL do so much copy, but
    little memory allocation, and still is very fast).
    3) I have a little more question. I want a few of my classes to evolve
    over time (i.e they are mutable.) as all of the states are not
    available initially. However if anyone wants it I need to send an
    unmodifyable snapshot of it ( i.e constantify it & send). Again as Java
    do not have const, I am looking for some inner class based
    implementation. Anything specific known regarding that? (like a
    modifier class, If someone gets access to modifier of a class he will
    be able to modify its state, otherwise the class is immutable! ) .

    Thanks for help and suggestion.
    > -- chris
     
    toton, Oct 24, 2006
    #3
  4. Hi,

    concerning your problem of recycling objects, my opinion is clear:

    Do NOT recycle objects. It *may* speed up you app in some cases (while
    it may slow down your app in other cases). Write clean and readable code
    and choose the right data structures and algorithms. If your platform
    does not have enough resources to properly run your application,
    recycling objects will not help very much. In 99% there are more
    disadvantages than advantages.

    To your other question ("const" (which I am missing as well) vs
    "mutability"):

    I have not tested it in a productive environment, but an approach would
    by something like that:

    class UnmodifiableInt {
    protected int i;
    public int getValue() {
    return i;
    }
    }

    class ModifiableInt extends UnmodifiableInt {
    public void setValue(int i) {
    this.i=i;
    }
    }

    Then, you can do the following:

    class Foo
    {

    void bar1(ModifiableInt i)
    {
    }

    void bar2(UnmodifiableInt i)
    {
    }

    void bar()
    {
    UnmodifiableInt ui = new UnmodifiableInt();
    ModifiableInt i = new ModifiableInt();
    bar1(ui); // compiler error
    bar1(i);
    bar2(ui);
    bar2(i);
    }

    }

    For "plain" objects (in contrast to "compound" objects) this should work
    easily.

    Of course it is not "save" because if you have a reference of type
    UnmodifiableInt, it may point to an object of type ModifiableInt, so
    that you could do a cast. But on the other hand, casts are always
    somehow "unsafe"... (IIRC its the same with 'const' which you can "cast
    away")

    On the other hand, even immutable Types like java.lang.String can be
    modified (using reflection).

    Ciao,
    Ingo
     
    Ingo R. Homann, Oct 24, 2006
    #4
  5. toton

    Oliver Wong Guest

    "Ingo R. Homann" <> wrote in message
    news:453e20ac$0$5729$-online.net...
    > Hi,
    >
    > concerning your problem of recycling objects, my opinion is clear:
    >
    > Do NOT recycle objects. It *may* speed up you app in some cases (while it
    > may slow down your app in other cases). Write clean and readable code and
    > choose the right data structures and algorithms. If your platform does not
    > have enough resources to properly run your application, recycling objects
    > will not help very much. In 99% there are more disadvantages than
    > advantages.
    >
    > To your other question ("const" (which I am missing as well) vs
    > "mutability"):
    >
    > I have not tested it in a productive environment, but an approach would by
    > something like that:
    >
    > class UnmodifiableInt {
    > protected int i;
    > public int getValue() {
    > return i;
    > }
    > }
    >
    > class ModifiableInt extends UnmodifiableInt {
    > public void setValue(int i) {
    > this.i=i;
    > }
    > }


    I recommend having 3 classes, instead of 2 (or 2 classes, and 1
    interface):

    interface Int {
    public int getValue();
    }

    final class UnmodifiableInt implements Int {
    protected int i;
    public int getValue() {
    return i;
    }
    }

    final class ModifiableInt implements Int {
    protected int i;
    public int getValue() {
    return i;
    }
    public void setValue(int i) {
    this.i=i;
    }
    }

    The problem with the 2-class design is that it fails the IS-A test of
    inheritance: that is, it should not be the case than a ModifiableInt IS-A
    UnmodifiableInt. So you should not be able to use a ModifableInt anywhere an
    UnmodifiableInt is expected.

    - Oliver
     
    Oliver Wong, Oct 24, 2006
    #5
  6. Hi,

    Oliver Wong wrote:
    > The problem with the 2-class design is that it fails the IS-A test of
    > inheritance: that is, it should not be the case than a ModifiableInt IS-A
    > UnmodifiableInt. So you should not be able to use a ModifableInt anywhere an
    > UnmodifiableInt is expected.


    No, I think, the 2-class-design is better:

    Consider you have a method that wants to indicate that it does not
    change the Parameter:

    void foo(UnmodifiableInt i) {...}

    Now, why should it be impossible to pass a ModifiableInt to that method?

    And vice versa: Consider a method is returning an ModifiableInt:

    ModifiableInt foo() {...}

    Why should it be impossible to assign the returned value to a variable
    of type UnmodifiableInt to document that the variable will not be modified?

    Ciao,
    Ingo
     
    Ingo R. Homann, Oct 25, 2006
    #6
  7. toton

    Chris Uppal Guest

    Ingo R. Homann wrote:

    > Why should it be impossible to assign the returned value to a variable
    > of type UnmodifiableInt to document that the variable will not be
    > modified?


    Because the user of the Unmodifiable should be able to rely on it not, in fact,
    being modified ?

    To some extent this is a documentary issue rather than an OO design issue --
    the question being whether and when the user of an object can assume that that
    object is immutable. For instance the class name "UnmodifiableXxx" strongly
    suggests immutability, the class name "ReadonlyXxxFacade" does not.

    -- chris
     
    Chris Uppal, Oct 25, 2006
    #7
  8. toton

    Chris Uppal Guest

    toton wrote:

    > 2) Only thing I like immutable object, [...]
    > I try to have immutable object as
    > much as possible. It makes a lots of thing simpler.


    That's sensible.


    > Resetting an object is not free, neither memory allocation. But what is
    > the cost comparison for Java (in C++ resetting an object is cheap,
    > memory allocation in heap is costly. Thus STL do so much copy, but
    > little memory allocation, and still is very fast).


    Ah, you are a C++ programmer. You will almost certainly find that your
    intuitions about costs are wrong in the Java world.

    That's for two important reasons: one is that in Java certain operations are
    performed /much/ more often than in C++ (object allocation is a case in point),
    and so they receive a great deal of attention from the JVM implementers. The
    other reason is that Java implementations (at least on desktop machines and
    bigger) tend to be extremely advanced (Sun's JVMs as about close to the
    bleeding edge as you can get), and so the implementation techniques are less
    than obvious, and the mapping from source code to eventual machine code may be
    a lot more indirect than would normally be the case with a C++ program. The
    effect of adaptive optimisation alone makes it hard both to reason about, and
    to measure, performance (BTW, any micro-benchmark -- like the one in your first
    post in this thread -- which does not take account of adaptive optimisation is
    probably completely useless.)

    Now, on desktop (and better) machines object allocation is /very/ fast (only a
    very few instructions -- less than it takes to zero the memory for the newly
    allocated object), and normally it would be a mistake to use object pools
    (might even slow the program down, since the GC algorithms are designed and
    tuned on the -- correct -- assumption that most objects don't survive for very
    long at all). Whether that still applies in your target JVM (on the iPAQ) I
    have no idea. But what you can be fairly sure of is that the target JVM's
    memory handling has been very carefully designed around the hardware's balance
    of CPU speed and memory size. To put it another way, its a fair bet that the
    JVM can manage memory faster than you can do it yourself ;-)


    > 3) I have a little more question. I want a few of my classes to evolve
    > over time (i.e they are mutable.) as all of the states are not
    > available initially. However if anyone wants it I need to send an
    > unmodifyable snapshot of it ( i.e constantify it & send). Again as Java
    > do not have const, I am looking for some inner class based
    > implementation. Anything specific known regarding that? (like a
    > modifier class, If someone gets access to modifier of a class he will
    > be able to modify its state, otherwise the class is immutable! ) .


    I suggest that before you get stuck into complex code to try to replicate C++'s
    pointer-to-const semantics, you should first get some practise with working
    without it. This is (IMO) another case where intuitions trained on C++ are not
    applicable in the Java world; and you may find that the cost/benefit equation
    of "controlled mutability" favours a different balance in Java. Consider that
    in C++ sticking "const" onto some declaration has minimally disruptive effect
    on the source and/or overall design, and has zero cost at runtime. In Java
    there is no equivalent of that mechanism, so controlled immutability (as
    opposed to just creating completely immutable objects) would have a cost in
    both design/code effort, and at runtime. The costs are higher, but the benefit
    is at most the same and may actually be smaller (as a result of Java's
    generally safer and less easy-to-break-accidentally semantics).

    I.e. just don't bother (normally).

    On the fairly rare occasions where you /do/ need to hand out data while
    disallowing changes to it, you should consider at least three options:

    1) Just hand out a copy (remember allocation is cheap in Java). This should
    be your first choice since it is both simple and totally reliable.

    2) Hand out a reference to the data, but in the form of a reference of a type
    which doesn't include mutating operators. Oliver and Ingo have already
    discussed this option. Note that there is not much to prevent the consumer
    from misusing the reference by downcasting it back to the mutable type.

    3) Hand out a helper object which itself has no mutating operations, and which
    implements readonly operations by forwarding them to the "real" object. Thus
    the consumer only ever has controlled access to the real object. Something
    like:

    public class MyStuff
    {
    private RealData m_realData;

    public static class PublicData
    {
    private final RealData m_data;
    PublicData(ReadData data) { m_data = data; }
    public int getX() { return m_data.getX(); }
    }

    private static class RealData
    {
    ....
    int getX() { ... }
    void setX(int x) { ... }
    ....
    }

    public PublicData
    getData()
    {
    return new PublicData(m_realData);
    }
    }

    There's nothing magical about the use of nested classes in the above. They
    might make the code look prettier for this kind of application, but they don't
    add anything semantically different from what you could do with "real"
    (top-level) classes.

    Do note that all these options add complexity and have a runtime cost (which
    may not, in fact, be very great, but it won't be zero). Don't use these
    techniques unless you have a better reason than just a habit carried over from
    C++.

    -- chris
     
    Chris Uppal, Oct 25, 2006
    #8
  9. On 2006-10-25 11:09, Chris Uppal wrote:
    > Ingo R. Homann wrote:
    >
    >> Why should it be impossible to assign the returned value to a
    >> variable of type UnmodifiableInt to document that the variable will
    >> not be modified?

    >
    > Because the user of the Unmodifiable should be able to rely on it
    > not, in fact, being modified ?
    >
    > To some extent this is a documentary issue rather than an OO design
    > issue -- the question being whether and when the user of an object
    > can assume that that object is immutable. For instance the class
    > name "UnmodifiableXxx" strongly suggests immutability, the class
    > name "ReadonlyXxxFacade" does not.


    It seems to me that, as the Collections.unmodifiable*() methods
    suggest, "unmodifiable" does not mean "immutable", but rather mean
    what you call "readonly". "Unmodifiable" is a property of the
    interface (or proxy) type, i.e. the (observable) object state cannot
    be modified via that interface/proxy (but possibly via some other one),
    whereas "immutable" is a property of the class, i.e. instances of such
    a class don't ever change their (observable) state throughout their
    lifetime.

    In any case, however they are named, these are two distinct concepts
    (immutability implies unmodifiability, but not the other way round),
    and their implementation will look different accordingly.

    -- Niklas Matthies
     
    Niklas Matthies, Oct 25, 2006
    #9
  10. Hi,

    Chris Uppal wrote:
    >>Why should it be impossible to assign the returned value to a variable
    >>of type UnmodifiableInt to document that the variable will not be
    >>modified?

    >
    > Because the user of the Unmodifiable should be able to rely on it not, in fact,
    > being modified ?


    Well, I explained my point of view to this in a post before:

    'Of course it is not "save" because if you have a reference of type
    UnmodifiableInt, it may point to an object of type ModifiableInt, so
    that you could do a cast. But on the other hand, casts are always
    somehow "unsafe"... (IIRC its the same with 'const' which you can "cast
    away")
    On the other hand, even immutable Types like java.lang.String can be
    modified (using reflection).'

    Ciao,
    Ingo
     
    Ingo R. Homann, Oct 25, 2006
    #10
  11. toton

    Oliver Wong Guest

    "Ingo R. Homann" <> wrote in message
    news:453f0bb1$0$30329$-online.net...
    > Hi,
    >
    > Oliver Wong wrote:
    >> The problem with the 2-class design is that it fails the IS-A test of
    >> inheritance: that is, it should not be the case than a ModifiableInt IS-A
    >> UnmodifiableInt. So you should not be able to use a ModifableInt anywhere
    >> an UnmodifiableInt is expected.

    >
    > No, I think, the 2-class-design is better:
    >
    > Consider you have a method that wants to indicate that it does not change
    > the Parameter:
    >
    > void foo(UnmodifiableInt i) {...}
    >
    > Now, why should it be impossible to pass a ModifiableInt to that method?


    It depends on the situation, of course, but what if foo, for example,
    uses i as the key in a hashtable, on the assumption that the hashcode for i
    will never change. Then passing in a ModifiableInt might cause a lot of
    problems.

    You could simulate your intended behaviour in the 3-class (or
    2-class+1-interface) design as:

    void foo(Int i) { ... }

    Where Int is the interface/class which only has the getter, but makes no
    guarantee about whether or not i is immutable. I.e. you could pass
    ImmutableInt or MutableInt to foo, because both classes implement/extend
    Int.

    >
    > And vice versa: Consider a method is returning an ModifiableInt:
    >
    > ModifiableInt foo() {...}
    >
    > Why should it be impossible to assign the returned value to a variable of
    > type UnmodifiableInt to document that the variable will not be modified?


    Similarly, you could assign this to a reference of type Int if you don't
    care about modifiability.

    However, I realize now that I had assumed "unmodifiable" was synonymous
    with "immutable", but Chris' and Niklas' posts indicate that some
    programmers may interpret a difference between these two terms.

    - Oliver
     
    Oliver Wong, Oct 25, 2006
    #11
  12. Hi,

    Oliver Wong wrote:
    >>void foo(UnmodifiableInt i) {...}
    >>
    >>Now, why should it be impossible to pass a ModifiableInt to that method?

    >
    > It depends on the situation, of course, but what if foo, for example,
    > uses i as the key in a hashtable, on the assumption that the hashcode for i
    > will never change. Then passing in a ModifiableInt might cause a lot of
    > problems.


    Ah, OK, perhaps that's what Chris meant as well (I interpreted his
    answer diffently (that the value could be changed by casting the
    reference to a ModifiableInt)... post cancelled).

    Good reason!

    Ciao,
    Ingo
     
    Ingo R. Homann, Oct 25, 2006
    #12
  13. "Oliver Wong" <> writes:

    > "Ingo R. Homann" <> wrote in message
    > news:453f0bb1$0$30329$-online.net...


    >> void foo(UnmodifiableInt i) {...}
    >>
    >> Now, why should it be impossible to pass a ModifiableInt to that method?

    >
    > It depends on the situation, of course, but what if foo, for example,
    > uses i as the key in a hashtable, on the assumption that the hashcode for i
    > will never change. Then passing in a ModifiableInt might cause a lot of
    > problems.


    Nevermind the problems, just the name is enough to disqualify this
    approach. After all, one would have to say:
    "ModifiableInt is-a UnmodifiableInt"
    That's incorrect, so either the names or the inheritance is wrong.

    If anything, it should be something like ModifiableInt and ReadableInt,
    because the modifiable int is a readable int.

    /L
    --
    Lasse Reichstein Nielsen -
    DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
    'Faith without judgement merely degrades the spirit divine.'
     
    Lasse Reichstein Nielsen, Oct 25, 2006
    #13
  14. On 2006-10-25 15:06, Lasse Reichstein Nielsen wrote:
    :
    > Nevermind the problems, just the name is enough to disqualify this
    > approach. After all, one would have to say:
    > "ModifiableInt is-a UnmodifiableInt"
    > That's incorrect, so either the names or the inheritance is wrong.
    >
    > If anything, it should be something like ModifiableInt and ReadableInt,
    > because the modifiable int is a readable int.


    I would suggest:

    interface Int { int getValue(); }

    interface ModifiableInt extends Int { void setValue(int value); }

    class ImmutableInt implements Int
    {
    private final int value;
    public ImmutableInt(int value) { this.value = value; }
    public int getValue() { return value; }
    }

    class MutableInt implements ModifiableInt
    {
    private int value;
    public MutableInt(int value) { this.value = value; }
    public int getValue() { return value; }
    public void setValue(int value) { this.value = value; }
    }

    -- Niklas Matthies
     
    Niklas Matthies, Oct 25, 2006
    #14
  15. toton

    Oliver Wong Guest

    "Niklas Matthies" <> wrote in message
    news:...
    >
    > I would suggest:
    >
    > interface Int { int getValue(); }
    >
    > interface ModifiableInt extends Int { void setValue(int value); }
    >
    > class ImmutableInt implements Int
    > {
    > private final int value;
    > public ImmutableInt(int value) { this.value = value; }
    > public int getValue() { return value; }
    > }
    >
    > class MutableInt implements ModifiableInt
    > {
    > private int value;
    > public MutableInt(int value) { this.value = value; }
    > public int getValue() { return value; }
    > public void setValue(int value) { this.value = value; }
    > }


    2 classes + 2 interfaces? Now that's just being crazy. ;)

    - Oliver
     
    Oliver Wong, Oct 25, 2006
    #15
  16. toton

    Rogan Dawes Guest

    Chris Uppal wrote:
    > toton wrote:
    >
    >> 2) Only thing I like immutable object, [...]
    >> I try to have immutable object as
    >> much as possible. It makes a lots of thing simpler.

    >
    > That's sensible.
    >
    >
    >> Resetting an object is not free, neither memory allocation. But what is
    >> the cost comparison for Java (in C++ resetting an object is cheap,
    >> memory allocation in heap is costly. Thus STL do so much copy, but
    >> little memory allocation, and still is very fast).

    >
    > Ah, you are a C++ programmer. You will almost certainly find that your
    > intuitions about costs are wrong in the Java world.
    >
    > That's for two important reasons: one is that in Java certain operations are
    > performed /much/ more often than in C++ (object allocation is a case in point),
    > and so they receive a great deal of attention from the JVM implementers. The
    > other reason is that Java implementations (at least on desktop machines and
    > bigger) tend to be extremely advanced (Sun's JVMs as about close to the
    > bleeding edge as you can get), and so the implementation techniques are less
    > than obvious, and the mapping from source code to eventual machine code may be
    > a lot more indirect than would normally be the case with a C++ program. The
    > effect of adaptive optimisation alone makes it hard both to reason about, and
    > to measure, performance (BTW, any micro-benchmark -- like the one in your first
    > post in this thread -- which does not take account of adaptive optimisation is
    > probably completely useless.)
    >


    As a counterpoint to Chris's comments, note that Swing reuses objects in
    many cases, most notably renderers, for performance reasons.

    From the JavaDocs for DefaultTableCellRenderer:

    Implementation Note: This class inherits from JLabel, a standard
    component class. However JTable employs a unique mechanism for rendering
    its cells and therefore requires some slightly modified behavior from
    its cell renderer. The table class defines a single cell renderer and
    uses it as a as a rubber-stamp for rendering all cells in the table; it
    renders the first cell, changes the contents of that cell renderer,
    shifts the origin to the new location, re-draws it, and so on. The
    standard JLabel component was not designed to be used this way and we
    want to avoid triggering a revalidate each time the cell is drawn. This
    would greatly decrease performance because the revalidate message would
    be passed up the hierarchy of the container to determine whether any
    other components would be affected. So this class overrides the
    validate, revalidate, repaint, and firePropertyChange methods to be
    no-ops. If you write your own renderer, please keep this performance
    consideration in mind.

    Rogan
     
    Rogan Dawes, Oct 25, 2006
    #16
  17. On 2006-10-25 16:10, Oliver Wong wrote:
    > "Niklas Matthies" <> wrote in message
    > news:...
    >>
    >> I would suggest:
    >>
    >> interface Int { int getValue(); }
    >>
    >> interface ModifiableInt extends Int { void setValue(int value); }
    >>
    >> class ImmutableInt implements Int
    >> {
    >> private final int value;
    >> public ImmutableInt(int value) { this.value = value; }
    >> public int getValue() { return value; }
    >> }
    >>
    >> class MutableInt implements ModifiableInt
    >> {
    >> private int value;
    >> public MutableInt(int value) { this.value = value; }
    >> public int getValue() { return value; }
    >> public void setValue(int value) { this.value = value; }
    >> }

    >
    > 2 classes + 2 interfaces? Now that's just being crazy. ;)


    You won't have to use them all at the same time. :)
    Clients will only "see" either Int, ModifiableInt or (if the guarantee
    of immutability really needs to be made explicit) ImmutableInt.

    You could also drop MutableInt and instead implement it directly in
    ModifiableInt, but this would remove the flexibility of passing a
    differently-implemented ModifiableInt to clients. With a simple int
    this might not seem so probable, but think of ModifiableList or
    similar.

    Take the collections framework for example. A better design would have
    been to make the Collection interface "unmodifiable" (i.e. with all
    the mutating methods removed) and provide a ModifiableCollection
    interface that extends it with the mutating methods. Same for List,
    Map, Set and so on. Then ArrayList would implement ModifiableList,
    but you could still simply pass it to clients as just List and be
    certain that they don't modify it (unless they attempt to cast it to
    ModifiableList) instead of having to wrap it into an "unmodifiable"
    proxy. In addition the framework could provide one ImmutableList class
    that implements List and whose constructor takes an arbitrary List
    whose elements would be copied to become the contents of the
    ImmutableList (which would then be really immutable instead of just
    unmodifiable).

    To illustrate the analogy with the interfaces/classes above:

    Int ~ List
    ModifiableInt ~ ModifiableList
    ImmutableInt ~ ImmutableList
    MutableInt ~ ArrayList, LinkedList, ...

    So, yes, it's one additional interface (ModifiableList) and one
    additional class (ImmutableList), but it would be much sounder than
    the existing design (where you get UnsupportedOperationExceptions),
    and it can be used with all List implementations, so it amortizes
    pretty well.

    Of course, having something like C++'s "const" (or rather its inverse:
    a "modifiable" qualifier) would be even better.

    -- Niklas Matthies
     
    Niklas Matthies, Oct 25, 2006
    #17
  18. toton

    Chris Uppal Guest

    Rogan Dawes wrote:

    > As a counterpoint to Chris's comments, note that Swing reuses objects in
    > many cases, most notably renderers, for performance reasons.


    Indeed, yes.

    Still, I'd like to make a couple of observations (I'm not disagreeing, you
    understand, just expanding on a good point):

    I really should have been clearer that I was refering to the time taken to
    allocate the memory -- the time taken to initalise the object that will live in
    that memory is, of course, dependent on the object itself, and may take an
    arbitrarily long time.

    public class Ouch
    {
    publich Ouch() { for (;;); }
    }

    ;-)

    Also, if wouldn't advise newcomers to Java to take Swing as an example of
    either good /or/ typical Java programming.

    -- chris
     
    Chris Uppal, Oct 26, 2006
    #18
  19. toton

    toton Guest

    Chris Uppal wrote:
    > toton wrote:
    >
    > > 2) Only thing I like immutable object, [...]
    > > I try to have immutable object as
    > > much as possible. It makes a lots of thing simpler.

    >
    > That's sensible.
    >
    >
    > > Resetting an object is not free, neither memory allocation. But what is
    > > the cost comparison for Java (in C++ resetting an object is cheap,
    > > memory allocation in heap is costly. Thus STL do so much copy, but
    > > little memory allocation, and still is very fast).

    >
    > Ah, you are a C++ programmer. You will almost certainly find that your
    > intuitions about costs are wrong in the Java world.

    Yes, I "see" Java memory allocations are much faster than C++ new
    allocation (dynamic one). Java dynamic allocation almost competes with
    C++ stack based (static) allocation!
    Maybe someday Java will have an @valueType attribute to "help" memory
    allocation for non-polymorphic objects (final objects), and the
    collection will "hold" the value type objects! Who knows!
    > That's for two important reasons: one is that in Java certain operations are
    > performed /much/ more often than in C++ (object allocation is a case in point),
    > and so they receive a great deal of attention from the JVM implementers. The
    > other reason is that Java implementations (at least on desktop machines and
    > bigger) tend to be extremely advanced (Sun's JVMs as about close to the
    > bleeding edge as you can get), and so the implementation techniques are less
    > than obvious, and the mapping from source code to eventual machine code may be
    > a lot more indirect than would normally be the case with a C++ program. The
    > effect of adaptive optimisation alone makes it hard both to reason about, and
    > to measure, performance (BTW, any micro-benchmark -- like the one in your first
    > post in this thread -- which does not take account of adaptive optimisation is
    > probably completely useless.)

    Heard sun is opening up its C++ sourcecode for JIT , eager to look at
    the "bleeding edge" techniques.
    > Now, on desktop (and better) machines object allocation is /very/ fast (only a
    > very few instructions -- less than it takes to zero the memory for the newly
    > allocated object), and normally it would be a mistake to use object pools
    > (might even slow the program down, since the GC algorithms are designed and
    > tuned on the -- correct -- assumption that most objects don't survive for very
    > long at all). Whether that still applies in your target JVM (on the iPAQ) I
    > have no idea. But what you can be fairly sure of is that the target JVM's
    > memory handling has been very carefully designed around the hardware's balance
    > of CPU speed and memory size. To put it another way, its a fair bet that the
    > JVM can manage memory faster than you can do it yourself ;-)

    That always one programmer wants! But a human never wants a machine to
    overperform him! what a irony!
    >
    > > 3) I have a little more question. I want a few of my classes to evolve
    > > over time (i.e they are mutable.) as all of the states are not
    > > available initially. However if anyone wants it I need to send an
    > > unmodifyable snapshot of it ( i.e constantify it & send). Again as Java
    > > do not have const, I am looking for some inner class based
    > > implementation. Anything specific known regarding that? (like a
    > > modifier class, If someone gets access to modifier of a class he will
    > > be able to modify its state, otherwise the class is immutable! ) .

    >
    > I suggest that before you get stuck into complex code to try to replicate C++'s
    > pointer-to-const semantics, you should first get some practise with working
    > without it. This is (IMO) another case where intuitions trained on C++ are not
    > applicable in the Java world; and you may find that the cost/benefit equation
    > of "controlled mutability" favours a different balance in Java. Consider that
    > in C++ sticking "const" onto some declaration has minimally disruptive effect
    > on the source and/or overall design, and has zero cost at runtime. In Java
    > there is no equivalent of that mechanism, so controlled immutability (as
    > opposed to just creating completely immutable objects) would have a cost in
    > both design/code effort, and at runtime. The costs are higher, but the benefit
    > is at most the same and may actually be smaller (as a result of Java's
    > generally safer and less easy-to-break-accidentally semantics).
    >
    > I.e. just don't bother (normally).

    It is again like, I want an immutable class, but the class is big! How
    to set all of the fields within constructor? It will be a huge list.
    I have a Document class, which has name, address , and many other
    fields. Now this class can load its fields from different types of
    files, some are XML based, some simply name value pair. Now, the
    Document need not to know the parsing logic, it is separated. A parser
    for each type parses the file, and sets the field in the Document. and
    when done, Document is ready, an immutable class. No more modification
    is allowed. To make it immutable I need to pass all of the parameters
    to the Document ctor, which is a long list (say 20 fields). Other thing
    I can have is setters, which makes it mutable.
    I "feel" there must be a better way. Like I make Document an inner
    class for an abstract class Parser (or an interface) which all of the
    specific parsers implement! Thus all of the parsers can access the
    Document fields and set them. But no setters, thus no one else can do
    it. Not sure about the idea ( I am not sure about the inner classes ).
    > On the fairly rare occasions where you /do/ need to hand out data while
    > disallowing changes to it, you should consider at least three options:
    >
    > 1) Just hand out a copy (remember allocation is cheap in Java). This should
    > be your first choice since it is both simple and totally reliable.
    >
    > 2) Hand out a reference to the data, but in the form of a reference of a type
    > which doesn't include mutating operators. Oliver and Ingo have already
    > discussed this option. Note that there is not much to prevent the consumer
    > from misusing the reference by downcasting it back to the mutable type.
    >
    > 3) Hand out a helper object which itself has no mutating operations, and which
    > implements readonly operations by forwarding them to the "real" object. Thus
    > the consumer only ever has controlled access to the real object. Something
    > like:
    >
    > public class MyStuff
    > {
    > private RealData m_realData;
    >
    > public static class PublicData
    > {
    > private final RealData m_data;
    > PublicData(ReadData data) { m_data = data; }
    > public int getX() { return m_data.getX(); }
    > }
    >
    > private static class RealData
    > {
    > ....
    > int getX() { ... }
    > void setX(int x) { ... }
    > ....
    > }
    >
    > public PublicData
    > getData()
    > {
    > return new PublicData(m_realData);
    > }
    > }
    >
    > There's nothing magical about the use of nested classes in the above. They
    > might make the code look prettier for this kind of application, but they don't
    > add anything semantically different from what you could do with "real"
    > (top-level) classes.
    >
    > Do note that all these options add complexity and have a runtime cost (which
    > may not, in fact, be very great, but it won't be zero). Don't use these
    > techniques unless you have a better reason than just a habit carried over from
    > C++.

    In the meantime writting a Java "preprocessor" which recognizes const
    keyword and do check! However no runtime check. In progress ! Will add
    a good skill to my compiler knowledge! Not something serious, Just for
    fun! The Java project is also my personal one only, as a hobby.

    Thanks all for the long discussion and suggestions and advices!.
    > -- chris
     
    toton, Oct 26, 2006
    #19
  20. toton

    toton Guest

    Chris Uppal wrote:
    > Rogan Dawes wrote:
    >
    > > As a counterpoint to Chris's comments, note that Swing reuses objects in
    > > many cases, most notably renderers, for performance reasons.

    >
    > Indeed, yes.
    >
    > Still, I'd like to make a couple of observations (I'm not disagreeing, you
    > understand, just expanding on a good point):
    >
    > I really should have been clearer that I was refering to the time taken to
    > allocate the memory -- the time taken to initalise the object that will live in
    > that memory is, of course, dependent on the object itself, and may take an
    > arbitrarily long time.
    >
    > public class Ouch
    > {
    > publich Ouch() { for (;;); }
    > }
    >
    > ;-)
    >
    > Also, if wouldn't advise newcomers to Java to take Swing as an example of
    > either good /or/ typical Java programming.

    And here, the O.P. ( Myself) is not a new comer in Java World. He
    professionally worked with some big company in Java (now in a small
    company, with C++ , and more in research field :( ) . But all those
    programs are really trivial (You know EJB , Servlet, Hibernate etc) ,
    doesn't require much in-depth knowledge about the language itself. But
    when it comes with his personal interses, he goes a little deep and
    explores the possiblities, problems and solutions, as here no
    timeframe, no rulebook no project leader! His interests are in language
    construction (among others) and developed a nearly full compiler for
    Java, which compiles a Java programm, and you can run it!
    Thanks
    > -- chris
     
    toton, Oct 26, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Carlo v. Dango

    how to mutate a tuple?

    Carlo v. Dango, Oct 14, 2003, in forum: Python
    Replies:
    10
    Views:
    876
    John Roth
    Oct 14, 2003
  2. mike p.
    Replies:
    1
    Views:
    324
    Terry Reedy
    Feb 27, 2004
  3. Bruno Desthuilliers

    Re: mutate dictionary or list

    Bruno Desthuilliers, Sep 7, 2010, in forum: Python
    Replies:
    0
    Views:
    506
    Bruno Desthuilliers
    Sep 7, 2010
  4. Rick Johnson
    Replies:
    51
    Views:
    631
    Rick Johnson
    Feb 12, 2013
  5. Jean-Michel Pichavant
    Replies:
    0
    Views:
    106
    Jean-Michel Pichavant
    Feb 11, 2013
Loading...

Share This Page