Cost of creating objects?

S

Sebastian

@Override
public int compare(AttrValue o1, AttrValue o2)
{
Long ts1 = o1.getEffectiveSequenceNumber(); // ??
Long ts2 = o2.getEffectiveSequenceNumber(); // ??
return ts1.compareTo(ts2);
}

Would you expect a measureable impact of creating these
variables ts1, ts2, instead of "inlining" the calls to
getEffectiveSequenceNumber(). (Using JDK 6?)

How can I reason about this things, probably influenced by
JIT, without doing actually measurements, say as part of a
code inspection?

-- Sebastian
 
S

Sebastian

Am 07.08.2013 12:02, schrieb Donkey Hottie:
07.08.2013 10:44, Sebastian kirjoitti:

What is getEffectiveSequenceNumber() returning?

If Long, there is no way to prevent the creation of a Long.

If long, try and use long variables instead, and manually code the
comparison code, it's not that complicated anyway.

Thanks for the hint, yes, I forgot to state that the method returns a
long primitive.

However, your answer does not address my question, which wasn't about
how to code a long comparison.

-- Sebastian
 
J

Joerg Meier

@Override
public int compare(AttrValue o1, AttrValue o2)
{
Long ts1 = o1.getEffectiveSequenceNumber(); // ??
Long ts2 = o2.getEffectiveSequenceNumber(); // ??
return ts1.compareTo(ts2);
}
Would you expect a measureable impact of creating these
variables ts1, ts2, instead of "inlining" the calls to
getEffectiveSequenceNumber(). (Using JDK 6?)

I would expect the JIT to inline them for you if the method is called more
than a handful of times.
How can I reason about this things, probably influenced by
JIT, without doing actually measurements, say as part of a
code inspection?

You probably can't, nor will you find a huge audience to reason with you on
a topic like this, because it's so obviously pointless. If your performance
bottleneck is assigning temporary local variables, then Java simply isn't
the right language for whatever task you are doing, and I would expect most
people to hold similar views.

Liebe Gruesse,
Joerg
 
E

Eric Sosman

Am 07.08.2013 12:02, schrieb Donkey Hottie:

Thanks for the hint, yes, I forgot to state that the method returns a
long primitive.

However, your answer does not address my question, which wasn't about
how to code a long comparison.

