
Have you ever had such situations when your Java application is cracking at the seams? In my case it happened due to the lack of available RAM. And, of course, there was a shortage at the most inopportune moment: another long-awaited release is on the nose, one of the servers is stopped for updating the code and data and the reincarnation of the old code is no longer possible; In general, the emergency has not gone unnoticed.
By the way, if I had made the correct backup and the emergency work on the restoration of viability would have passed much more calmly, but this would have been a completely different story. So at my disposal there is a code that lacks 15Gb of RAM for normal operation and a very long and expensive startup process (about 5 hours), during which you can only sit with crossed fingers and hope that this time the cherished words OutOfMemoryException are not appear in the console of the remote server.
I will not describe all the tricks that had to be done to restore the stopped server within three days, but I’ll share one of my mini discoveries -
boolean is not the type of data that you want to use in high-load systems. Attention question:
How do you think, how much memory does boolean take for example on Ubuntu server x64?
The correct answer is:
unknown and depends only on the implementation of the JVM.')
Consider the common Sun JVM and read in the virtual machine specification that
there is no boolean type as such , int is used instead! This means that exactly 32 bits are used to store a “yes / no” value, regardless of the processor architecture. However, in the same section, we see that optimization has been made for working with boolean arrays, which are converted into an array of bytes, which gives an increase in available memory by 4 times. And yet, paying for storing a zero or one family with seven extra bits - sometimes just blasphemy and mockery of servers (especially with arrays of 500 million items).
The salvation in such cases will be the BitSet class, which behaves like a boolean array, but packs the data so that only one bit of memory is allocated for one bit (with low overhead for the entire array). BitSet stores an array of the long type inside it, and when requesting or setting the value of a specific bit, it calculates the index of the desired long, and using bitwise and shift operations it performs calculations on a single bit.
There is an even more interesting BitSet implementation,
OpenBitSet is an Apache implementation that is used for Lucene. It is much faster, but it misses some of the checks carried out on the original BitSet. What to use is up to you.