Most efficient initial capacity size for StringBuilder?

I write a lot of material for registering packages and optimizing the data path. I am StringBuilder log text using StringBuilder . What would be the most efficient initial capacity, would memory management be reasonable, so that would work well regardless of the JVM? The goal is to avoid redistribution almost always, which should be covered by an initial capacity of about 80-100. But I also want to spend as few bytes as possible, since an instance of StringBuilder can be buffer-hung and wasting bytes.

I understand that it depends on the JVM, but there must be some value that will spend fewer bytes, regardless of the JVM, a kind of "least common denominator". I am currently using 128-16 , where 128 is a good round number, and subtraction is for overhead. In addition, this can be seen as a case of "premature optimization", but since the answer I received is the number of the "thumb rule", knowing that it will be useful in the future.

I do not expect answers to “my best assumptions” (my own answer above already exists), I hope someone already researched this and can share the answer based on knowledge.

+5
source share
2 answers

Well, I ended up testing this myself, and then testing a few more comments to get an edited answer.

Using JDK 1.7.0_07 and a test application reporting the name of the virtual machine “Java Server HotSpot (TM) 64-bit Server VM”, the memory granularity of StringBuilder is 4 characters, increasing even by 4 characters.

Answer: any few of 4 is equally good for a StringBuilder from a memory allocation point, at least on this 64-bit JVM.

Tested by creating 1,000,000 StringBuilder objects with different initial capabilities, in different executions of the test program (for the same state of the initial heap) and printing ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() before and after.

It also confirms that the size of the print heap is also confirmed that the amount actually allocated from the heap for each StringBuilder buffer is equal to the even edge of 8 bytes, as expected since Java char has a length of 2 bytes. In other words, allocating 1,000,000 copies with an initial capacity of 1..4 takes about 8 megabytes less memory (8 bytes per instance) than allocating the same number of isntances with an initial capacity of 5 ... 8.

+3
source

Do not try to be smart in this case.

I am currently using 128-16, where 128 is a good round number, and subtraction is for overhead.

In Java, this is based on completely arbitrary assumptions about the internal workings of the JVM. Java is not C. Byte alignment and the like is absolutely not a problem that a programmer can or should try to use.

If you know the (probable) maximum length of your lines, you can use it for the initial size. In addition, any optimization attempts are simply in vain.

If you really know that a huge amount of your StringBuilder will remain for very long periods of time (which doesn’t quite match the concept of logging), and you really feel the need to try to convince the JVM to save some bytes, you can try to use trimToSize() after the line will be built completely. But, again, until your lines spend megabytes each, you really need to go and focus on other issues in your application.

+4
source

Source: https://habr.com/ru/post/906542/


All Articles