Incrementing large numbers
Nov. 29th, 2017 08:16 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
At work I program in Java 7 mostly. I was asked to add some statistics-gathering to some code that gets called a lot so performance is key. After some initial test runs, back-of-the-envelope calculations about for how long our servers may run, etc., I did not feel safe in assuming that even a eight-byte long counter would never wrap around. In practice, I do not think a production server facing a continuously heavy workload during many years' uptime would come close to overflowing my long but I am used to having so much margin to work with that I do not even have to think about the issue.
A surprising discovery for me is that Java 7 does not offer efficient incrementing of arbitrarily large integers. Coming from a functional programming background I appreciate immutable values but I also appreciate compilers that can optimize much of the heap allocation out of the native code they generate. I have far less faith in what Java does, or indeed may do, with BigInteger, and people on the Internet already seem to have done some performance testing.
Fortunately, not all surprising discoveries are bad. It also turns out to be easy to increment an arbitrarily large integer with few heap allocations by storing it as a byte array, here named count:
A surprising discovery for me is that Java 7 does not offer efficient incrementing of arbitrarily large integers. Coming from a functional programming background I appreciate immutable values but I also appreciate compilers that can optimize much of the heap allocation out of the native code they generate. I have far less faith in what Java does, or indeed may do, with BigInteger, and people on the Internet already seem to have done some performance testing.
Fortunately, not all surprising discoveries are bad. It also turns out to be easy to increment an arbitrarily large integer with few heap allocations by storing it as a byte array, here named count:
To log the statistic readably it suffices to return new BigInteger(1, count).for (int index = count.length; index > 0;) if (++count[--index] != 0) return; count = new byte[count.length + 1]; count[0] = 1;
no subject
Date: 2017-11-29 06:54 pm (UTC)How many increments per second does the problem need?
no subject
Date: 2017-11-29 07:56 pm (UTC)It may not actually be much more than a few tens of thousands of increments per second which of course by modern standards is nothing, but I've not worked hard to be sure of an upper limit and we seem to increase the scale of data we want to push through the system faster than we can comfortably scale the system itself, so I'm worried that we may be up some orders of magnitude before anybody ever looks again at the code.
Update: Ah, I realize I was probably unclear: when I write of returning the BigInteger, I didn't mean from the increment method: I probably snipped too much context!
no subject
Date: 2017-11-30 05:47 pm (UTC)no subject
Date: 2017-11-30 05:54 pm (UTC)