Reputation: 5792
I am having the following code:
public static IEnumerable<int> GetCloseZipCodes(int zipcode, int radius)
{
PycDBDataContext db = new PycDBDataContext();
ZipCode reqZipInfo = ZipCodes.Instance.zipcodes[zipcode];
if (reqZipInfo == null)
return new int[] { };
double longt = LongitudePlusDistance((double)reqZipInfo.Longitude, (double)reqZipInfo.Latitude, radius);
double latit = LatitudePlusDistance((double)reqZipInfo.Latitude, radius);
double minLong = 2 * (double)reqZipInfo.Longitude - longt;
double minLat = 2 * (double)reqZipInfo.Latitude - latit;
var zips = ZipCodes.Instance.zipcodes.Where(x => (double)x.Value.Longitude >= minLong &&
(double)x.Value.Longitude <= longt &&
(double)x.Value.Latitude >= minLat &&
(double)x.Value.Latitude <= latit &&
CalcDistance((double)reqZipInfo.Longitude,
(double)reqZipInfo.Latitude,
(double)x.Value.Longitude,
(double)x.Value.Latitude) <= radius).Select(x => x.Key);
return zips;
}
This function is given with a zipcode, a radius and it will find all the zipcodes within the radius. I have performance issues here and after running dotTrace most of my time is in the following:
var zips = ZipCodes.Instance.zipcodes.Where(x => (double)x.Value.Longitude >= minLong &&
(double)x.Value.Longitude <= longt &&
(double)x.Value.Latitude >= minLat &&
(double)x.Value.Latitude <= latit &&
CalcDistance((double)reqZipInfo.Longitude,
(double)reqZipInfo.Latitude,
(double)x.Value.Longitude,
(double)x.Value.Latitude) <= radius).Select(x => x.Key);
And third of the time there, it is accessing
public System.Nullable<decimal> Longitude
{
get
{
return this._Longitude;
}
set
{
if ((this._Longitude != value))
{
this._Longitude = value;
}
}
}
How can I improve the performance??? We are talking about a few seconds here... I can't understand why. this is all cached and non-SQL.
Upvotes: 1
Views: 142
Reputation: 1499860
For one thing, you're doing a lot of conversions between double
and decimal
as far as I can see.
I'd suggest either changing your object representation to use double
to start with, or convert longt
and latit
to decimal
so that you can perform all the comparisons in a single type, without all the conversions.
Aside from anything else, keeping one consistent representation will leave your code cleaner as well as probably performing better. In this case, I'd say that double
is probably a more appropriate representation than decimal
anyway - it's not like these are exact decimal values like currency; they're naturally-occurring values which have already been approximated by measurement.
Additionally, you're doing the nullable to non-nullable conversion several times, both for x.Value
and for comparisons. Consider using a statement lambda instead:
x => {
if (x.Longitude == null || x.Latitude == null)
{
return false;
}
double longitude = x.Value.Longitude.Value;
double latitude = x.Value.Latitude.Value;
return longitude >= minLong &&
longitude <= longt &&
latitude >= minLat &&
latitude <= latit &&
longitude >= minLong &&
CalcDistance(reqZipInfo.Longitude, reqZipInfo.Latitude,
longitude, latitude) <= radius;
}
For the sake of readability, I'd probably put this in a separate method to be honest.
(Do you even need the properties to be nullable, by the way? It doesn't make much sense to me.)
Upvotes: 3