He answered part of your question, essentially saying "Don't
create a Long if the returned long suits your purpose." If you
can stick with long (which it seems you can), you can eliminate
the creation and eventual collection of two Long objects. (But
if getEffectiveSequenceNumber() does four hash table lookups,
three regex matches, two Fourier transforms, and a database
query, ... Even a hundred Long's would be "in the noise.")

Primitive local variables are free, pretty nearly, but if
you move to 1.7 you could even get rid of those:

@Override
public int compare(AttrValue o1, AttrValue o2)
{
return Long.compare( // New in 1.7
o1.getEffectiveSequenceNumber(),
o2.getEffectiveSequenceNumber());
}

Of course, the named primitives that disappear from your method
may reappear as the named parameters of compare(), so it might
just be a wash. I'd imagine that any difference would be so small
as to be very difficult to measure.
 
S

Stefan Ram

Sebastian said:
Would you expect a measureable impact of creating these
variables ts1, ts2, instead of "inlining" the calls to
getEffectiveSequenceNumber(). (Using JDK 6?)

Creating objects on the heap is not so much effort, but
eventual garbage collection might take some time. However,
the compiler can perform an escape analysis and then
create the objects on the stack. A smart compiler could
even transform the code to the code written by Donkey.
Therefore, programmers nowadays often do not ask
»what is most efficient?«, but »what is most readable?«.
 
S

Sebastian

Am 07.08.2013 17:39, schrieb Stefan Ram:
Creating objects on the heap is not so much effort, but
eventual garbage collection might take some time. However,
the compiler can perform an escape analysis and then
create the objects on the stack. A smart compiler could
even transform the code to the code written by Donkey.
Therefore, programmers nowadays often do not ask
»what is most efficient?«, but »what is most readable?«.

I would agree. The reason I asked is we have a person in our group
who is very much in a micro-optimization mind-set. Among the things
that concern him are, for example, temporary local variables, wrappers
as method arguments wasting heap space compared to primitives,
multiple hash map lookups (containsKey() followed by get()) etc.

I sometimes find his code inelegant and unclear and would like to know
that it cannot really be more efficient. But of course, I cannot
rewrite and profile all his stuff in order to convince him.

-- Sebastian
 
E

Eric Sosman

[...] The reason I asked is we have a person in our group
who is very much in a micro-optimization mind-set. Among the things
that concern him are, for example, temporary local variables, wrappers
as method arguments wasting heap space compared to primitives,
multiple hash map lookups (containsKey() followed by get()) etc.

I sometimes find his code inelegant and unclear and would like to know
that it cannot really be more efficient. But of course, I cannot
rewrite and profile all his stuff in order to convince him.

Prediction: Without measurement, you won't convince him.

Observation: Without measurement, perhaps neither of you
*should* convince the other.

Prediction II: ... but you'll both try anyhow. ;-)
 
L

Lew

Eric said:
Sebastian said:
[...] The reason I asked is we have a person in our group
who is very much in a micro-optimization mind-set. Among the things
that concern him are, for example, temporary local variables, wrappers
as method arguments wasting heap space compared to primitives,
multiple hash map lookups (containsKey() followed by get()) etc.

Overrule him. He's an idiot. Although doing a 'containsKey()' before a 'get()' is silly.

The burden of proof is on him to prove where these things matter, and not by micro-
benchmarks. Don't waste your time optimizing things that represent 0.00001% of program
execution time after JIT gets its mitts on them. Don't do things that are silly
(like checking 'containsKey()' just before a map 'get()' when 'null' is not an allowed value)
and your program should run about as fast as it can.

You do not need to know that. You only need for him not to know that it assuredly
is more efficient. If he cannot prove that, reject his silly suggestions. (Accept the ones that
are not silly.)

If he cannot prove that the "efficiency" is a real problem, and more importantly, that the cost
of this "inefficiency" is larger than the cost of maintaining unclear code (in dollars and cents),
then his suggestions must be rejected.

Not your job. It's his job to convince you.
Prediction: Without measurement, you won't convince him.

Nor should you.
Observation: Without measurement, perhaps neither of you
*should* convince the other.

Certainly without observations he should not try to convince you.
Prediction II: ... but you'll both try anyhow. ;-)

You should convince him. Not that the code is sufficiently "efficient" now, but that the
question is irrelevant. You won't convince him that he's an idiot, but maybe you will
convince him to shut up.
 
A

Arne Vajhøj

@Override
public int compare(AttrValue o1, AttrValue o2)
{
Long ts1 = o1.getEffectiveSequenceNumber(); // ??
Long ts2 = o2.getEffectiveSequenceNumber(); // ??
return ts1.compareTo(ts2);
}

Would you expect a measureable impact of creating these
variables ts1, ts2, instead of "inlining" the calls to
getEffectiveSequenceNumber(). (Using JDK 6?)

The difference between:

Long ts1 = o1.getEffectiveSequenceNumber();
Long ts2 = o2.getEffectiveSequenceNumber();
return ts1.compareTo(ts2);

and:

return
o1.getEffectiveSequenceNumber().compareTo(o2.getEffectiveSequenceNumber());

should be nothing.

The difference between:

Long ts1 = o1.getEffectiveSequenceNumber();
Long ts2 = o2.getEffectiveSequenceNumber();
return ts1.compareTo(ts2);

and doing something simple with long as described by other posters
would be huge in a program not doing anything but this in a 1 billion
times iteration but insignificant in most real world programs.
How can I reason about this things, probably influenced by
JIT, without doing actually measurements, say as part of a
code inspection?

Experience will enable you to make qualified guesses.

Measuring will tell you the facts.

:)

Arne
 
A

Arne Vajhøj

Am 07.08.2013 17:39, schrieb Stefan Ram:

