• Post Reply Bookmark Topic Watch Topic
  • New Topic

java string pool  RSS feed

 
David Spades
Ranch Hand
Posts: 348
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In Java 6, which one is better, or are they both the same?



lets assume that doSomething() is called a million times. Thanks
 
Joe Harry
Ranch Hand
Posts: 10128
3
Eclipse IDE Mac PPC Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Better is to always have state local to your method. Objects are stored in the heap. In your first case the Test object when loaded in memory has to have space for the two String instances (one and two). In the latter case those two String instances gets created only when the method doSomething is called.
 
David Spades
Ranch Hand
Posts: 348
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
yes, but this is string where pool is used. do both methods use string pool? thanks
 
Joe Harry
Ranch Hand
Posts: 10128
3
Eclipse IDE Mac PPC Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I would assume so. I don't see any reason for the JVM to have different behavior with respect to using String pool if they are reference variables of method local variables.
 
Paul Clapham
Sheriff
Posts: 22841
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't know what kind of "better" you had in mind, but...

It's better not to have "magic numbers" in your code. For example if you have this code:



then 34 is a "magic number". Why is 34 used and not 43, for example? It's better to document that by making the magic number a constant, like this:



and then to use the constant in your code.

So... your code has "magic strings" in it. What do you think now?
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To take Paul's post as a jumping off point, this:

is, as far as the doSomething code is concerned, compiled into the same code as this:

So "better" has nothing (as with most things in Java when dealing with small scale stuff like this) to do with performance. It's more to do with ease of managing the code. Code maintenance is a far bigger job than initial development.
 
Aaron Shawlington
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
OP is talking about the String pool, and says "lets assume that doSomething() is called a million times. Thanks". So obviously he's asking from a performance perspective.

As far as I'm aware, they're both the same.
 
Jude Niroshan
Ranch Hand
Posts: 132
5
Eclipse IDE Java Postgres Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If we concern this in performance aspect,

I see both the methods are pretty ok. But i feel, creating two strings inside the method for million times, might take some time than having two local variables. Because if we create new strings inside a local method, java needs to go to string pool and see whether that newly created string is already available in the pool. But if we have a static local variable, java will just take that string instead of drowning into the pool and search for that string is already there or not.
That's hw i think about this. Correct me if i am wrong.
Regards,
Jude
 
Paul Clapham
Sheriff
Posts: 22841
43
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jude Niroshan wrote:But i feel... That's hw i think about this. Correct me if i am wrong.


Guessing about performance issues is always the wrong thing to do. In this case your reasoning is wrong because the two string constants in question are put into the string pool only once each regardless of which version of the code we are talking about. Your idea of the code repeatedly looking into the string pool to see if a particular constant is there, well, that's actually not how it works. That's what I mean about guessing about performance issues. The right thing to do is to actually test the performance of two (or more versions) of whatever you're asking about. It isn't easy to write a good performance test, but guesswork is worse.
 
Jude Niroshan
Ranch Hand
Posts: 132
5
Eclipse IDE Java Postgres Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'll take that into consider sir.
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Aaron Shawlington wrote:OP is talking about the String pool, and says "lets assume that doSomething() is called a million times. Thanks". So obviously he's asking from a performance perspective.

As far as I'm aware, they're both the same.


Well, I did say that:
"is ... compiled into the same code ... (s)o "better" has nothing ... to do with performance."
 
Vitaliy Gaydarenko
Greenhorn
Posts: 22
IntelliJ IDE Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think,it will be better:

public class Test {
private StringBuffer sb = new StringBuffer();
private static final String one = "string 1";
private static final String two = "string 2";

public void doTest(String addStr) {
if (sb.length() > 0)
sb.delete(0, sb.length());
sb.append(one).append(addStr).append(two);
.....
}
}
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There's little point in creating a StringBuilder for a single line String concatenation.
The compiler will do it for you, which means the code will (generally) be more readable if you just let it do that.
 
Aaron Shawlington
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote:

Well, I did say that:
"is ... compiled into the same code ... (s)o "better" has nothing ... to do with performance."


