我想在重载操作期间保持列表顺序的一些输入,我决定以并行方式尝试以确定它是否会提升性能。 (确实如此!)
我提出了一个解决方案,但由于这是我第一次尝试任何平行的事情,如果我做了一些非常愚蠢的事情,我需要有人拍我的手。
有一个查询返回一个卡片所有者列表,按名称排序,然后按出生日期排序。这需要在网页上的表格中呈现(ASP.Net WebForms)。原始编码器决定他将逐个单元格构建表格(TableCell
),将它们添加到行(TableRow
),然后将每行添加到表格中。所以没有GridView,据说其性能不好,但无论如何表现都很差。)。
数据库查询很快就会返回,大部分时间用于循环结果并添加表格单元格等。
我制作了以下方法来维护列表的原始顺序:
private TableRow[] ComposeRows(List<CardHolder> queryResult)
{
int queryElementsCount = queryResult.Count();
// array with the query's size
var rowArray = new TableRow[queryElementsCount];
Parallel.For(0, queryElementsCount, i =>
{
var row = new TableRow();
var cell = new TableCell();
// various operations, including simple ones such as:
cell.Text = queryResult[i].Name;
row.Cells.Add(cell);
// here I'm adding the current item to it's original index
// to maintain order in the output list
rowArray[i] = row;
});
return rowArray;
}
正如您所看到的,因为我正在返回一种非常不同类型的数据(List<CardHolder> -> TableRow[]
),所以我不能简单地省略原始查询的排序,以便在操作之后执行此操作。
另外,我还认为 Dispose()
每个循环结束时的对象是个好主意,因为查询可以返回一个巨大的列表,并让单元格和行对象堆积在堆可能会影响性能。(?)
我做得多么糟糕?如果我的有缺陷,有没有人有更好的解决方案?
经过测试,使用| 2000 |数组,StopWatch
表示并行合成在63毫秒(165082刻度)完成,串行合成在267毫秒(698222)完成。两者都包括添加行 - (table.Rows.AddRange()
),然后呈现Table
。无需添加和渲染,并行时间为33ms / 87541t,串行时间为178ms / 467068t。
答案 0 :(得分:1)
一点代码审查:
Dispose()
的2次调用。充其量它们是无害的。 originalIndex
。它应该总是等于i
,所以你不需要它。 但除了这一点精简之外,没有太多改进。令人怀疑的是,并行执行此操作会有很大帮助,或者这是您代码中的真正瓶颈。我怀疑大部分时间都花在处理TableRow[]
的结果上。