I would agree. The reason I asked is we have a person in our group
who is very much in a micro-optimization mind-set. Among the things
that concern him are, for example, temporary local variables, wrappers
as method arguments wasting heap space compared to primitives,
multiple hash map lookups (containsKey() followed by get()) etc.

I sometimes find his code inelegant and unclear and would like to know
that it cannot really be more efficient. But of course, I cannot
rewrite and profile all his stuff in order to convince him.

Send him back to the 9970's or 1980's - there were great use
for developers like him back then.

Today that type of stuff typical make large chunks of code
unreadable and saves little on overall execution time.

But you may find it difficult to convince him. Microoptimizers
believe very strongly in their religion.

You can suggest every time he wants to change something that
you measure the real application before and after the change.

My guess is that he will find an excuse for not doing that and
refer to his own micro-benchmark.

Arne
 
E

Eric Sosman

Eric said:
Sebastian said:
[...] The reason I asked is we have a person in our group
who is very much in a micro-optimization mind-set. Among the things
that concern him are, for example, temporary local variables, wrappers
as method arguments wasting heap space compared to primitives,
multiple hash map lookups (containsKey() followed by get()) etc.

Overrule him. He's an idiot. Although doing a 'containsKey()' before a 'get()' is silly.

Situation: A Map that is searched for keys that are usually
*not* present (poor man's Bloom filter, say), and some of whose
mapped values are null. Now, attend:

if (map.containsKey(key)) { // usually false
Value val = map.get(key); // seldom needed
...
}

vs.

Value val = map.get(key);
if (val == null // usually true
|| map.containsKey(key) // usually false
) {
...
}

If the key is present 0.0 <= p <= 1.0 of the time, the first
version does (1 + p) searches, the second (1 + (1 - p)) = (2 - p).
Even if the second search is cheaper than the first (maybe the
key's hashCode has been cached), for small p the first wins.
 
K

Kevin McMurtrie

lipska the kat said:
Have you heard of a profiler?

A few years ago I used one to investigate an application running on
Weblogic application server, the results were eye opening.

I seem to remember the company I was working for handed over a large wad
of cash to get a couple of licences for a commercial product ... can't
remember what it was called unfortunately.

Googling 'java profiler' today returns the usual plethora of hits and I
expect the game has moved on since I last used one, there also appear to
be a bunch of free ones out there.

If you want to reason about this stuff then it might pay you to have a
look at your application with a profiler, you will almost certainly
learn something to help you in your endeavors.

lipska

Most automatic Java profilers are a waste of effort. There are two
methods supported by the JVM:

1) Profiler instrumentation. This rewrites methods to contain timing
calls. This rewriting and data collection breaks all the optimizations
that are critical to Java performing well. Most can only collect data
into a single thread so all concurrency is gone too. These only work
when manually configured to target very specific points of code.


2) Sampling. This takes rapid stack snapshots of each thread and
collects statistics. It's simple and you can even build a JSP to do it.
This also doesn't work for performance benchmarking because snapshots of
native code require threads to stop at a safepoint. When HotSpot is
doing a good job, safepoints come at regular intervals in the optimized
native code, not your source code. When I use sampling profiling on a
project at work, Integer.hashCode() sometimes leaps to the #1 spot.
There's not actually any code in that method and it's not called very
frequently, but often a safepoint's native address maps to that source
in the debug symbol table. Sampling is best for finding code that
pauses (I/O, semaphore, waiting for resource, etc.) for unexpectedly
long times.

As for the original question, variable declarations mean nothing in
compiled code. They're just for humans. At times when AttrValue is
known to have only one possible implementation, HotSpot may even inline
the methods and use direct field access. Later when AttrValue may have
more than one implementation, HotSpot can go remove that optimization.
 
K

Kevin McMurtrie

Sebastian said:
Am 07.08.2013 12:02, schrieb Donkey Hottie:

Thanks for the hint, yes, I forgot to state that the method returns a
long primitive.

However, your answer does not address my question, which wasn't about
how to code a long comparison.

-- Sebastian

This:
Long l= 4L;

