Низкая производительность на DataTable foreach DataColum в C# ASP.NET - PullRequest
0 голосов
/ 15 апреля 2020

Между одной версией нашего программного обеспечения и новой бета-версией существует значительная задержка в методе, который перебирает все DataColumns в DataTable (который также находится в пределах al oop по всем строкам).

Вот (упрощенный, но логически полный) код, который одинаков для обеих версий:

Stopwatch foretimer = Stopwatch.StartNew();
foreach (DataColumn dc in ds.Tables[0].Columns)
{
    Stopwatch foreinnertimer = Stopwatch.StartNew();
    RenderProfile.addProfile("Rows.StandardCellContents.foreEachColumn-Qty", 1);

    if (renderColumn(dc))
    {
        Stopwatch trtimer = Stopwatch.StartNew();
        temp = TokenReplacement.replaceNonCachedTokens(temp, rsa, dc, dr);
        RenderProfile.add("Rows.StandardCellContents.replaceCellTokens", trtimer.ElapsedMilliseconds);
        RenderProfile.add("Rows.StandardCellContents.replaceCellTokens-Qty", 1);

        RenderProfile.add("Rows.StandardCellContents.foreEachColumn-inner", foreinnertimer.ElapsedMilliseconds);
    }
    RenderProfile.add("Rows.StandardCellContents.foreEachColumn-inner-ALL", foreinnertimer.ElapsedMilliseconds);
}
RenderProfile.add("Rows.StandardCellContents.foreEachColumn", foretimer.ElapsedMilliseconds);

TokenReplacement.replaceNonCachedTokens есть некоторые изменения в базовом коде, но он не проявляется значительно разное время профиля)

Эти примеры относятся к одному и тому же входу , который имеет 1000 строк и 24 столбца, 19 из которых «визуализируются».

Это создает следующие значения профиля в старой версии:

 Rows-Qty:1000
 Rows.StandardCellContents.foreEachColumn-Qty:24000
 Rows.StandardCellContents.replaceCellTokens:14ms
 Rows.StandardCellContents.replaceCellTokens-Qty:19000
 Rows.StandardCellContents.foreEachColumn-inner:14ms
 Rows.StandardCellContents.foreEachColumn-inner-ALL:14ms
 Rows.StandardCellContents.foreEachColumn:2032ms

и эти значения профиля в новой версии:

 Rows-Qty:1000
 Rows.StandardCellContents.foreEachColumn-Qty:24000
 Rows.StandardCellContents.replaceCellTokens:59ms
 Rows.StandardCellContents.replaceCellTokens-Qty:19000
 Rows.StandardCellContents.foreEachColumn-inner:66ms
 Rows.StandardCellContents.foreEachColumn-inner-ALL:67ms
 Rows.StandardCellContents.foreEachColumn:9174ms

Как это может быть ?? Кажется прискорбным, что даже в старой (более быстрой) версии итерация только для DataColumns (Rows.StandardCellContents.foreEachColumn) составляет ~ 2 секунды, но для меня абсолютно странным является то, что новая версия последовательно + 7-8 секунд !!

Они оба работают на одной и той же версии. NET (4.0). В обновлениях, которые мы сделали, я не могу найти ничего, что изменило бы структуру DataTable ... Есть ли что-то связанное с DataSet / DataTable, которое могло бы замедлить for each l oop по всем столбцам ??

Любое руководство или совет относительно того, как проанализировать этот вопрос, высоко ценится.

1 Ответ

1 голос
/ 05 мая 2020

Ну, на самом деле это не отвечает на вопрос, но чтобы определить, действительно ли проблема в итерации, а не где-то еще, я бы прокомментировал весь код, кроме итерации:

Stopwatch foretimer = Stopwatch.StartNew();
foreach (DataColumn dc in ds.Tables[0].Columns)
{
    Stopwatch foreinnertimer = Stopwatch.StartNew();
    RenderProfile.addProfile("Rows.StandardCellContents.foreEachColumn-Qty", 1);

    //if (renderColumn(dc))
    {
        //Stopwatch trtimer = Stopwatch.StartNew();
        //temp = TokenReplacement.replaceNonCachedTokens(temp, rsa, dc, dr);
        //RenderProfile.add("Rows.StandardCellContents.replaceCellTokens", trtimer.ElapsedMilliseconds);
        //RenderProfile.add("Rows.StandardCellContents.replaceCellTokens-Qty", 1);

        RenderProfile.add("Rows.StandardCellContents.foreEachColumn-inner", foreinnertimer.ElapsedMilliseconds);
    }
    RenderProfile.add("Rows.StandardCellContents.foreEachColumn-inner-ALL", foreinnertimer.ElapsedMilliseconds);
}
RenderProfile.add("Rows.StandardCellContents.foreEachColumn", foretimer.ElapsedMilliseconds);

Это ограничит то, что рассчитывается, до foreach (и, возможно, незначительные накладные расходы операторов Stopwatch и RenderProfile).

Я предполагаю, что в renderColumn или TokenReplacement что-то изменилось между двумя версиями (не обязательно в вашем коде - может быть в коде фреймворка, хотя регрессия производительности такой величины была бы необычной).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...