컬렉션 2 개 중첩 루프 안의 컬렉션에 새 개체를 추가하여 List < 컬렉션으로 작업하고 있습니다. 루프가 끝나면 컬렉션에 500,000 개가 추가됩니다.C# List <> Add() 메서드 성능
처음에는 adition 작업이 잘 실행되지만 성능 저하가 눈에 띄기 시작하자마자 마지막 수천 개의 요소에 대해 지연 시간은 견딜 수 없습니다.
List <> 컬렉션을 사용하여 다양한 트릭 (특정 크기 - 500000의 컬렉션 초기화)을 시도했지만 너무 도움이되지 않았습니다.
문제를 해결하기위한 팁을 알려주시겠습니까? 더 최적화 된 구조로 구조를 변경하는 것이 흥미 롭습니다 - LinkedList <> 예를 들어 추가 등의 작업을 통해 List <>보다 성능이 좋습니다. 상기 방법은 객체 (동시 사전)을 판독하고,로 (이 경우 LinkedList의 단위)리스트를 갱신 - :리스트에게있어서의
private void UpdateForecastList(ConcurrentDictionary<Int32, RegistroSalidaProductoPrevision> prediccion, bool soloMejoresMetodos = true)
{
foreach (KeyValuePair<int, RegistroSalidaProductoPrevision> kvp in prediccion)
{
KeyValuePair<int, RegistroSalidaProductoPrevision> localKvp = kvp;
IList<Prediccion> pExistente = prediccionList.Where(p => p.Id == localKvp.Key).ToList();
Articulo articulo = (articuloList.Where(a => a.Id == localKvp.Key)).First();
if (pExistente.Count > 0)
{
foreach (var p in pExistente)
{
prediccionList.Remove(p);
}
}
if (kvp.Value.Previsiones.Count > 0)
{
var previsiones = kvp.Value.Previsiones.Where(prevision => prevision.Value.LPrevision[1] != null).ToList();
int previsionesCount = previsiones.Count;
for (int a = 0; a < previsionesCount; a++)
{
var registros = previsiones[a].Value.LPrevision[1].Serie;
int c = registros.Count;
if (soloMejoresMetodos)
{
if (localKvp.Value.MejorMetodo != previsiones[a].Key) continue;
for (int i = 0; i < c; i++)
{
var p = new Prediccion()
{
Id = articulo.Id,
Nombre = articulo.Codigo,
Descripcion = articulo.Descripcion,
NombreMetodo =
Utils.SplitStringByCapitals(previsiones[a].Value.NombreMetodo),
Fecha = registros[i].Fecha,
PrediccionArticulo = Math.Round(registros[i].Cantidad, 2),
EsMejorMetodo =
(previsiones[a].Value.NombreMetodo == localKvp.Value.MejorMetodo)
? true
: false
};
// This line experiences performance loss
prediccionList.Add(p);
}
}
else
{
for (int i = 0; i < c; i++)
{
prediccionList.Add(new Prediccion()
{
Id = articulo.Id,
Nombre = articulo.Codigo,
Descripcion = articulo.Descripcion,
NombreMetodo = previsiones[a].Value.NombreMetodo,
Fecha = registros[i].Fecha,
PrediccionArticulo =
Math.Round(registros[i].Cantidad, 2),
EsMejorMetodo =
(previsiones[a].Value.NombreMetodo ==
localKvp.Value.MejorMetodo)
? true
: false
});
}
}
}
}
else
{
prediccionList.Add(new Prediccion()
{
Id = articulo.Id,
Nombre = articulo.Codigo,
Descripcion = articulo.Descripcion,
NombreMetodo = kvp.Value.ErroresDatos[0].Texto,
});
}
}
}
작은 설명을 업데이트
방법 특정 기사에 해당하는 예측.
동시 사전 객체는 동시에 액세스하는 다양한 스레드에서 지속적으로 업데이트됩니다.
목록은 모든 아티클에 해당하는 null 예측으로 초기화됩니다. 예를 들어 700 개의 기사가있는 경우 처음에는 목록에 700 개의 빈 예측이 채워집니다.
계산 쓰레드 중 하나가 concurent 사전을 업데이트하면 위에서 언급 한 방법을 호출하는 이벤트가 발생하고 차례로 목록 (prediccionList)이 업데이트됩니다.
prediccionList (이 경우)에서 보유 할 수있는 레코드의 최대 수는 약 500000 레코드이지만 목록에서 약 40000 개의 레코드를 추가 한 후에 성능 저하가 감지 될 수 있습니다.
다양한 최적화 기법 (예 : foreach'es 바꾸기, 루프 외부 계산, 목록 <> 개체를 LinkedList <> 등으로 대체)을 시도해 보니 코드가 약간 녹슬어 보일 수 있습니다. 마지막으로 실행 시간을 늦추는 부분은 "prediccionList.Add (p);"라는 결론에 도달했습니다.
목록에 추가 된 개체는 Prediccion 클래스의 인스턴스입니다. 이 개체는 내가 heacy가 아니라고 생각합니다. 단지 7 개의 필드만을 포함하고 있습니다.
메모리 사용량
결과를 메모리 프로파일 링에서 첨부합니다. 사용 된 메모리는 256MB를 능가하지 않아 메모리가 문제가 될 것이라고 생각하지 않습니다.
어디에서 500000 개 항목을 가져 오나요? –
문제를 재현하는 코드 샘플을 제공 할 수 있습니까? – alun
어떤 유형의 개체를 추가합니까? – jalf