我正在處理一個List <>集合,在兩個嵌套循環內向集合添加新對象。在循環完成執行後,有約50萬個項目被添加到集合中。C#List <> Add()方法的性能
首先,adition操作運行良好,但不久之後可以注意到性能下降,對於最後幾千個元素來說,延遲時間是無法忍受的。
我嘗試了各種技巧(初始化一定大小的集合 - 500000),用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,
});
}
}
}
該方法的小描述: - 該方法讀取的對象(併發字典),並與更新的列表(在這種情況下,鏈表)預測對應某篇文章。
併發字典對象不斷從各個併發訪問它的線程更新。
該列表使用對應於所有文章的空預測進行初始化;因此,例如,如果您有700篇文章,那麼在開始時,列表中將填充700個空白預測。
由於其中一個計算線程更新了conformant字典,因此會引發一個調用上述方法的事件,該事件輪流更新列表(predicateList)。
可以在prediccionList(本例中)中保存的記錄的最大數量約爲500000條記錄,但是在列表中添加大約40000條記錄後,可能會發現性能損失。
該代碼可能看起來有點生疏,因爲我嘗試了各種優化技巧(用for替換foreach'es,計算循環外的count,用LinkedList替換列表<>等)。最後,我得出結論:減慢執行時間的部分是「prediccionList.Add(p);」行。
添加到列表中的對象是Prediccion類的實例;這個對象我認爲不是非常heacy,它只包含7個字段。
內存使用情況
我附加了內存分析的結果。使用的內存不超過256 MB,因此我不認爲這裏的內存應該是一個問題。
從哪裏得到500000個物品? –
你能提供一個能夠重現問題的代碼示例嗎? – alun
正在添加什麼類型的對象? – jalf