• The_Assimilator (cs)

    PROTIP: if you're trying to fix performance problems by caching integers, you're Doing It Wrong(tm).

    ...

    Screw that... if you're caching integers in any scenario, you're doing it so wrong you should probably shouldn't have tried to be a programmer in the first place.

    Also, FRIST.

  • anonym (unregistered)

    if ParentID == MathUtil.getInteger(0) first

  • jspenguin (cs)

    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.

  • SR (unregistered)

    StringUtil.getString("G"); StringUtil.getString("o"); StringUtil.getString("o"); StringUtil.getString("d"); StringUtil.getString(" "); StringUtil.getString("G"); StringUtil.getString("r"); StringUtil.getString("i"); StringUtil.getString("e"); StringUtil.getString("f"); StringUtil.getString("!"); StringUtil.getString(" "); StringUtil.getString("W"); StringUtil.getString("h"); StringUtil.getString("a"); StringUtil.getString("t"); StringUtil.getString(" "); StringUtil.getString("a"); StringUtil.getString(" "); StringUtil.getString("M"); StringUtil.getString("u"); StringUtil.getString("p"); StringUtil.getString("p"); StringUtil.getString("e"); StringUtil.getString("t"); StringUtil.getString("!");

  • Crash Magnet (unregistered)

    And my nomination for best WTF since "Paula Beans".

  • F (unregistered) in reply to jspenguin
    Comment held for moderation.
  • Phill (cs)

    Ok, so this is stupid but maybe not as stupid as it first seems... He is not caching ints, he's caching the Integer object representation of an int. If he was regularly using loads of Integer objects for values below 256, this might save some memory. As the latest GC implementations optimise towards short lived objects though, I doubt there would be any significant gain, and all for the sake of some horrible code. And I hope he has a good reason for not just using an int as the ParentId - or is Java's nullable int implementation really that bad? (seems like he's using the magic number 0 for null anyway)

  • Bellinghman (cs) 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.

    It's barely possible that the original coder actually anticipated standard library functionality, since that feature didn't arrive in Java until 1.5.

    (Sadly, when I'm required to write Java, I have to ensure the result works under 1.4, because some customers won't update their Java installs beyond that point. Java 7? Hah!)

  • LordOfThePigs (unregistered)

    Well, the principle is not that stupid at all since this is already what the JRE does. The Java specification requires the instances of the Integer class representing integer numbers between -128 to 127 to be cached. Also in java,

    Integer customerId = 0;

    compiles in bytecode to

    Integer customerId = Integer.valueOf(0);

    which returns the cached instance of 0. This avoids a lot of garbage collection, and can save a significant amount of memory, since the minimal memory size of an object in java is 2 pointers (so 8 or 16 bytes depending on your platform) + the size of whatever members it contains. 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.

    Now what is stupid is that the libraries already do it for you, but as the comments show, many people don't know that...

  • pjt33 (cs) 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.

    That's what I thought too. If caching small Integers is a WTF then the post should be about Sun's API implementation rather than some random guy working for an unspecified company.

    -- Submission attempt 3

  • LordOfThePigs (unregistered) in reply to SR
    Comment held for moderation.
  • LordOfThePigs (unregistered) in reply to SR
    SR:
    StringUtil.getString("G"); StringUtil.getString("o"); StringUtil.getString("o"); StringUtil.getString("d"); StringUtil.getString(" "); StringUtil.getString("G"); StringUtil.getString("r"); StringUtil.getString("i"); StringUtil.getString("e"); StringUtil.getString("f"); StringUtil.getString("!"); StringUtil.getString(" "); StringUtil.getString("W"); StringUtil.getString("h"); StringUtil.getString("a"); StringUtil.getString("t"); StringUtil.getString(" "); StringUtil.getString("a"); StringUtil.getString(" "); StringUtil.getString("M"); StringUtil.getString("u"); StringUtil.getString("p"); StringUtil.getString("p"); StringUtil.getString("e"); StringUtil.getString("t"); StringUtil.getString("!");

    Damn, the previous post refers to the one quoted above...

  • pjt33 (cs) in reply to Bellinghman
    Bellinghman:
    It's barely possible that the original coder actually anticipated standard library functionality, since that feature didn't arrive in Java until 1.5.
    Nor did auto-boxing, which means that the post's observation
    The original post:
    seemed like an overly complex way of writing "ParentID = 0;"

    would be nonsense. Of course, given the general level of proof-reading that seems to go into posts here...

  • c0rnh0li0 (unregistered)

    'MathUtil.getInteger(...)' needs to be rewritten for the enterprise:

    public static Integer getInteger(final int i) {
      try {
        return arrCachedIntegers[i];
      } catch(ArrayIndexOutOfBoundsException e) {
        return new Integer(i);
      }
    }
    
  • mr_smith (unregistered) in reply to LordOfThePigs
    LordOfThePigs:
    Well, the principle is not that stupid at all since this is already what the JRE does. The Java specification requires the instances of the Integer class representing integer numbers between -128 to 127 to be cached. Also in java,

    Integer customerId = 0;

    compiles in bytecode to

    Integer customerId = Integer.valueOf(0);

    which returns the cached instance of 0. This avoids a lot of garbage collection, and can save a significant amount of memory, since the minimal memory size of an object in java is 2 pointers (so 8 or 16 bytes depending on your platform) + the size of whatever members it contains. 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.

    Now what is stupid is that the libraries already do it for you, but as the comments show, many people don't know that...

    The worst thing about the daily wtf is that there is a whole group of wtf makers hanging around trying to pretend they are good developers. I see this as the "actively pick on somebody else so they won't notice me" strategy.

  • Procedural (unregistered)

    Minor quibble, but it is "hare brain". Nervous small brain, mostly concerned with sex and eating, not a great strategist. That`s why it is so often opposed to the fox in stories.

  • grzlbrmft (unregistered)

    Well, if you have some boiling water left, put it in the freezer, in case you need it later!

    (I know that's not a new one, but it came to my mind when I saw that WTF)

  • Schobi (unregistered) in reply to Bellinghman
    Bellinghman:
    [...] (Sadly, when I'm required to write Java, I have to ensure the result works under 1.4, because some customers won't update their Java installs beyond that point. Java 7? Hah!)

    Wait a minute! There exists a version 7 of Java? That must be joke, right? I mean, everybody knows that Java versions go up to 6 but not beyond.

  • Philipp (unregistered) in reply to Bellinghman
    Comment held for moderation.
  • tego (unregistered) in reply to Schobi
    Comment held for moderation.
  • Calling Out Hypocrites (unregistered) in reply to mr_smith
    mr_smith:
    The worst thing about the daily wtf is that there is a whole group of wtf makers hanging around trying to pretend they are good developers. I see this as the "actively pick on somebody else so they won't notice me" strategy.

    mr_smith, you forgot to submit your code with your post.

  • Vlad Patryshev (unregistered)

    Looks suspiciously familiar. I saw this kind of cache pretty recently. Not that it is being used these days of enlightenment, but the cache is still there, by the principle that that that is is right.

  • Bellinghman (cs) in reply to Philipp
    Philipp:
    @Bellinghman

    Might be interesting for customers:

    http://java.sun.com/j2se/1.4.2/

    J2SE 1.4.2 is in its Java Technology End of Life (EOL) transition period. The EOL transition period began Dec, 11 2006 and will complete October 30th, 2008, when J2SE 1.4.2 will have reached its End of Service Life (EOSL).
    Aye. And don't mention Windows 200 either, please.
  • Bellinghman (cs) in reply to pjt33
    pjt33:
    Nor did auto-boxing, which means that the post's observation
    The original post:
    seemed like an overly complex way of writing "ParentID = 0;"
    would be nonsense. Of course, given the general level of proof-reading that seems to go into posts here...
    Ah, good point.

    (My brain saw that, and momentarily flipped into C++ mode, reading the "= 0" as "= null". Bad brain. No caffeine for you.)

    I suppose it's vaguely conceivable that the Integer caching was added in a pre-1.5 version, and that when auto-boxing arrived with 1.5, that facility was gratefully received, but the internal caching wasn't noticed.

    I do wonder whether the coder had ever measured whether the generation of lots of Integer objects caused any problems in the first place.

  • Vlad Patryshev (unregistered) in reply to F

    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.

  • Jamie (unregistered)

    The maze of twisy passages was from Zork's predecessor the original and the best Collosal Cave Adventure. I once wrote a port of Collosal Cave Adventure for a bizzare programming language as part of a research project :)

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

    Who even does

    new Integer(0)
    anyway? That line in itself is a WTF.

  • SR (unregistered) in reply to LordOfThePigs
    Comment held for moderation.
  • ClutchDude (unregistered) in reply to Bellinghman
    Bellinghman:
    (Sadly, when I'm required to write Java, I have to ensure the result works under 1.4, because some customers won't update their Java installs beyond that point. Java 7? Hah!)

    You too?!?!?!?

    Our codebase has been 1.4.2 since the project's inception.

    Thankfully, we're moving to 1.6 before too long. The code is migrated and regression testing needs to be done.

    Convenience for-loops, autoboxing, and generic support for all(And more stuff since 1.5)!

  • Ben (unregistered)

    You've made an eggcorn. It's "hare brained", not "hair brained". As in hare, an animal.

  • Xeron (cs)

    What an idiot! Rather than pre-cache integers 0-255 in the constructor, he should use the array to store the 256 most used integers!

    The constructor would simply mark all elements of the array as unused (why not use an array of boolean values for such a purpose?).

    Then, when a function requests an integer, iterate through the array, and when the integer of required value is found, return it. If it isn't found, iterate through the array to find an unused slot, and cache the new integer there.

    If the array is full, why not re-allocate it as a bigger array? Then you can cache every integer you ever use!

    You could even log every integer access to a file, and analyse the results to optimise integer usage; why use 6 when 5 is near enough and is already being used by another function?!

    In fact, it could analyse the logs itself and identify the most used integers, then parse its own source code to find integers that are "near enough" and change them, recompile itself, launch a new instance and quit. That way it is SELF OPTIMISING!

  • Xeron (cs) in reply to Xeron

    Oh... but then, you could store every integer in an SQL table, then retrieve it before calling getInteger() on the result. That way, the program only has to modify the SQL table like this:

    UPDATE Integers SET Value=5 WHERE Actual=6

    then you wouldn't need to recompile the app; it automatically uses "near enough" values straight away!

  • dkf (cs) in reply to Bellinghman
    Bellinghman:
    I do wonder whether the coder had ever measured whether the generation of lots of Integer objects caused any problems in the first place.
    I've got code where it is a big win when processing can generate lots of immutable objects (not in Java as it happens, but it's an equivalent principle). Basically, you're using the Flyweight pattern with highly-sharable objects, and if you're managing to get a good amount of sharing of references going, that's a delicious win. In fact, it turned out to be such a big win when we deployed that code in practice that it was enabled even for cases where it was not a big win (the cost of the cache building was surprisingly small, the poor-performance cases unlikely).
  • Jones (unregistered) in reply to Bellinghman
    Comment held for moderation.
  • xtremezone (cs)

    Xeron wins the thread. \o/

  • Bavo (unregistered)

    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.

  • Daniel Pitts (unregistered) in reply to Bellinghman

    Bellinghman:

    Sadly, when I'm required to write Java, I have to ensure the result works under 1.4, because some customers won't update their Java installs beyond that point. Java 7? Hah!
    That is very sad. Even Java 1.5 is end of life. You should tell your customers that there are significant performance and security improvements in Java 1.6. You wouldn't be lying, even though your motivation would be the ability to use an improved language.
  • fbomb (unregistered)

    In a fit of pedantry, I feel obligated to point out that "maze of twisty passages, all alike" is from Adventure. Not Zork.

  • aristos_achaion (unregistered) in reply to F
    Comment held for moderation.
  • Chris (unregistered) in reply to Bavo

    Uhhh... no, both object comparisons will fail because you explictly created new objects. If you create the Integers using autoboxing or Integer.valueOf() then what you say has some merit however.

    Note though that the actual default range that is cached is -128 to 127. In more recent JDKs you can override the upper limit by setting the java.lang.Integer.IntegerCache.high system property.

    There are more WTFs in these comments than the original post - in fact the original code is a valid solution to a (possibly) valid problem. We have similar caches and object pools in our codebase where we need them. In some cases the performance boost is huge.

  • David (unregistered)

    So are we saying that the Real WTF is Java itself?

  • frits (cs)

    Writing performance critical code in Java is stupid.

  • Prof (unregistered)
    ParentID = MathUtil.getInteger(0)
    But even that is wrong, because there's still a hard-coded integer in your source, and hard-coded programs are inflexible. Besides, who knows what the zero (or other constant) represents? It isn't documented! How did you arrive at that value?

    No, a Good Programmer (TM) never uses any constants.

    You have to bootstrap a few things like this, but after that it is easy:

    # create a zero by clearing out any debris that may have been in memory
    Z = Z - Z
    # create a one (true)
    I = (Z == Z)
    # two
    T = I + I
    # and so on...
    
  • Chris (unregistered) in reply to frits
    Comment held for moderation.
  • frits (cs) in reply to Chris

    I dare you to write your database engine in pure Java.

  • Chris (unregistered) in reply to frits
    Comment held for moderation.
  • DAT (unregistered)

    By the way, the idiom is "hare-brained," not "hair-brained." It goes along with the one about "mad as March hare."

  • Hugh (unregistered) in reply to Jones
    Comment held for moderation.
  • PK (unregistered)

    H2 database was written in Java and its way faster than PostgreSQL which was written in C or MySQL which was written in C++.

    Databases are probably the best example of the system, where "performance of the language" does not count. What counts is algorithms. In databases world probably more than anywhere else. It is more likely to get better/more advanced algorithms writing in some high-level language than using plain old C.

Leave a comment on “The Integer Cache”

Log In or post as a guest

Replying to comment #:

« Return to Article