[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
|