RFR 4641897: Faster string conversion of large integers
Dmitry Nadezhin
dmitry.nadezhin at gmail.com
Sat Jun 22 09:11:58 UTC 2013
Below are the results of performance evaluation:
1) Performance improvement of specialized method bi.toHexString() against
general bi.toString(16).
2) Code ot hypothetical BigInteger.toHexString();
3) Code of benchmark.
-Dima
=== b.bitLength(); b.toString(16); b.toHexString();
bitLength=2047; 0.001458205 sec 3.11251E-4 sec
bitLength=4095; 0.003836644 sec 6.14027E-4 sec
bitLength=8191; 0.01112082 sec 0.001148153 sec
bitLength=16383; 0.009785916 sec 0.00256648 sec
bitLength=32767; 0.024226532 sec 0.005104734 sec
bitLength=65535; 0.040899736 sec 0.001239427 sec
bitLength=131071; 0.057398824 sec 0.002302767 sec
bitLength=262143; 0.13263946 sec 0.004272388 sec
bitLength=524287; 0.44488142 sec 8.64876E-4 sec
bitLength=1048575; 1.628629919 sec 0.001423972 sec
bitLength=2097151; 6.399754105 sec 0.002084977 sec
bitLength=4194303; 25.052650526 sec 0.004460035 sec
bitLength=8388607; 100.974373978 sec 0.009238686 sec
bitLength=16777215; 407.2107094 sec 0.018795085 sec
===
=== The code of BigInteger.toHexString()
public String toHexString() {
if (signum == 0) {
return "0";
}
int highestLimb = mag[0];
int digitsInHigherLimb = 8 -
Integer.numberOfLeadingZeros(highestLimb) / 4;
int len = (mag.length - 1) * 8 + digitsInHigherLimb;
if (signum < 0)
len++;
StringBuilder buf = new StringBuilder(len);
if (signum<0)
buf.append('-');
for (int i = digitsInHigherLimb - 1; i >= 0; i--) {
buf.append(Character.forDigit((highestLimb >> (i * 4)) & 0xF,
16));
}
for (int i = 1; i < mag.length; i++) {
int m = mag[i];
buf.append(Character.forDigit((m >> 28) & 0xF, 16));
buf.append(Character.forDigit((m >> 24) & 0xF, 16));
buf.append(Character.forDigit((m >> 20) & 0xF, 16));
buf.append(Character.forDigit((m >> 16) & 0xF, 16));
buf.append(Character.forDigit((m >> 12) & 0xF, 16));
buf.append(Character.forDigit((m >> 8) & 0xF, 16));
buf.append(Character.forDigit((m >> 4) & 0xF, 16));
buf.append(Character.forDigit(m & 0xF, 16));
}
return buf.toString();
}
===
=== The benchmark program
public class TestToString {
public static void main(String[] args) {
int n = 1;
BigInteger bi = BigInteger.ONE;
System.out.println("b.bitLength(); b.toString(16);
b.toHexString();");
for (int i = 0; i <= 23; i++) {
long time0 = System.nanoTime();
String s1 = bi.toString(16);
long time1 = System.nanoTime();
String s2 = bi.toHexString();
long time2 = System.nanoTime();
assert s1.equals(s2);
if (i >= 10) {
System.out.println("bitLength=" + bi.bitLength() + ";\t" +
(time1 - time0) / 1e9 + " sec\t" + (time2 - time1) / 1e9 + " sec");
}
n *= 2;
bi = bi.shiftLeft(n).add(bi);
}
}
}
====
On Sat, Jun 22, 2013 at 8:37 AM, Alan Eliasen <eliasen at mindspring.com>wrote:
> On 06/21/2013 10:23 PM, Dmitry Nadezhin wrote:
> > Brian,
> >
> > This patch significally enhances performance of string conversion for
> > large numbers.
> >
> > I suggest to create also a fast path for power-of-two radices: 2, 4, 8,
> 16,
> > 32 .
> > It is a simple linear algorithm that is suitable both for large and small
> > numbers.
> > Can it be attached to this bug activity ?
> > Or should it be filed as another bug ?
>
> I'd file it as another bug.
>
> As you'll see if you run profiling tests, and the power-of-two
> radices are already *much* faster than the other powers, as would be
> expected. It's possible to do the power-of-two conversions completely
> with bit operations in BigInteger and not relying on Long, but the
> improvement may be small as these cases are already relatively fast.
>
> --
> Alan Eliasen
> eliasen at mindspring.com
> http://futureboy.us/
>
More information about the core-libs-dev
mailing list