Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   Java (http://www.velocityreviews.com/forums/f30-java.html)
-   -   Why "lock" functionality is introduced for all the objects? (http://www.velocityreviews.com/forums/t750601-why-lock-functionality-is-introduced-for-all-the-objects.html)

Alex J 06-28-2011 09:29 AM

Why "lock" functionality is introduced for all the objects?
 
I'm curious why Java designers once decided to allow every object to
be lockable (i.e. allow using lock on those).
I know, that out of such a design decision every Java object contain
lock index, i.e. new Object() results in allocation of at least 8
bytes where 4 bytes is object index and 4 bytes is lock index on 32-
bit JVM.
I think that it just inefficient waste of space, because not all the
objects requires to be lockable/waitable.

The better decision, IMHO, would be to introduce lock/wait mechanics
for only, say, the Lockable descendants.
The current approach seems to be very simple, but is the performance
penalty so small for not be taken into an account?
Eclipse uses tons of small objects and I guess that is why it consumes
so much memory while a significant part of it is never used.

What do you think of it?

blmblm@myrealbox.com 06-28-2011 03:56 PM

OT "sic" (was Re: Why "lock" functionality is introduced for all the objects?
 
In article <iuce66$2nh$1@news.albasani.net>, Lew <noone@lewscanon.com> wrote:
> Alex J wrote:
> > I'm curious why Java designers once decided to allow every object to
> > be lockable (i.e. [sic] allow using lock on those).


"[sic]"? The only thing that seems wrong here to me is the absence
of a comma after "i.e.". Have I missed an error here ....

[ snip ]

> > The better decision, IMHO, would be to introduce lock/wait mechanics
> > for only, say, the Lockable descendants.

>
> Oh, yeah, your opinion is humble.


Seemed that way to me. Your reply, Lew, seems a little testy even
by your standards. Just sayin'. <shrug>

[ snip ]

--
B. L. Massingill
ObDisclaimer: I don't speak for my employers; they return the favor.

Lew 06-28-2011 04:19 PM

Re: OT "sic" (was Re: Why "lock" functionality is introduced forall the objects?
 
blmblm@myrealbox.com wrote:
> Lew wrote:
>> Alex J wrote:
>>> I'm curious why Java designers once decided to allow every object to
>>> be lockable (i.e. [sic] allow using lock on those).

>
> "[sic]"? The only thing that seems wrong here to me is the absence
> of a comma after "i.e.". Have I missed an error here ....


That'd be it. Good eye.

The trouble I had with "IMHO" is the guy spouting off about supposed
inefficiencies in Java with regard to one of the most key features of the
language, and presuming to offer a so-called "better" solution out of sheer
ignorance. That is the antithesis of humility.

--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedi.../c/cf/Friz.jpg

Michal Kleczek 06-28-2011 04:41 PM

Re: Why "lock" functionality is introduced for all the objects?
 
Lew wrote:

> Alex J wrote:
>> I'm curious why Java designers once decided to allow every object to
>> be lockable (i.e. [sic] allow using lock on those).

>
> Because that makes it possible to do concurrent programming intrinsically.
>


Could you elaborate more on that?
Do you mean there is no other way to do it?

I find this question quite intriguing as well since it looks quite useless
for example to be able to lock on java.lang.Integer instance (and it is
strange for me that java.lang.Integer instance occupies much more memory as
int). Surely a compromise must have been done taking into account various
language features ("synchronized" keyword, lack of multiple inheritance,
lack of closures) - but I am not that knowlegeable enough to explain this
compromise in detail.

>> I know, that out of such a design decision every Java object contain
>> lock index, i.e. new Object() results in allocation of at least 8
>> bytes where 4 bytes is object index and 4 bytes is lock index on 32-
>> bit JVM.
>> I think that it just inefficient waste of space, because not all the
>> objects requires to be lockable/waitable.

>
> Well, that's your opinion.
>


It is not only his opinion - the size of object header is important
especially on memory constrained devices. But not only - there is a reason
why UseCompressedOops flag was introduced in 64 bit HotSpot JVM.

>> The better decision, IMHO, would be to introduce lock/wait mechanics
>> for only, say, the Lockable descendants.

>
> Oh, yeah, your opinion is humble.
>
>> The current approach seems to be very simple, but is the performance
>> penalty so small for not be taken into an account?

>
> Yes. Nonexistent, really.
>


I wouldn't say so - see:
http://wikis.sun.com/display/HotSpot...CompressedOops
Especially the sentence:
"Memory is pretty cheap, but these days bandwidth and cache is in short
supply"

--
Michal

Lew 06-28-2011 05:10 PM

Re: Why "lock" functionality is introduced for all the objects?
 
On 06/28/2011 12:41 PM, Michal Kleczek wrote:
> Lew wrote:
>
>> Alex J wrote:
>>> I'm curious why Java designers once decided to allow every object to
>>> be lockable (i.e. [sic] allow using lock on those).

>>
>> Because that makes it possible to do concurrent programming intrinsically.
>>

>
> Could you elaborate more on that?
> Do you mean there is no other way to do it?


No, I don't mean that, and I don't see how it follows from what I said.

To elaborate, building monitors into 'Object' (and perforce its descendants)
means that multi-threaded programming is intrinsic, that is, built in to the
very nature of objects in Java. This makes the simple case for
synchronization, well, simple. You create an object of arbitrary type and you
can use it as a lock (strictly speaking, a Hoare monitor). This means that
any class can achieve a measure of thread safety by the proper use of
'synchronized (this)' or the implicit equivalents. The idiom is pervasive and
extremely useful in Java. It is arguably one of the key aspects to Java's
success as a language.

> I find this question quite intriguing as well since it looks quite useless
> for example to be able to lock on java.lang.Integer instance (and it is


So don't lock on an Integer instance, then.

> strange for me that java.lang.Integer instance occupies much more memory as


"strange"? Based on what?

'int' is a primitive, available for convenience because primitives are so
useful without the overhead of objectness. That might not be an optimal
decision, although many successful languages have made the same choice. (C,
C++, C#, Java.) Given the long history of languages with the same dichotomy,
I find it strange that you find it strange.

> int). Surely a compromise must have been done taking into account various
> language features ("synchronized" keyword, lack of multiple inheritance,
> lack of closures) - but I am not that knowlegeable enough to explain this
> compromise in detail.


Java's supposed "lack" of closures, given the admittedly more verbose
alternatives that actually do exist, poses little if any problem. Java does
allow multiple inheritance of contract, just not of implementation, and
actually that distinction makes for clean, elegant code. The 'synchronized'
keyword depends for its utility on the very feature in dispute in this thread,
namely the presence of a monitor in every object. Far from being a
compromise, this is a key strength of the Java language.

>>> I know, that out of such a design decision every Java object contain
>>> lock index, i.e. new Object() results in allocation of at least 8
>>> bytes where 4 bytes is object index and 4 bytes is lock index on 32-
>>> bit JVM.
>>> I think that it just inefficient waste of space, because not all the
>>> objects requires to be lockable/waitable.

>>
>> Well, that's your opinion.
>>

>
> It is not only his opinion - the size of object header is important
> especially on memory constrained devices. But not only - there is a reason
> why UseCompressedOops flag was introduced in 64 bit HotSpot JVM.



OK, that's your opinion, too.

>>> The better decision, IMHO, would be to introduce lock/wait mechanics
>>> for only, say, the Lockable descendants.

>>
>> Oh, yeah, your opinion is humble.
>>
>>> The current approach seems to be very simple, but is the performance
>>> penalty so small for not be taken into an account?

>>
>> Yes. Nonexistent, really.
>>

>
> I wouldn't say so - see:
> http://wikis.sun.com/display/HotSpot...CompressedOops
> Especially the sentence:
> "Memory is pretty cheap, but these days bandwidth and cache is in short
> supply"


Show me the numbers. What penalty? Compared to what instead? If you give up
a feature, you have to add it some other way - what would be the inefficiency
of Java's approach compared to the alternative?

And give us some measurements to support the claim of any "penalty".

Don't forget that HotSpot saves memory as well as increases speed, depending
ont he optimizations involved at any given moment. Have you taken that into
consideration?

--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedi.../c/cf/Friz.jpg

Stefan Ram 06-28-2011 05:33 PM

Re: Why "lock" functionality is introduced for all the objects?
 
Alex J <vstrength@gmail.com> writes:
>What do you think of it?


I do not think, but use a web search engine and find:

http://c2.com/cgi/wiki?JavaObjectOverheadIsRidiculous
http://www.trevorpounds.com/blog/?p=351

. And here is a rationale given for why every object has a lock:

http://forums.oracle.com/forums/thre...readID=1140765

, that is, so that one can use »synchronized« on object
methods (which stands for »synchronized( this )«).


Michal Kleczek 06-28-2011 05:53 PM

Re: Why "lock" functionality is introduced for all the objects?
 
Lew wrote:

> On 06/28/2011 12:41 PM, Michal Kleczek wrote:
>> Lew wrote:
>>
>>> Alex J wrote:
>>>> I'm curious why Java designers once decided to allow every object to
>>>> be lockable (i.e. [sic] allow using lock on those).
>>>
>>> Because that makes it possible to do concurrent programming
>>> intrinsically.
>>>

>>
>> Could you elaborate more on that?
>> Do you mean there is no other way to do it?

>
> No, I don't mean that, and I don't see how it follows from what I said.
>
> To elaborate, building monitors into 'Object' (and perforce its
> descendants) means that multi-threaded programming is intrinsic, that is,
> built in to the
> very nature of objects in Java. This makes the simple case for
> synchronization, well, simple. You create an object of arbitrary type and
> you
> can use it as a lock (strictly speaking, a Hoare monitor). This means
> that any class can achieve a measure of thread safety by the proper use of
> 'synchronized (this)' or the implicit equivalents. The idiom is pervasive
> and
> extremely useful in Java. It is arguably one of the key aspects to Java's
> success as a language.
>


The point is - I don't see a need to be able to use _every_ object as a
monitor. But I have to pay the price (memory usage) of this possibility.

>> I find this question quite intriguing as well since it looks quite
>> useless for example to be able to lock on java.lang.Integer instance (and
>> it is

>
> So don't lock on an Integer instance, then.
>
>> strange for me that java.lang.Integer instance occupies much more memory
>> as

>
> "strange"? Based on what?
>
> 'int' is a primitive, available for convenience because primitives are so
> useful without the overhead of objectness. That might not be an optimal
> decision, although many successful languages have made the same choice.
> (C,
> C++, C#, Java.) Given the long history of languages with the same
> dichotomy, I find it strange that you find it strange.
>


"Strange" is a wrong word - it simply is a PITA :)
For example it makes it unfeasible to use java.util collections in numerical
algorithms.
C++ and C# have their own way of dealing with this - templates and generics
without erasure.

>> int). Surely a compromise must have been done taking into account various
>> language features ("synchronized" keyword, lack of multiple inheritance,
>> lack of closures) - but I am not that knowlegeable enough to explain this
>> compromise in detail.

>
> Java's supposed "lack" of closures, given the admittedly more verbose
> alternatives that actually do exist, poses little if any problem.
> Java
> does allow multiple inheritance of contract, just not of implementation,


If Java had multiple implementation inheritance and closures there would be
no need for "synchronized" keyword at all (the modifier could be added as a
syntactic sugar).

class Foo extends public Bar, private Monitor {
void method() {
//synchronized is defined in Monitor class
synchronized({
//do stuff
});
}
}

> and
> actually that distinction makes for clean, elegant code. The
> 'synchronized' keyword depends for its utility on the very feature in
> dispute in this thread,
> namely the presence of a monitor in every object. Far from being a
> compromise, this is a key strength of the Java language.
>


Yet in the end the community seems to agree not to use "synchronized"
directly but rather use classes from java.util.concurrent (namely Lock and
Condition). So is this keyword really that important?

[snip]
>>>> The current approach seems to be very simple, but is the performance
>>>> penalty so small for not be taken into an account?
>>>
>>> Yes. Nonexistent, really.
>>>

>>
>> I wouldn't say so - see:
>> http://wikis.sun.com/display/HotSpot...CompressedOops
>> Especially the sentence:
>> "Memory is pretty cheap, but these days bandwidth and cache is in short
>> supply"

>
> Show me the numbers. What penalty?


It is (almost) twice as much memory as it could be and twice as much GC
cycles. Almost because in real world the number of objects that you need to
synchronize on is way lower than the number of all objects you create.

> Compared to what instead? If you
> give up a feature, you have to add it some other way - what would be the
> inefficiency of Java's approach compared to the alternative?
>


That is actually something I would like to hear as well and - as I read it -
what OP asked for - the discussion of pros and cons of different approaches
with some explanation of why it is done like this in Java.
And your answer looks like "that's the way it is and it is the best way it
can be done".

--
Michal

Lew 06-28-2011 06:13 PM

Re: Why "lock" functionality is introduced for all the objects?
 
Michal Kleczek wrote:
> Lew wrote:
>> Show me the numbers. What penalty?

>
> It is (almost) twice as much memory as it could be and twice as much GC
> cycles. Almost because in real world the number of objects that you need to


Nonsense. It's an extra 4 bytes per object. Most objects are much larger
than 4 bytes, so it's far, far less than "twice as much memory".

Similarly there's no way four extra bytes per object double the number of GC
cycles.

Anyhow, when I ask you to show me the numbers, I mean real numbers, not
made-up speculative nonsense. What Java version, host, OS, configuration and
workload? What was the actual, measured, real, verified impact?

Show me the numbers.

> synchronize on is way lower than the number of all objects you create.
>
>> Compared to what instead? If you
>> give up a feature, you have to add it some other way - what would be the
>> inefficiency of Java's approach compared to the alternative?


> That is actually something I would like to hear as well and - as I read it -
> what OP asked for - the discussion of pros and cons of different approaches
> with some explanation of why it is done like this in Java.
> And your answer looks like "that's the way it is and it is the best way it
> can be done".


How does it look like that? How do you get to misrepresent what I say and
attribute different points to me from what I actually said?

What I actually said was the answer to the OP's question - why was it done
that way? There was a reason. Nowhere did I say or imply that it's the best
way it can be done. In fact, I explicitly disavowed that interpretation.
You're being dishonest here. Stop that.

--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedi.../c/cf/Friz.jpg

supercalifragilisticexpialadiamaticonormalizeringelimatisticantations 06-28-2011 06:23 PM

Re: Why "lock" functionality is introduced for all the objects?
 
On 28/06/2011 2:13 PM, Lew wrote:
> Michal Kleczek wrote:
>> Lew wrote:
>>> Show me the numbers. What penalty?

>>
>> It is (almost) twice as much memory as it could be and twice as much GC
>> cycles. Almost because in real world the number of objects that you
>> need to

>
> Nonsense. It's an extra 4 bytes per object. Most objects are much larger
> than 4 bytes,


Bullpuckey, other than that a nontrivial object is always at least 12
bytes due to Java's bloated object headers plus alignment. Ignoring
that, it's quite common to have lots of small objects at runtime -- from
boxed primitives (4 bytes for most and 8 bytes for Longs and Doubles,
plus object headers) to short strings (two bytes per character plus four
for the length field = 8 for a two-letter word and 4 for an empty string
-- again, plus object headers) and the occasional content-free
pure-behavior object (abstract factories, strategy pattern
implementations, event listeners, plus most of the things you'd use an
anonymous inner class for ...). Small collections are a bit larger but
an 8 byte object header is still likely to be a fair percentage; and
their iterators may contain as little as a single integer index plus a
single pointer (ArrayList's likely does) and so be the same size as a
Long or a Double.

And then there's all the objects with one or two reference type fields.
Four bytes each, on a 32-bit JVM. You can't count the "nested" objects'
own sizes, because they each have their own object header.

Objects with many fields are quite a bit rarer than ones with only one
or two fields. *Classes* with many fields are less common, and usually
there will be fewer live instances at runtime.

Ultimately, overhead fraction = average bytes directly in fields (at
most 4 for most fields on 32-bit systems, excepting long and double
primitive fields) divided by header size, where the average is over a
*typical population of live objects in a running system* rather than
over a set of, say, classes in use in a system.

Lew 06-28-2011 06:33 PM

Re: Why "lock" functionality is introduced for all the objects?
 
On 06/28/2011 02:23 PM,
supercalifragilisticexpialadiamaticonormalizeringe limatisticantations wrote:
> On 28/06/2011 2:13 PM, Lew wrote:
>> Michal Kleczek wrote:
>>> Lew wrote:
>>>> Show me the numbers. What penalty?
>>>
>>> It is (almost) twice as much memory as it could be and twice as much GC
>>> cycles. Almost because in real world the number of objects that you
>>> need to

>>
>> Nonsense. It's an extra 4 bytes per object. Most objects are much larger
>> than 4 bytes,

>
> Bullpuckey, other than that a nontrivial object is always at least 12 bytes


So 4 bytes overhead is less than 100%, as I said.

> due to Java's bloated object headers plus alignment. Ignoring that, it's quite
> common to have lots of small objects at runtime -- from boxed primitives (4
> bytes for most and 8 bytes for Longs and Doubles, plus object headers) to
> short strings (two bytes per character plus four for the length field = 8 for
> a two-letter word and 4 for an empty string -- again, plus object headers) and


Most strings in a typical program are non-empty and generally longer than two
bytes. A good percentage are interned. Strings in many runtime contexts
refer to substrings of those already in memory, saving overhead.

Integer objects make up a small fraction of most programs. Many Integer
instances are shared, especially if one follows best practices. Not a lot of
memory pressure there.

Double and Long, even fewer.

> the occasional content-free pure-behavior object (abstract factories, strategy
> pattern implementations, event listeners, plus most of the things you'd use an
> anonymous inner class for ...). Small collections are a bit larger but an 8
> byte object header is still likely to be a fair percentage; and their


What percentage is "fair"? Surely less than 100%, as I claim.
\
> iterators may contain as little as a single integer index plus a single
> pointer (ArrayList's likely does) and so be the same size as a Long or a Double.
>
> And then there's all the objects with one or two reference type fields. Four
> bytes each, on a 32-bit JVM. You can't count the "nested" objects' own sizes,
> because they each have their own object header.
>
> Objects with many fields are quite a bit rarer than ones with only one or two
> fields. *Classes* with many fields are less common, and usually there will be
> fewer live instances at runtime.
>
> Ultimately, overhead fraction = average bytes directly in fields (at most 4
> for most fields on 32-bit systems, excepting long and double primitive fields)
> divided by header size, where the average is over a *typical population of
> live objects in a running system* rather than over a set of, say, classes in
> use in a system.


You show only that the overhead of 4 bytes per object is less than 100% of the
object's memory footprint, which is what I said.

Which footprint can be reduced by HotSpot, to the point of pulling an object
out of the heap altogether.

Where are the numbers? Everyone's arguing from speculation. Show me the numbers.

Real numbers. From actual runs. What is the overhead, really? Stop making
**** up.

Show me the numbers.

--
Lew
Honi soit qui mal y pense.
http://upload.wikimedia.org/wikipedi.../c/cf/Friz.jpg


All times are GMT. The time now is 06:05 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.