- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
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.
Admin
if ParentID == MathUtil.getInteger(0) first
Admin
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.
Admin
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("!");
Admin
And my nomination for best WTF since "Paula Beans".
Admin
OTOH, maybe you don't need to encapsulate the value in an Integer object in the first place, and a primitive would do the job.
Admin
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)
Admin
(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!)
Admin
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...
Admin
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
Admin
You might want to look at String.intern() before you post further comments...
Admin
Damn, the previous post refers to the one quoted above...
Admin
would be nonsense. Of course, given the general level of proof-reading that seems to go into posts here...
Admin
'MathUtil.getInteger(...)' needs to be rewritten for the enterprise:
Admin
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.
Admin
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.
Admin
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)
Admin
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.
Admin
@Bellinghman
Might be interesting for customers:
http://java.sun.com/j2se/1.4.2/
Admin
Admin
mr_smith, you forgot to submit your code with your post.
Admin
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.
Admin
Admin
(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.
Admin
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.
Admin
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 :)
Admin
Admin
Who even does
anyway? That line in itself is a WTF.Admin
And you might want to refer to Psuedocode.
Admin
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)!
Admin
You've made an eggcorn. It's "hare brained", not "hair brained". As in hare, an animal.
Admin
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!
Admin
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!
Admin
Admin
The caching is much older than 1.5. Only that specific method is not.
Admin
Xeron wins the thread. \o/
Admin
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.
Admin
Bellinghman:
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.Admin
In a fit of pedantry, I feel obligated to point out that "maze of twisty passages, all alike" is from Adventure. Not Zork.
Admin
You seem to underestimate the utility of having an Integer object, especially if you're dealing with generics.
Also, while valueOf caches too, remember that valueOf caches frequently used values, which presumably means that a number greater than 256 could get cached and unused numbers less than 256 wouldn't be. He's decided to limit "caching" to numbers less than 256, I guess because otherwise it'd be a self-defeating memory hog. So there's a pre-built integer for 17 and 31, but not one for 512 and 1024. That's why this is a WTF, not just a reimplemented library function.
Admin
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.
Admin
So are we saying that the Real WTF is Java itself?
Admin
Writing performance critical code in Java is stupid.
Admin
No, a Good Programmer (TM) never uses any constants.
You have to bootstrap a few things like this, but after that it is easy:
Admin
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++.
http://blogs.azulsystems.com/cliff/2009/09/java-vs-c-performance-again.html
Admin
I dare you to write your database engine in pure Java.
Admin
What, like one of these?
http://java-source.net/open-source/database-engines
Admin
By the way, the idiom is "hare-brained," not "hair-brained." It goes along with the one about "mad as March hare."
Admin
Please excuse the typo on 'hair-brained'.
The portal was built using Java 6. Everyone that I've spoken with who knows the history of the project is glad that the lead developer who built it is no longer with the company. The Integer Cache was just one example of the coding disasters that I ran across.
Here are some additional highlights.
Every URL on the portal is the same no matter what page you go to. Most pages are derived from information in classes that are cached in the user's session. OK, they didn't want the user bookmarking pages or something like that. Unfortunately, they didn't take into account the fact that a user might hit the browser's back button. So, when you go back and select something else, the session's objects aren't current and it throws lots of errors. It also had the interesting feature of updating the session objects and refreshing the entire page whenever a user selected an item from a picklist.
There was another page that displayed up to 10 tables of results in alternating colors. For some reason, they decided to create 10 sets of variables like table1, table2, table3, etc. to put the yellow table data in and another 10 sets like table21, table22, table23, etc. to put the green items in. The data was stored such that if table1 had data, table21 would not. So that if you had 10 tables displayed, the data would be stored like this:
There was a lot of code dedicated to storing and then trying to figure out which variables had the table data that they were processing. There were additional variables that were tracking which tableX and table2X variables had data in them rather than examining the tables.
I managed to reduce the 10,000 line class file with over 300 variables of the form var, var2, var3, entry, entry2, entry3, etc. Note that the first one was not named var1 as you would expect. This added an extra level of fun while trying to reorganize the variables. After putting 30 sets of variables into similarly named lists, the class was reduced to a more manageable 2000 lines. Still bloated but, you could now get a sense of what it was supposed to be doing. Most of the variables also had public getters and setters that are accessed from the JSF pages that they built this in. I ended up putting 1000 lines of variables along with their getters and setters in a separate class so that I could find the main business methods in the class.
The 2500 line method was nothing more that a pair of nested loops that reduced to less than 100 lines of code. The method originally looked like this:
Another odd trait was the unnecessary copy and pasting that was going on. I have found numerous examples like the one above where large blocks of code were wrapped in an if statement and copied into the else statement with only one line changed.
Oh, I almost forgot. The database also contained a number of parent tables that were referenced throughout the code with a specific numbering scheme. But, when you want to create a link between two tables, the data was stored using a different numbering scheme. Of course, the data was stored as numbers in the database so that it isn't readable and this feature isn't documented in the code. Those numbers were in a separate helper table in the database. The trick is that only four of the tables have different storage numbers from their application counterparts which meant that I literally had to stumble across it when I was testing saves to one of those four tables.
Again, these are just the highlights. There are more.
Admin
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.