Linq on generic List需要花费很多时间

时间:2014-12-11 10:30:32

标签: vb.net performance linq list

我有一个数据库表,每秒从6个不同的测量站(即42个值)获得7个不同的值。数据不存储时间戳,只存储“TickNumber”,然后根据TickNumber和测量开始时间计算时间。

我无法控制这一点。

然而,为了加快速度,我下载数据,分析数据并将其存储在另一个带有asp.net前端的数据库中。这个系统运作良好,每个人都很开心。

然而,分析部分正在进行中,在使用性能分析器一段时间后,我发现了问题。

这将获取数据并返回List。

Public Shared Function GetMeasuredValues(ByVal _startdate As Date, ByVal _enddate As Date) As List(Of MeasuredValues)
    Dim _db As New Quickview

    Dim functions() As Integer = System.Enum.GetValues(GetType(Enums.MeasuredValueTypes))
    Dim total_values As New List(Of MeasuredValues)

    'Finding max and min row values
    Dim stations() As Integer = {1, 2, 3, 4, 6, 16}
    For Each i In stations
        Dim station As Integer = i
        Dim local_start As Integer = DB.DateToPeriodNo(station, _startdate)
        Dim local_end As Integer = DB.DateToPeriodNo(station, _enddate)

        If local_start > 0 Then
            Dim all_values = (From vls In _db.MeasuredValues
                              Where vls.MeasValueId = station _
                              And functions.Contains(vls.FuncId) _
                              And vls.PeriodNo >= local_start And vls.PeriodNo <= local_end _
                              ).ToList
            Console.WriteLine("Data count for station " & i & ": " & all_values.Count)
            total_values.AddRange(all_values)
        End If
    Next

    Dim sorted_values = (From vls In total_values
                         Order By vls.Time Ascending, vls.MeasValueId Ascending).ToList

    Return sorted_values
End Function

这很好用。存在大量数据,并且在此步骤中传输数据占用了大部分消耗的时间。

然后过滤此数据以给出一小时(07:00到07:59等)的值。我使用这些值来计算该小时所需的平均值和总和。可悲的是,这很多是对数所以我不能使用。总和等。

然后我这样做:

Dim all_values = DB.GetMeasuredValues(date_start, date_end)

....它只是给我一个我需要的所有值的列表。

这是问题,这个查询似乎需要永远。

''' [in for-loop going through each hour between date_start and date_end, typically 24 hours]
Dim values_hour = (From vls In all_values
                   Where vls.MeasValueId = station _
                   And vls.FuncId = Func _
                   And vls.Time >= time_start And vls.Time < time_end).ToList

如果我信任性能分析器,这个简单的查询占用了97%的资源。我的计算似乎没有任何影响(<0.2%)。

我确定我做错了什么,但是什么?

2 个答案:

答案 0 :(得分:2)

ToList的调用会导致很多开销,因为它需要每次为列表分配内存,然后填写该列表。
你试过删除吗?
最重要的是,我会使用total_values.Concat(all_values)代替total_values.AddRange(all_values),然后就像你已经做的那样在最后调用ToList

如果处于调试模式或类似的情况下,我只会写入数据计数,这样,当性能很重要时,你就不会在那里浪费时间。

答案 1 :(得分:2)

由于您按时间排序数据,因此您可以使用SkipWhile/TakeWhile从中获取时间块,然后应用其他过滤器。因此,您只需枚举批量数据一次即可获得所需的时间,并仅将过滤器应用于此数据子集:

Dim slice = all_values _
            .SkipWhile(Function(vls) vls.Time < time_start) _
            .TakeWhile(Function(vls) vls.Time < time_end)

然后按Funcstation进行过滤。