[Geographiclib-users] Excessive object allocation in Geodesic
Geographic library
Brought to you by:
karney
From: Andrea A. <and...@gm...> - 2020-08-24 15:40:48
|
Hi, I am investigating the slowness of a software using Geodesic lib to perform calculations. The code is calling Geodesic.inverse, which leads to the following report by Java Mission Control: ------------------------ The most allocated type is likely 'double[]', most commonly allocated by: Geodesic.C1f(double, double[]) (34,8 %) Frequently allocated types are good places to start when trying to reduce garbage collections. Look at where the most common types are being allocated to see if many instances are created along the same call path. Try to reduce the number of instances created by invoking the most commonly taken paths less. ------------------------ The stack trace looks like the following: void net.sf.geographiclib.Geodesic.C1f(double, double[]) 16856 Geodesic$LengthsV net.sf.geographiclib.Geodesic.Lengths(double, double, double, double, double, double, double, double, double, double, int, double[], double[]) 16852 Geodesic$Lambda12V net.sf.geographiclib.Geodesic.Lambda12(double, double, double, double, double, double, double, double, double, double, boolean, double[], double[], double[]) 13132 Geodesic$InverseData net.sf.geographiclib.Geodesic.InverseInt(double, double, double, double, int) 13132 GeodesicData net.sf.geographiclib.Geodesic.Inverse(double, double, double, double, int) 13132 GeodesicData net.sf.geographiclib.Geodesic.Inverse(double, double, double, double) 13132 Let's have a look at the source code of Geodesic.C1f: // The coefficients C1[l] in the Fourier expansion of B1 protected static void C1f(double eps, double c[]) { final double coeff[] = { // C1[1]/eps^1, polynomial in eps2 of order 2 -1, 6, -16, 32, // C1[2]/eps^2, polynomial in eps2 of order 2 -9, 64, -128, 2048, // C1[3]/eps^3, polynomial in eps2 of order 1 9, -16, 768, // C1[4]/eps^4, polynomial in eps2 of order 1 3, -5, 512, // C1[5]/eps^5, polynomial in eps2 of order 0 -7, 1280, // C1[6]/eps^6, polynomial in eps2 of order 0 -7, 2048, }; double eps2 = GeoMath.sq(eps), d = eps; int o = 0; for (int l = 1; l <= nC1_; ++l) { // l is index of C1p[l] int m = (nC1_ - l) / 2; // order of polynomial in eps^2 c[l] = d * GeoMath.polyval(m, coeff, o, eps2) / coeff[o + m + 1]; o += m + 2; d *= eps; } } Now... the only allocation I see is the coeff array... maybe the original author thought, since it was a final, that it would be allocated just once? Instead it seems it's allocated for every call (and it's really mutable, only the object reference itself is final, arrays in java cannot be made constant, as far as I know). My guess is that moving these coefficients (and many others used in the other methods) out in a "static final" field may solve the issue. Does that make sense? Btw, I looked for a bug tracker, but could not find one, so I've reported the issue here. Cheers Andrea |