Удивительные различия в производительности: List.Constains, SortedList.ContainsKey, DataRowCollection.Contains, DataTable.Select, DataTable.FindBy

Первоначально я хотел попросить самый быстрый способ запросить Datatable для специальной строки.

Я проверил 5 различных методов их работы с удивительным (для меня) результатом.

Предыстория: я создал представление в базе данных MS Sql-Server 2005. Это представление имеет общее количество строк 6318. Поскольку я должен очень часто проверять, существует ли данный идентификатор в этом представлении, я задавался вопросом, что является наиболее эффективным способом сделать. Я создал DataAdapter в строго типизированном наборе данных, который возвращает все строки и заполняет Datatable. Мой первый подход состоял в том, чтобы создать общий общий список (из Int32) и заполнить его идентификаторами из представления один раз при запуске приложения. Тогда используйтеList.Contains проверить, есть ли текущий идентификатор в этом списке. Поскольку все строки различны, я задавался вопросом, не быстрее ли использовать SortedList и егоContainsKey-metod. Затем я проверил также производительность прямого доступа к Datable с егоSelect-метод, его автоматически генерируется (когда столбец определен как первичный ключ)FindBy-метод и последнее, но не менее важноеDatarowCollection.Contains-Метод. Так что у меня есть 5 методов, чтобы проверить, находится ли мой идентификатор в этом представлении (или отображается список / SortedList).

Я измерил их производительность сSystem.Diagnostics.StopWatch и получил несколько интересных результатов. Я думал, что SortedList.ContainsKey должен быть быстрее, чем List.Contains, потому что они различны и отсортированы, но верно обратное. Но самым удивительным для меня было то, что DataRowCollection.Contains-Method (о котором я впервые забыл), безусловно, самый быстрый. Это даже в 50 раз быстрее, чем метод dataTable.FindBy.

Чем вызваны эти различия?Я забыл лучший способ?Является ли мой метод измерения правильным (я думаю, что лучше зациклить их и принять эти значения)?Являются ли значения переносимыми или зависят от размера таблицы данных / коллекции?После моего обновления (1000000 итераций) ContainsKey является самым быстрым. Это потому, что я всегда проверяю один и тот же идентификатор или вообще? Есть ли какой-то SortedList без издержек KeyValue-Pair словаря?

Результаты [за 1000000 итераций *]

Timespan 1 =SortedList.ContainsKey = Ø 0,65634 [238.1095] МизTimespan 2 =List.Contains = Ø 0,06802 [57045,37955] МизTimespan 3 =DataTable.FindByIdData(автоматически сгенерированный метод) = Ø 0,31580 [1542,62345] МизTimespan 4 =DataTable.Select = Ø 0,27790 [26029,39635] Миз

Timespan 5 =DataRowCollection.Contains = Ø 0,00638 [1202,79735] Миз

1.)
Timespan 1: 0,6913 ms
Timespan 2: 0,1053 ms
Timespan 3: 0,3279 ms
Timespan 4: 0,1002 ms
Timespan 5: 0,0056 ms

2.)
Timespan 1: 0,6405 ms
Timespan 2: 0,0588 ms
Timespan 3: 0,3112 ms
Timespan 4: 0,3872 ms
Timespan 5: 0,0067 ms

3.)
Timespan 1: 0,6502 ms
Timespan 2: 0,0588 ms
Timespan 3: 0,3092 ms
Timespan 4: 0,1268 ms
Timespan 5: 0,007 ms

4.)
Timespan 1: 0,6504 ms
Timespan 2: 0,0586 ms
Timespan 3: 0,3092 ms
Timespan 4: 0,3893 ms
Timespan 5: 0,0063 ms

5.)
Timespan 1: 0,6493 ms
Timespan 2: 0,0586 ms
Timespan 3: 0,3215 ms
Timespan 4: 0,386 ms
Timespan 5: 0,0063 ms



Timespan 1: 0,6913 0,6405 0,6502 0,6504 0,6493 = Ø 0,65634
Timespan 2: 0,1053 0,0588 0,0588 0,0586 0,0586 = Ø 0,06802
Timespan 3: 0,3279 0,3112 0,3092 0,3092 0,3215 = Ø 0,31580
Timespan 4: 0,1002 0,3872 0,1268 0,3893 0,3860 = Ø 0,27790
Timespan 5: 0,0056 0,0067 0,0070 0,0063 0,0063 = Ø 0,00638

И для полноты картины частьVB.Net источник:

Dim applies As Boolean
Dim clock As New System.Diagnostics.Stopwatch

clock.Start()
For i As Int32 = 1 To 1000000
    applies = sortedListAC17NextClaims.ContainsKey(myClaim.idData)
Next
clock.Stop()
Dim timeSpan1 As String = "Timespan 1: " & clock.Elapsed.TotalMilliseconds.ToString & " ms"

clock.Reset()
clock.Start()
For i As Int32 = 1 To 1000000
    applies = listAC17NextClaims.Contains(myClaim.idData)
Next
clock.Stop()
Dim timeSpan2 As String = "Timespan 2: " & clock.Elapsed.TotalMilliseconds.ToString & " ms"

clock.Reset()
clock.Start()
For i As Int32 = 1 To 1000000
    applies = Not MyDS.AC17NextClaims.FindByIdData(myClaim.idData) Is Nothing
Next
clock.Stop()
Dim timeSpan3 As String = "Timespan 3: " & clock.Elapsed.TotalMilliseconds.ToString & " ms"

clock.Reset()
clock.Start()
For i As Int32 = 1 To 1000000
    applies = MyDS.AC17NextClaims.Select("idData=" & myClaim.idData).Length > 0
Next
clock.Stop()
Dim timeSpan4 As String = "Timespan 4: " & clock.Elapsed.TotalMilliseconds.ToString & " ms"

clock.Reset()
clock.Start()
For i As Int32 = 1 To 1000000
    applies = MyDS.AC17NextClaims.Rows.Contains(myClaim.idData)
Next
clock.Stop()
Dim timeSpan5 As String = "Timespan 5: " & clock.Elapsed.TotalMilliseconds.ToString & " ms"

ОБНОВИТЬ: Я изменил свои результаты и источник выше. В квадратных скобках указаны значения для 1000000 итераций. Теперь результат совершенно другой. Самый быстрый метод сейчас определенно - это ContainsKey из SortedList.

ОБНОВЛЕНИЕ 2: Я забыл альтернативу использоватьList.BinarySearch, Это кажется самым быстрым для меня:

clock.Start()
For i As Int32 = 1 To 1000000
    applies = listAC17NextClaims.BinarySearch(myClaim.idData) > -1
Next
clock.Stop()

для выполнения 1000000 итераций требуется всего 219,1805 мс, и, следовательно, он является самым быстрым без издержек SortedList-KeyValue-Pair. Я могу использовать его без сортировки списка, потому что DataAdapter заполнил элемент данных предложением Order By.

Ответы на вопрос(3)

Ваш ответ на вопрос