--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
--
Fabrizio Giudici - Java Architect, Project Manager
Tidalwave s.a.s. - "We make Java work. Everywhere."
java.net/blog/fabriziogiudici - www.tidalwave.it/people
Fabrizio...@tidalwave.it
While I understand the performance improvements because of no more locks
This does take a little getting used to, the "new" way often involves
making a database update through a DSL expression (like a SQL update
statement, which leaves the original object intact and just changes
the data in the database), and then re-querying the object to get it
in its new state, rather than just updating fields and saving the new
object.
Of course, there's also the reduction (and eventually total eradication)
of deadlock risks.
--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
Hi Dick,
I am on the (not so short) list of those that don't believe that immutability is the cure all for concurrency. I counter your Brian, Doug and Guy with Cliff Click. And, I'm not sure that Brian is completely on the list of immutability. Doug clearly has a number of mutable thread safe fully concurrent data structures at least one of which is lock-less and wait-free! RIch Hickey is another that you can take off of the list that immutability is the cure to all that is evil about concurrency. I softened him up in Aarhus and Cliff finished him off at the Java Language Summit.
So, what is wrong with immutability. On the surface, nothing. And if used judiciously, I'm ok with using it. However, used liberally and you will end up with a system that will run slowly for no apparent reason. The no apparent reason is because the measurement that you need to consider is CPU write channel bandwidth to memory. This is a measure that very very few people consider but it is a measure that is becoming increasingly important. A few years ago I would have never seen an application who's performance would have been effected by the capacity of the CPU to write data to memory but since then, I have started running into a couple of applications that are putting enough pressure on that part of the hardware that it has had a significant impact on performance. Immutability only increases the pressure on this up and coming bottleneck. This is also a testament to the much improved performance of the JVM
Two factors why the situation isn't going to get better any time soon.
Your comments on GC are completely correct, catching a short lived objects (those caught in Eden) is almost a 0 cost operation. That said, (dead) objects will still pushed from the CPU to memory. CPU's are getting faster and memory at a rate of about 8% per year. That means that CPU starvation is going to increasingly be a bigger problem than it already is. The ability of the CPU to generate data is already outstripping the ability to get it out of the CPU and that is only going to get worse. According to Azul studies, 50% of the memory bandwidth is being consumed by writing *dead* objects to memory. There is a hardware solution to this problem but it is specific to Java and consequently is unlikely to show up in an Intel or AMD CPU any time soon. Again, Immutability will only increase the pressure.
I believe you when you say that you don't notice the effects of immutability on your Scala application. I've had the pleasure of performance tuning a Scala app and have also sat with Bill (Venners) and Martin (Odersky) measuring and diagnosing performance problems in Bill's build tool and the compiler. In all cases I found plenty of other issues that would most likely prevent a Scala application from being able to put so much pressure.
I don't want to take anything away from Scala, I think it's a great language that offers some great features and there are definitely benefits to using it. But, instead of relying immutability exclusively we need to also consider alternate styles of concurrency like those suggested by Doug's WorkTransferQueue, Cliff's NonBlockingConcurrentHashMap and in those coding styles, my almost FIFOQueue. The later two rely on state machines to handle transitions. I would never claim to be clever enough to come up with a NonBlockingConcurrentHashMap but I do understand how it works and why certain decisions were made a key points in the implementation. Ok, maybe this is a wee bit more complicated than straight up immutability but then we don't have to be geniuses like Doug, Cliff, Brian, Rich, Guy.... we just need to learn how to ride on the coat sleeves of these guys.
Regards,
Kirk
How is the list for those that think it is a cure for easy to reason
about programs? There is some comfort knowing that a String will
never change value. It is nice to extend that comfort to other values
in the program.
Regards,
Kirk
Hmm... sounds like you are talking more about complex datastructures.
I'm typically more concerned with immutability in value types. And, I
ultimately wouldn't even care if the actual representation of the
String I'm using is mutated behind me. Interned for example. What I
care about is the value that I get when I use it stays the same. This
is similar to the GC argument. I don't care if my object stays put in
memory after I construct it. Only that I always get back to the same
object when I reference it.
Now, I know there are "persistent" datastructures. My understanding
is the majority of those actually use mutations behind the scenes.
(At least the complex ones. I confess I have not read all of
Functional Datastructures. Much less understood it.)
> That encourages monoliths.
how so?
Kirk
--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
Ok, I confess to skimming it, but I love the conclusion section. I
had never given thought to the whole L/R-brain ideas as they are
addressed towards programing. Thanks for the link!!
Agreed, but objects' design must be sealed... not only for immutability
and persistence, but for the sake of God (not the object).
On 06/17/2011 05:19 PM, Ricky Clarkson wrote:Agreed, but objects' design must be sealed... not only for immutability and persistence, but for the sake of God (not the object).
As soon as it becomes easier to 'just add this new bit of
functionality here so it can access the internal state' even if
naturally it doesn't belong there, you're on the path towards God
objects.
I'm happy to hear you say that immutability isn't a silver bullet. But the message is still coming in strong that it is and as I mentioned before, the problem isn't with GC. As you've mentioned, the cost of gc'ing an object in eden is almost nothing. It's never visited, it's never copied and in fact, they are never collected, the memory they occupy is placed back on the free list in one pointer reset. In fact, there really isn't a free list in any of the young gen memory pools. So, thats not the problem as GC for very short lived objects is cheap. The problem is, these short lived objects *still* need to be written out to RAM and that is the problem. Object lifecycle in the VM has gotten so good that it is not possible to have a collector running at close to 100% efficiency yet have memory management be the main bottleneck in your application and this is due to write bandwidth pressure. My lunch time argument with Rich was not in disagreement with is POV or PIT structures that he sets up in Clojure, it's the immutability that he uses to create these large data structures. Ultimately, (unless hardware changes significantly) these structures will limit scalability. My point was backed up with Cliff's talk at the summit on how modern hardware works. My later conversations with Rich indicates that he did not fall off of the immutability bandwagon (sorry didn't want to suggest something that strongly) but he has recognized that he needs to do more if performance is an issue.
As for your DB example.... it's a perfect place to punt a heavy transactional engine and just by doing that you will see a huge saving (or performance boost). This is something that I recommend people do quite often. In fact it was a recommendation that I made just last week to a client that clearly had mostly read occasionally write. In this case the occasional write can be managed quite easily without synchronization or immutability. In fact, it can be managed very easily with an AtomicReference. The write is not that complex using AtomicReference. It did require a wee bit of thought but in the end, it's not that more complex than "simply" making the structure immutable. I suggest that everyone look at Cliff's excellent work in this area. If what you're suggesting is that most normal programmers wouldn't be able to have created Cliff's or Doug's work then we are in total agreement. But if you're suggesting that we can't understand or expand on the ideas after understanding then.... I often present Cliff's work (Lock free) or Doug's work (wait free) and I offer a few examples of were one can provide some useful extensions.
Again, I'm not against immutability, it just seems that we've all picked up on that sound bite and have forgotten all of the other colors that make the world interesting.
Regards,
Kirk
It always is but then we find that we hit a scalability wall. I wouldn't go for a complex solution as that would be a premature optimization. However, I don't believe that many of the mutable solutions are really that extraordinarily complex. Especially when you have the smart guys sorting out the complexities for you.
Regards,
Kirk
Use case: We have an Account (persistent object) for which we bill at
the end of the year, and various other situations, such as a transfer
of ownership.
We have a calculation engine which calculates what an invoice should
be for the Account. We need to update the Account with the results of
that calculation. The calculation engine has lots of deep and dark
magic. We show the user what the results will be for a particular
operation, and the user can cancel an operation. Obviously, if the
operation is cancelled we don't want to update the account in any way.
For a transfer, we have two calculations with different parameters for
the same Account, for the old and new owner.
We had two options:
1) Update the account directly in the calculation engine.
Plus points: simple to understand, minus: we have to reread the
account from the database each time we do a cancel. Worse, for a
transfer, we have to do funky stuff to ensure that both calculations
can happen on the same Account without one affecting the other.
2) In the calculation engine, assume that the Account object is
immutable, and cannot be changed. The engine returns a (new)
Calculation object for each call.
Plus points: This makes multiple calculations on an Account much
easier to manage. We can cancel a calculation much more easily. When
reading the code, we know exactly what the calculation engine does: it
creates the Calculation object. The results of a calculation are a
Calculation object, not an updated Account. This makes it easier to
grok, and also easier to test. Minus points: less performant.
1) is clearly more performant than 2. 2 has more code (we have to
update the Account object outside the calculation engine), and will be
slower (creation of a Calculation object, more passing around inside
the calculation engine). However, 2 is a much better solution. It has
more safety (persistent objects not updated until after user
confirmation), testability (we have to compare the Calculation object,
not Account), we can reason about it.
Please note that Account is not actually immutable (it's an object
persisted to the database using hibernate, there are lots of getters &
setters involved). Calculation IS, but only to make subsequent use of
the object more secure, and it's not persisted.
When I consider immutability, I'm not usually concerned about
performance, or multi-threading, it just helps me think a bit clearer.
Even thinking of something as immutable can lead to a better solution.
It's one more tool in the box.
Have fun.
Matthew.
2011/6/21 Steve Lindsay <stephen....@gmail.com>:
errr, profilers don't find write bandwidth bottlenecks in large applications. There is a *lot* more to profiling then just blindly throwing an execution profiler at an application.
If a function can be substituted with a constant return it wasn't much of a function was it.. and again, having an object take responsibility for it's internal state takes care of a lot of problems. Just look at actors.
Regards,KirkOn Jun 21, 2011, at 10:27 AM, Kevin Wright wrote:On 21 June 2011 03:40, Steve Lindsay <stephen....@gmail.com> wrote:
On Jun 21, 3:01 am, Kirk <kirk.pepperd...@gmail.com> wrote:Hasn't most of the immutability push (outside of this thread at least)
>
> Again, I'm not against immutability, it just seems that we've all picked up on that sound bite and have forgotten all of the other colors that make the world interesting.
>
been about safety, maintainability, ability to reason about complexity
etc., rather than performance?Oh absolutely. It's very refreshing being able to see some value declared at the top of a class and being certain that it's exactly the same thing further down the file. This becomes even more useful if you want to be certain that some other thread also hasn't fiddled with it.It's also much easier dealing with pure functions, guaranteed to always do the same thing for the same input and not have side effects. Referential integrity means that you can substitute a function call with its precalculated result; this particular optimisation is almost as old as programming itself, with one classic example being a lookup table of trigometric functions.So dropping immutability is a very useful optimisation, but it certainly isn't the only one in our toolbox, and there are other optimisations that immutability makes possible. As always, we're better off starting with clean and provably correct code, then letting a profiler be our guide as to where speedups can be found.--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
--
You received this message because you are subscribed to the Google Groups "The Java Posse" group.
To post to this group, send email to java...@googlegroups.com.
To unsubscribe from this group, send email to javaposse+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javaposse?hl=en.
Not trying to speak for Kevin, but I assume he was talking about memoization
of functions, not functions that returned a constant.
I've found attempting this effect with several objects is more elegant if you
can rely on the objects being side-effect-free and "wrapping" them with
memoization behaviour, rather than implementing it in the internals of each
object. Again, this is more a concern of readability and reasoning than
performance, particularly where disk/network IO is the likely performance
hindrance.
Kind regards,
Graham