Sure. Just highlighting that as the OP's code doesn't actually do anything, I would assume that he's not interested in hearing abut magic numbers etc. Otherwise what would be 'better' would be to just delete the pointless method :P


On the StringBuilder topic (for the poster previously) - basically it tends to be inside loops where the compiler doesn't automatically convert to use a StringBuilder. E.g:



I'm sure there's probably a good reason for it.
 
Vitaliy Gaydarenko
Greenhorn
Posts: 22
IntelliJ IDE Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For one string it is really not profitable, but I think it will be other manipulations with this String in code. And in this case, it has meaning.
 
Vitaliy Gaydarenko
Greenhorn
Posts: 22
IntelliJ IDE Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
StringBuilder recommended use in applications without multi thread.
StringBuffer used when there are 2 or more threads.
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Vitaliy Gaydarenko wrote:For one string it is really not profitable, but I think it will be other manipulations with this String in code. And in this case, it has meaning.


Oh yes, most definitely.
In those cases, with drawn out concatenation you run the risk of the compiler creating multiple StringBuilders, which is clearly inefficient.
 
Vitaliy Gaydarenko
Greenhorn
Posts: 22
IntelliJ IDE Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote: ... creating multiple StringBuilders, which is clearly inefficient.

Why it will be creating multiple StringBuilders? StringBuilder create one time, in time when class will be initialized.
 
Dave Tolls
Ranch Foreman
Posts: 3068
37
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Vitaliy Gaydarenko wrote:
Dave Tolls wrote: ... creating multiple StringBuilders, which is clearly inefficient.

Why it will be creating multiple StringBuilders? StringBuilder create one time, in time when class will be initialized.


When this code is compiled:

the compiler creates a StringBuilder for each of those '+=' lines.
That is clearly less efficient than declaring a StringBuilder and using that.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To Paul's earlier point, programmers are notoriously bad at performance tuning based on intuition and gut feeling. If performance is really a concern, dont' guess, use a profiler. If you're going to make any statement about how one piece of code performs vs another, you should at least back that statement up with this information:

1. Concrete proof about your assertion in the form of test results
2. The version(s) of Java you used to test your assertion

The Java compiler has undergone many optimizations over the years of its existence so unless you're an ubergeek who has tracked and memorized the history of all these optimizations, any offhand statement offered without the above information is probably just an opinion and most everyone has one those so,
¯\_(ツ)_/¯

