2012-02-10 2 views
1

Я имею следующий код:Медленная работа LINQ

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; 
     } 

Эта функция задается с помощью почтовый индекс, радиус, и она найдет все Почтовые индексы в пределах радиуса. У меня есть проблемы с производительностью, здесь и после запуска dotTrace большую часть своего времени в следующем:

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); 

И третья часть времени, он получает доступ к

public System.Nullable<decimal> Longitude 
     { 
      get 
      { 
       return this._Longitude; 
      } 
      set 
      { 
       if ((this._Longitude != value)) 
       { 
        this._Longitude = value; 
       } 
      } 
     } 

Как я могу улучшить производительность? ?? Мы говорим здесь несколько секунд ... Не понимаю, почему. все это кэшировано и не-SQL.

+0

Сколько записей является его соответствие против? –

+0

Моя первая мысль заключалась в том, что метод CalcDistance является узким местом, поскольку он называется для каждого элемента. Попробуйте создать реальный метод для замены выражения лямбда, и тогда будет проще поместить некоторые таймеры вокруг него и дополнительно изолировать проблему. Я не вижу ничего, кроме этого метода, который мог бы это сделать. Возможно, вы можете разместить содержимое CalcDistance? –

+0

Если вы используете возвращаемое значение 'GetCloseZipCodes' много раз, вы можете попытаться преобразовать его' ToList' или 'ToArray', чтобы устранить несколько вычислений. –

ответ

3

С одной стороны, вы делаете много переходов между double и decimal, насколько я могу видеть.

Я хотел бы предложить либо изменив представление объекта использовать double, чтобы начать с, или конвертировать longt и latit в decimal, так что вы можете выполнять все сравнения в одном типе, без всяких преобразований.

Помимо всего прочего, сохранение одного согласованного представления оставит ваш код чистым, а также, вероятно, лучшим. В этом случае я бы сказал, что double, вероятно, более подходящее представление, чем decimal в любом случае - это не так, как это точный десятичные значения, такие как валюта; они являются естественными значениями, которые уже были аппроксимированы измерением.

Кроме того, вы выполняете преобразование с нулевым значением в не-nullable несколько раз, как для x.Value, так и для для сравнения. Рассмотрите возможность использования заявление лямбда вместо:

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; 
} 

Ради удобства чтения, я бы, вероятно, поместить это в отдельный метод, чтобы быть честным.

(Вы даже нужны свойства быть обнуляемым, кстати? Это не имеет большого смысла для меня.)

+0

Нужно ли мне повышать? : P haha ​​btw этот ответ настолько велик .... – rofans91

Смежные вопросы