• Blah (unregistered) in reply to ClutchDude

    Apple didn't make a Java 6 JVM for 32-bit OS X and apparently never will. That may or may not matter to you depending on your app and userbase. All the language features you mentioned are in Java 5, but you have to watch your API calls (e.g. no String.isEmpty) to not depend on 6.

  • alpha maniac (unregistered) in reply to Prof

    I like. Here are proposed initial definitions for unsigned byte values in "alpha" (a new computer language lacking numeric characters).

    Only zero and one require a "leap", imagine them as equivalent to a big bang creation event to get something from nothing. Everything else can be defined using ring operations "plus" and "times".

    define zero as (|{}|) -- cardinality of an empty set define one as (zero!) -- number of permutations of zero define two as (one plus one) define three as (two plus one) define four as (two times two) define five as (four plus one) define six as (four plus two) define seven as (four plus two plus one) define eight as (four times two) ... define two-hundred-fifty-five as (one-hundred-twenty-eight plus sixty-four plus thirty-two plus sixteen plus eight plus four plus two plus one)

  • katastrofa (unregistered) in reply to LordOfThePigs
    LordOfThePigs:
    And I'm sure we can all agree that spending 20 bytes when we should really only use 4 is stupid, especially if you do it with 5'000 different instances of the same immutable Integer object.

    20 * 5000 = 10000 bytes = 10kb

    That's peanuts.

  • mypalmike (unregistered)

    This is a reverse WTF. The original code is fine, and the analysis is wrong.

    The only flaw in the original code is that it re-implements a feature the developer somehow managed to overlook among the documentation of the thousands of methods in the standard library. Here's the complicated fix:

    find . -name "*.java" | xargs sed -i 's/MathUtil.getInteger/Integer.valueOf/g'
  • Prof (unregistered) in reply to alpha maniac
    alpha maniac:
    ... define seven as (four plus two plus one) define eight as (four times two) ... define two-hundred-fifty-five as (one-hundred-twenty-eight plus sixty-four plus thirty-two plus sixteen plus eight plus four plus two plus one)
    Yes, you're getting the idea. Moreover, this could all be defined in a (large) header file that's automatically included with every compile.

    One suggestion, though, to save on typing and help with those who have trouble spelling. Name them i0, i1, i2 .. i255 ...

  • (cs)

    Just think of the sense of satisfaction you can get from deleting all that bloat.

    Mind, I wonder whether how much more fun it's going to be replacing all the magic numbers (which no doubt are riddling this app) with meaningful parameters. Or even Enums.

  • Hugh (unregistered) in reply to Matt Westwood
    Matt Westwood:
    Just think of the sense of satisfaction you can get from deleting all that bloat.

    Mind, I wonder whether how much more fun it's going to be replacing all the magic numbers (which no doubt are riddling this app) with meaningful parameters. Or even Enums.

    We reduced the size of the war file by 300K in one month and fixed 20 bugs at the same time. The original code had one sad enum created in 2006. We have put in lots of enums since we've started but so many of the magic numbers (that are riddling the app) are being passed that it would be easier to completely rewrite it.

  • (cs) in reply to Chris
    Chris:

    Sigh... this persistent myth is simply not true for the most part anymore. We write server software at an investment bank that processes huge volumes of data and is very performance critical. Well written Java is more than up to the task for what we do. Bottlenecks invariably are due to IO or algorithm design, not the choice of Java vs say C or C++.

    A certain large web-based retailer handling bazillions of requests per second has Java handling page rendering. If you're familiar with this sort of stuff, you'll know that there's a direct relationship between render time and sales (people get frustrated with slow-to-render sites). Java holds its own quite well in this situation; most of the time taken is IO bottlenecks or remote service calls, both of which are essentially language-independent.

    Java has its benefits; so does C/C++. Neither is inherently better than the other (in the general case).

    My preference for C++ over Java is largely arbitrary. I like C++ better because I like C++ better... maybe it's because I learned it first? Who knows.

  • (cs) in reply to Jamie
    Jamie:
    The maze of twisy passages was from Zork's predecessor the original and the best Collosal Cave Adventure.
    I guess he must have been trolling ....
  • (cs) in reply to Matt Westwood
    Matt Westwood:
    Mind, I wonder whether how much more fun it's going to be replacing all the magic numbers (which no doubt are riddling this app) with meaningful parameters. Or even Enums.

    I did this in a previous employer's large C++ application once. I replaced things like

    #define PI 3.14159

    with consts, enums, etc. Fixed several bugs in the process (where the wrong defined FOOBAR was used or the lack of type checking caused issues or whatever).

    It's far easier to maintain an enum than a manually enumerated set of #defined constants...

    For those keeping score at home, this was authorized by the same manager that fired me for rewriting that context menu code to be sane and readable (not to mention reducing it from 2000 LOC to 200 LOC).

  • Bendin (unregistered)

    Actually, the is a WTF by reason of redundancy, not insanity: This very optimization is built into the Java Runtime. There's a cache of small-valued Integer and Long objects. I guess it reduces garbage collector churn.

  • Jimbo Jones (unregistered) in reply to DAT

    [quote user="DAT"]By the way, the idiom is "hare-brained," not "hair-brained." It goes along with the one about "mad as March hare."[/quote]

    Seeing as som many of you have said something along these lines.... freedictionary.com says: [quote=freedictionary]hare·brained (hârbrnd) adj. Foolish; flighty: a harebrained scheme. Usage Note: The first use of harebrained dates to 1548. The spelling hairbrained also has a long history, going back to the 1500s when hair was a variant spelling of hare. The hair variant was preserved in Scotland into the 18th century, and as a result it is impossible to tell exactly when people began writing hairbrained in the belief that the word means "having a hair-sized brain" rather than "with no more sense than a hare." While hairbrained continues to be used and confused, it should be avoided in favor of harebrained which has been established as the correct spelling. [/quote]

    Hairbrained is not in correct, merely discouraged.

  • Scott (unregistered)

    I'm going to have to side with the others who have suggested the Integer cache probably works. I've timed some usage of Integer.valueOf() professionally, which appears to do exactly the same thing. It, on average, runs significantly faster (and saves memory). In most programs, Integer objects contain vastly more small values than large ones.

    Java also has a built in caches of Byte, Short, Long and Boolean objects. The Boolean cache makes the most sense as you only ever need two Boolean objects.

  • Mac (unregistered) in reply to Heron
    Heron:
    Chris:
    <snip>
    <snip>

    Java has its benefits; so does C/C++. Neither is inherently better than the other (in the general case).

    My preference for C++ over Java is largely arbitrary. I like C++ better because I like C++ better... maybe it's because I learned it first? Who knows.

    I agree. I learnt Java first, and have since learnt C and (to a lesser degree) C++ Personally I prefer C when possible, and C++ otherwise, but I couldn't really tell you why. I'll fight to the death over it, though....

  • (cs)

    Nice, a true idempotent method!

    MathUtil.getInteger(0) == MathUtil.getInteger(MathUtil.getInteger(MathUtil.getInteger( MathUtil.getInteger(MathUtil.getInteger(MathUtil.getInteger(MathUtil.getInteger(MathUtil.getInteger(MathUtil.getInteger( MathUtil.getInteger(MathUtil.getInteger(MathUtil.getInteger(MathUtil.getInteger(MathUtil.getInteger(0))))))))))))))

    To be sure, you should probably externalize that 0 - or maybe you should externalize a cache parameter instead?

  • Tom Hawtin (unregistered)

    I've written code like this (about a decade ago). The reason? My profiler told me to. The Java port ended up faster than the C++ program (and was an awful lot sexier).

    The potential existence of a sufficiently smart compiler some time in the future is no excuse for not delivering performance now. Even today, the difference is not clear.

  • mypalmike (unregistered) in reply to Bendin
    Bendin:
    I guess it reduces garbage collector churn.

    It's not just garbage collector churn. Memory allocation takes far more cpu cycles than array indexing.

  • Quirkafleeg (unregistered) in reply to Prof
    Prof:
    alpha maniac:
    […] define two-hundred-fifty-five as (one-hundred-twenty-eight plus sixty-four plus thirty-two plus sixteen plus eight plus four plus two plus one)
    […] One suggestion, though, to save on typing and help with those who have trouble spelling. Name them i0, i1, i2 .. i255 ...
    That would also help those of us who don't miss out the “and”s. (Was that ‘200, 55’ or ‘255’?)
  • Quirkafleeg (unregistered) in reply to Jimbo Jones
    Jimbo Jones:
    […] Hairbrained is not in correct, merely discouraged.
    … whereas ‘in correct’ is definitely incorrect.

    An initials-of-days-of-week cache (or array or string). What does it have in the middle?

  • Contra (unregistered) in reply to katastrofa
    katastrofa:
    LordOfThePigs:
    And I'm sure we can all agree that spending 20 bytes when we should really only use 4 is stupid, especially if you do it with 5'000 different instances of the same immutable Integer object.

    20 * 5000 = 10000 bytes = 10kb

    That's peanuts.

    Wow, strong math skills.

  • Dave (unregistered) in reply to alpha maniac

    data Nat = Zero | Succ Nat

  • Jimmy McJimbo (unregistered)

    but but but... i dont know java... but... if it just returns a pointer to an existing instance of integer, and i then manualy change its value in my code. Wont the value of the original cached object also change, resulting in a tear in the fabric of space and time itself.

  • Fedaykin (unregistered) in reply to jspenguin
    jspenguin:
    Reimplementing standard library functionality. Yawn.

    http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Integer.html#valueOf%28int%29

    Returns a Integer instance representing the specified int value. [If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values.

    Take note of the "since" Javadoc.

    This (particular line) is not a WTF, it's a workaround for a problem in early Java versions.

  • Jimmy McJimbo (unregistered) in reply to Contra
    katastrofa:
    LordOfThePigs:
    And I'm sure we can all agree that spending 20 bytes when we should really only use 4 is stupid, especially if you do it with 5'000 different instances of the same immutable Integer object.

    20 * 5000 = 10000 bytes = 10kb

    That's peanuts.

    Well peanuts have 2 nuts to each shell. So in any single shell we could have either 0 nuts, 1 nut, or 2 nuts. So using our peanut shell ternary system, we can see that: 202 * 20212012 = 12002011201. Which tells me you are wrong by a factor of 111201101.

    Perhaps you should brush up on your peanut math skills.

  • Jimmy McJimbo (unregistered) in reply to Jimmy McJimbo
    Jimmy McJimbo:
    Which tells me you are wrong by a factor of 111201101.

    Damn, peanuts did my brain in, should be: wrong by a factor of 101.

  • Fedaykin (unregistered)

    Complete rubbish. While the general code sounds like a total POS project, this particular contsruct is a GOOD piece of code. Early versions of Java did not cache integers (meaning every time you needed a wrapped int -- like when putting it in a data structure -- it would create a new instance of Integer) thus this workaround exists in a lot of early java projects that made a lot of use of Integers.

    It was only in java 1.5 that the core API was updated to do this very same thing. Given that the sample doesn't use any 1.5 specific syntax, it's likely pre 1.5

    However, if this was written post 1.5.. well then it's a WTF.

    The OP is exposing their own ignorance and not a WTF here.

  • Anonymous (unregistered) in reply to Jimmy McJimbo
    Jimmy McJimbo:
    katastrofa:
    LordOfThePigs:
    And I'm sure we can all agree that spending 20 bytes when we should really only use 4 is stupid, especially if you do it with 5'000 different instances of the same immutable Integer object.

    20 * 5000 = 10000 bytes = 10kb

    That's peanuts.

    Well peanuts have 2 nuts to each shell. So in any single shell we could have either 0 nuts, 1 nut, or 2 nuts. So using our peanut shell ternary system, we can see that: 202 * 20212012 = 12002011201. Which tells me you are wrong by a factor of 111201101.

    Perhaps you should brush up on your peanut math skills.

    It's more complicated than that. You can eat much more than one peanut per byte, so you might have 12002011201, but you have much fewer bytes. Still more than 10000 but nowhere near as many as 12002011201.

  • (cs) in reply to DAT
    DAT:
    By the way, the idiom is "hare-brained," not "hair-brained." It goes along with the one about "mad as March hare."

    That might be the correct usage, but I think the former would be more accurate for some of the stuff we see in here.

  • Tom Hawtin (unregistered) in reply to mypalmike

    Memory allocation for Integer? About 20 cycles? Less if escape analysis (if enabled) puts it on the stack. It causes memory churn because those heap bytes have to be read in and written out.

    I understand the real problem with this optimisation/pessimisation is non-localisation. Keep the Integer instances about and they could all be in different pages (although they may end up contiguous). Allocate an individual instance, and it'll be in a row with objects allocated by the same thread at a similar time initially. Depending upon GC algorithm, the instance is also likely to be found just after where it is referenced - good for processor cache and good for TLA buffers.

  • (cs) in reply to Vlad Patryshev
    Vlad Patryshev:
    Primitives don't work as keys; and not every jvm is 1.5 compatible; if you try RIMM, you'll be amazed how careful one should be allocating Integers or even using String literals.

    I second this.. I tried RIM, the slow GC really is a major pain in the back.

  • --- (unregistered)

    Another meta wtf.

  • (cs) in reply to aristos_achaion
    aristos_achaion:
    You seem to underestimate the utility of having an Integer object, especially if you're dealing with generics.

    I can understand the utility of having an object Integer, as opposed to an int. But if the language was built to be almost pure OO, like Java was, rather than giving it two integer types (one a class and one a primitive), the language should've just applied classy goodness to normal int primitives.

    The language doesn't have to store anything extra with each int; it could just simply know that int objects use the built-in int methods if they invoke methods. But that would've required more capable programmers than those at Sun, apparently.

    This is one of the many things that Sun could've done with Java to make it worthwhile. Sadly, they just went for making another fad language.

    It is nice that, since then, they fixed up a lot of the problems with it. For example, they've almost, but not quite, fixed this one.

  • Daniel Sobral (unregistered)

    I hereby declare all of you to be ignorant fools! Change that code and run it with the Java 1.3 it probably came from, and see it crash and burn!!!

    The reason being, of course, that Integer(0) != Integer(0), as reference equality is used for objects. So, unless you cache each boxed Integer you have, you can't rely on them as keys (ParentID, remember?).

  • (cs) in reply to Chris
    Chris:
    frits:
    I dare you to write your database engine in pure Java.

    What, like one of these?

    http://java-source.net/open-source/database-engines

    That's a lot of market share in that list.

  • @Deprecated (unregistered) in reply to Jimmy McJimbo
    Jimmy McJimbo:
    katastrofa:
    LordOfThePigs:
    And I'm sure we can all agree that spending 20 bytes when we should really only use 4 is stupid, especially if you do it with 5'000 different instances of the same immutable Integer object.

    20 * 5000 = 10000 bytes = 10kb

    That's peanuts.

    Well peanuts have 2 nuts to each shell. So in any single shell we could have either 0 nuts, 1 nut, or 2 nuts.

    ...

    What, you never cracked open a peanut with three nuts in it?

  • (cs) in reply to Tom Hawtin
    Tom Hawtin:
    Memory allocation for Integer? About 20 cycles? Less if escape analysis (if enabled) puts it on the stack. It causes memory churn because those heap bytes have to be read in and written out.

    It also adds an additional point for the GC routine to check for allocation. I know this used to be on every pass, but it's possible that Java's fixed its GC routine over the years.

    Tom Hawtin:
    I understand the real problem with this optimisation/pessimisation is non-localisation. Keep the Integer instances about and they could all be in different pages (although they may end up contiguous).

    As I understand it, non-localised allocations are only an issue for swapping and caching. If you have a bunch of Integers allocated within a block and they're kept hot enough to stay cached, the fact that they're half a gigabyte from the rest of your data matters not at all.

    Tom Hawtin:
    Allocate an individual instance, and it'll be in a row with objects allocated by the same thread at a similar time initially. Depending upon GC algorithm, the instance is also likely to be found just after where it is referenced - good for processor cache and good for TLA buffers.

    Initially - but if the new object outlives everything around it (not too unlikely) then it's an isolated variable, and overall bad for your program performance.

  • (cs) in reply to Crash Magnet
    Crash Magnet:
    And my nomination for best WTF since "Paula Beans".

    Except that this code actually ran and performed a task.

    Paula still has infinitely more WTFiness.

  • storray expert (unregistered) in reply to Bavo
    Bavo:
    AFAIK integers below 256 are always cached automatically which makes

    Integer a = new Integer(3); Integer b = new Integer(3); assert a==b;

    succeed, because they will always poijt to the same instance. Typical JCJP gotcha :)

    Integer a = new Integer(300); Integer b = new Integer(300); assert a==b;

    but this will not.

    wrong

  • Randy (unregistered) in reply to Philipp

    Unless you are an unfortunate SAP user, then 1.4.2 is the ONLY supported version and SAP made a deal with Sun to continue support for 1.4.2. So, if you want to use a newer version of Java, kiss your SAP support goodbye.

  • Jakob Lund Krarup (unregistered) in reply to Ben

    Re: The Integer Cache 2010-01-04 10:44 • by Ben You've made an eggcorn. It's "hare brained", not "hair brained". As in hare, an animal.

    According to Wikipedia (as I read it, I may be wrong) it is not an EggCorn (where the original meaning is preserved) but a Malapropism (http://en.wikipedia.org/wiki/Eggcorn).

    Kind regards - Jakob

  • Herby (unregistered) in reply to David
    David:
    So are we saying that the Real WTF is Java itself?
    No further comment is needed.
  • sagaciter (unregistered) in reply to Randy
    Randy:
    Unless you are an unfortunate SAP user, then 1.4.2 is the ONLY supported version and SAP made a deal with Sun to continue support for 1.4.2. So, if you want to use a newer version of Java, kiss your SAP support goodbye.

    I fail to see where getting rid of SAP is a bad thing.

  • Herby (unregistered)

    Practices like this go back farther than I want to know. I worked on a FORTRAN (ANSI-66) application that the designers thought they could save memory (it was tight in those days) by putting lots of constants in common blocks. I.e.: COMMON /CONSTANTS/ TWOPI/6.28/, ONE /1.0/, ZERO/0.0/

    The problem with this is that on the machine fo the day (IBM 360), it took more instructions to address the common block than it took to address local memory constants. So it was in many cases a NET LOSS to do this. Oh, well. So it goes on. To this day this construct exists in this product. It scares me, because I know what it is used for (SIGH).

  • Mirv (unregistered) in reply to The_Assimilator

    You do know that Integer.valueOf(int i) does exactly this?

  • oheso (unregistered) in reply to LordOfThePigs
    LordOfThePigs:
    You might want to look at String.intern() before you post further comments...

    That documentation is a REAL WTF!!

  • (cs) in reply to Jimmy McJimbo
    Jimmy McJimbo:
    but but but... i dont know java... but... if it just returns a pointer to an existing instance of integer, and i then manualy change its value in my code. Wont the value of the original cached object also change, resulting in a tear in the fabric of space and time itself.

    Nope. In Java, Integers are immutable objects. And since they're objects, "changing the value" of an Integer is actually creating (or getting from the/a cache) a whole other Integer and telling your variable to refer to that one instead.

  • WiSK (unregistered) in reply to Hugh
    Hugh:
    The Integer Cache was just one example of the coding disasters that I ran across.

    Admit it: TRWTF is that out of all the 'disasters' in that project, you picked the one thing that wasn't a WTF.

  • Hugh (unregistered) in reply to WiSK

    I didn't 'pick' that one. I wrote much more than was posted and the editors picked that particular one to emphasize. The application is running Java 1.6 and, as it's been said many times in the comments, Integer.valueOf(int i) does exactly the same thing. That code was completely unnecessary. Do you really believe that developers should create their own implementations of core Java class functions in their applications?

  • CLR (unregistered)

    Funny how c#-- errr.. I mean java developers have strange concerns...

  • Daniel Sobral (unregistered) in reply to Mirv
    Mirv:
    You do know that Integer.valueOf(int i) does exactly this?

    You do know Integer.valueOf(int i) is a Java 1.5 thingy?

Leave a comment on “The Integer Cache”

Log In or post as a guest

Replying to comment #:

« Return to Article