is shorthand for:

Long l= Long.valueOf(4);

It's optimized for some values to return a singleton. For others you'll
get a performance penalty on Long creation. How big that is depends on
your system. Run it a 100 million times and see.

Since comparing the primitives is known to be fast and trivial, I'd just
compare the primitives. There's no point writing potentially slow code
for no good reason.
 
J

Jukka Lahtinen

Eric Sosman said:
On 8/7/2013 7:52 PM, Lew wrote:
Situation: A Map that is searched for keys that are usually
*not* present (poor man's Bloom filter, say), and some of whose
mapped values are null. Now, attend:
if (map.containsKey(key)) { // usually false
Value val = map.get(key); // seldom needed
...
}
vs.
Value val = map.get(key);
if (val == null // usually true
|| map.containsKey(key) // usually false
) {

I think you mean

Value val = map.get(key);
if (val != null // usually false
|| map.containsKey(key)) { // usually false
 
E

Eric Sosman

I think you mean

Value val = map.get(key);
if (val != null // usually false
|| map.containsKey(key)) { // usually false

(Sigh.) Yes, indeed. That's what I get for writing once
and then editing "for clarity" ...
 
J

Jukka Lahtinen

lipska the kat said:
On 08/08/13 09:24, Jukka Lahtinen wrote:
I think (null != val ... ) is better.

Why? I see no real difference.
If you are thinking about NullPointerException, it is not thrown by
this kind of comparison, where you just check equality to null without
refering any possible members of val.
 
A

Arne Vajhøj

Why? I see no real difference.
If you are thinking about NullPointerException, it is not thrown by
this kind of comparison, where you just check equality to null without
refering any possible members of val.

The trick sometimes called Yoda condition is from C/C++ where
you could intend to write:
if(val == null)
and end up writing:
if(val = null)
and not get a compile error but instead a different semantics than
expected.

Writing:
if(null == val)
avoid that risk as:
if(null = val)
will give a compile error.

But Java is different.

Arne
 
S

Stefan Ram

Kevin McMurtrie said:
Most automatic Java profilers are a waste of effort. There are two
methods supported by the JVM:

As a corollary to »Don't try to fix it if it ain't broke¹«
and »You ain't gonna need it.«:

Either the completed product will be observably too slow or not.

If it is /not/ observably too slow,

any further work into optimization (which usually reduces
code portability and quality) will be a waste of time.
(And possibly work already done in this direction so far
already was a waste of time.)

If it /is/ observably too slow,

then, using reasoning and possibly a profiler, one can
identify possible regions of code eligible to further
optimization efforts. The beauty of fixing something
that actually /is/ broken is that it /will be observable/
whether the modifications make the product faster,
because we already have asserted that it is observably
too slow, so it also will be observable when this
condition is being changed (And possibly work already
done in this direction before was a waste of time,
because it was optimization at the wrong places.)

Of course, one can still choose to write code in the way
most efficient in the first place, whenever one can see that
this is /obviously/ (with certainity) the way most efficient,
and it comes with little additional cost.

¹ »ain't broke« = »is not broken«, »is not broken« is more
common, but I remember it this odd way: »ain't broke«.
 
A

Arved Sandstrom

This:
Long l= 4L;

is shorthand for:

Long l= Long.valueOf(4);

It's optimized for some values to return a singleton. For others you'll
get a performance penalty on Long creation. How big that is depends on
your system. Run it a 100 million times and see.

Since comparing the primitives is known to be fast and trivial, I'd just
compare the primitives. There's no point writing potentially slow code
for no good reason.
This little snippet from 5.1.7 of the language spec requires caching:

"If the value p being boxed is true, false, a byte, or a char in the
range \u0000 to \u007f, or an int or short number between -128 and 127
(inclusive), then let r1 and r2 be the results of any two boxing
conversions of p. It is always the case that r1 == r2."

Oddly enough, not for Long, although it's commonly done (as in OpenJDK 7).

Note that this definition does not prohibit other caching. So if using
== it's a really good idea to do some testing.

AHS
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top