(Edit: this is not addressed to any particular post/poster in this thread, it's just about the discussion in general)
 
Aaron Shawlington
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dave Tolls wrote:
the compiler creates a StringBuilder for each of those '+=' lines.


Good point - i've never bothered to try that out before. I had assumed that it just couldn't handle loops.

**edit** for interest:


 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Aaron Shawlington wrote:
**edit** for interest:



... or provide an analysis of the generated bytecode

What version of Java is this though?
 
Vitaliy Gaydarenko
Greenhorn
Posts: 22
IntelliJ IDE Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have a little test:
String s = "Start ";
for (int i = 0; i < 100000; i++) {
s += i;
}
System.out.println(s);

and
StringBuilder sb = new StringBuilder("Start ");
for (int i = 0; i < 100000; i++) {
sb.append(i);
}
System.out.println(sb.toString());

Speed of second (with Builder) is greater in thousands time.
And so, with Builder is much better than without it.
 
Aaron Shawlington
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also just had a thought... you specifically mention Java 6. There were some changes to the String pooling in one of the minor version updates (which you may or may not be referring to or interested in).

It used to be the case (unless I'm remembering it back-to-front) that "FOOBAR" and "FOO" were backed by the same character array, with the first string just having a reference to the last character at index 5 and the second string at index 2.

Now each string gets it's very own character array all for itself, and if you want to optimise and have the old behaviour then you need to implement it yourself.

That's the rough idea anyway - it's been a while since I looked into those changes.
 
Aaron Shawlington
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:
What version of Java is this though?


1.8.0 of whatever comes with OSX - unless I symlinked it to my homebrew installation :s
 
Aaron Shawlington
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Vitaliy Gaydarenko wrote:I have a little test:
String s = "Start ";
for (int i = 0; i < 100000; i++) {
s += i;
}
System.out.println(s);

and
StringBuilder sb = new StringBuilder("Start ");
for (int i = 0; i < 100000; i++) {
sb.append(i);
}
System.out.println(sb.toString());

Speed of second (with Builder) is greater in thousands time.
And so, with Builder is much better than without it.


Do you understand why it makes a difference in tis test, but not your first example? (assuming you trust that it wouldn't - as it compiles to the same bytecode)
 
Vitaliy Gaydarenko
Greenhorn
Posts: 22
IntelliJ IDE Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I emulated two situations about what we speak. And compare results.
We talk about resources, not abut that it will be a same code.
 
Aaron Shawlington
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Vitaliy Gaydarenko wrote:I emulated two situations about what we speak. And compare results.
We talk about resources, not abut that it will be a same code.


Sure... but using different code to wonder about different resource usage implications of writing that different code, doesn't make any sense when that code compiles down the the same thing. I.e. the different in the code that you're analysing is illusory (for want of a better word).

The last example you posted doesn't compile down to the same thing both times, so it's a valid test. Fine.

So what I'm checking is that you understand *why* using the StringBuilder is more efficient in the second example than not using it - and that you understand *why* it makes no difference in the first example (although I suppose I answered my own question when I said it compiles to the same thing).

The first is important to understand in order to have some mechanical sympathy wen writing code (although most of the time it doesn't matter too much).
The second is important because it can save you from writing theoretically more optimal, yet redundant, code at the cost of readability.
 
Vitaliy Gaydarenko
Greenhorn
Posts: 22
IntelliJ IDE Java Oracle
 
Paul Clapham
Sheriff
Posts: 22841
43
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is an interesting discussion, certainly, but if it deters people from writing



in favour of a more complicated expression involving a StringBuilder then I would say it's a harmful discussion. That's just my opinion though.
 
Aaron Shawlington
Ranch Hand
Posts: 50
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think I need to apologise to Vitaliy... For some reason I was thinking that you and the OP were the same person! No wonder my question didn't make sense to you.
 
Tim Holloway
Saloon Keeper
Posts: 18800
74
Android Eclipse IDE Linux
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Modern-day compilers are capable of some pretty impressive optimizations. Even fairly ancient ones routinely did compile-time expression folding. If there's any way that the compiler can deduce an optimal case at compile-time, then chances are that it will take it, even if it isn't doing something you'd think of yourself.

The ability to second-guess gets even more confused when you consider that Java JVM code is subject to JIT compiling and that may carry another set of optimizations on top of the basic JVM instructions as the code reduces to the native machine language. Not only are there machine-language tricks that can be played (a friend of mine once used a floating-point normalization instruction to find the first non-zero bit in a bitstring), but some machines, such as IBM mainframes have some rather unusual CISC instructions, such as the one that can scan a string of characters looking for special tokens. Or more recent mainframe instructions that actually implement certain C stdlib functions such as strcat as single machine-language instructions.

Then, just to further muddy the waters, dynamic code analysis can cause the JIT compiler to discard generated code and replace it with code that's more efficient for the measured usage.

So I simply refuse to "code optimally" at the low level anymore. There's simply no point in it. I could actually end up defeating the built-in optimizations. Instead I worry more about readability and concentrate on efficient algorithms, which can generally gain a whole lot more performance than low-level tweaking ever will. Bearing in mind that what's the most efficient algorithm may vary with the workload. The Heap and Quick sorts are "efficient', but not if the data is already highly ordered. In that case a bubble or shell sort may perform better (I can cite a real-world case where this was true).

It has been said long ago and it remains true that you can optimize clean code better than you can re-optimize kinky optimized code when it turns out that (as is often the case) that the real performance bottlenecks aren't where you "knew" they'd be.

So code clean, then if things don't suit, run performance measurement tools so you won't be wasting time optimizing places that don't pay to be optimized.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!