----- "Gilles Sadowski" <[email protected]> a écrit :
> Hello.
Hi Gilles,
>
> Would you consider implementing a _mutable_ 3D-vector class?
> A crude benchmark which I just did shows that re-using the same object
> is
> always (if sometimes only slightly) more efficient than re-creating
> it.
3D vectors have been changed from mutable to immutable for both robustness and
efficiency reasons ...
When small benchmarks are set up, the overall context is completely under
control and instances are created/used/reused in a specific use case,
corresponding to a simplified view. In these cases, instances modification
appear faster and manageable.
Real life situations with complex systems are not that simple.
Here is a summary of a real case problem, encountered on an operational library
using commons-math and Vector3D before it was turned to immutable. In a complex
application with lots of data sharing and time-dependent data, we wrote
something like:
Vector3D computeMotion(Trajectory trajectory) {
Vector3D initialPosition = trajectory.getCurrentPosition();
complexAlgorithm.processTrajectory(trajectory, targetDate);
Vector3D finalPosition = trajectory.getCurrentPosition();
return finalPosition.subtract(initialPosition);
}
The team developing computeMotion and the team developing Trajectory worked
apart from one another.
With mutable vector, you must be sure the two teams are aware that at each
interface they must really know who is responsible for the data, the caller or
the callee. They may decide that getCurrentPosition should build and return a
new vector, which belongs to the caller which can do what it wants with it,
including modifying it. In this case, two vectors are built since getPosition
is called twice and processTrajectory has no implementation constraint. They
may decide that the getCurrentPosition should return a reference to an internal
vector, then computeMotion should be rewritten to clone initialPosition before
finalPosition is retrieved. They should also know if the clone must be created
before or after the processTrajectory call because the internal reference may
be modified internally. Failing to have a very precise interface definition
which includes the responsibilities at each level leads to difficult to find
bugs.
In order to avoid these bugs, you often resort in using defensive programming
and adding a copy yourself, just in case the other team did not do its job
properly. In some case, when what you develop is by itself an intermediate
library and you don't know how the instances you create will be used, you
*must* do this copy.
This leads to a strange result: you have a potentially buggy code if one of the
team forgot to do defensive programming properly and you have a code that is
really inefficient just because everybody copies everything even when in fact
it is not needed.
With immutable object, on the other hand, you really don't have to worry at
all. People cannot change the object whatever they do, so you just keep
references around and create new instances when you want to change one
coordinates. You cannot do otherwise and don't rely on programming rules or
developers being smart. There are much fewer bugs and since new instances are
created only when needed, at the end you have not that much allocations.Here is
a good article about immutable objects:
<http://www.ibm.com/developerworks/java/library/j-jtp02183.html>
At the end, it appears that for complex applications with several layers, there
are more copies and allocations with mutable objects than with immutable
objects!
Another point to note is that the generational garbage collectors work better
with really short lived objects. So small immutable instances are handled
quickly and allocation should not be feared. It is efficient now, see
<http://www.ibm.com/developerworks/java/library/j-jtp09275.html>.
The points above are not theoretical one. Vector3D was mutable and it cost us
weeks of works at that time to track difficult bugs in a complex application.
This was not a simple problem of communication: I was involved in all teams
from commons-math to high level application, the rest of the team was just
around me and we exchanged lots of information. After we changed to immutable,
all problems were gone and we didn't notice any performance drawback. In fact,
another team in another project facing huge performances problems looked at
what we have done and changed also their objects to immutable: they got
significant performance improvements after that change because their code was
copying everything beforehand and it was not needed anymore afterward.
Luc
>
> [I can help with the editing work.]
>
> Best,
> Gilles
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]