Работа HashSet Добавляет по сравнению с, Содержит для существующих элементов

InstrumentationRegistry.getInstrumentation().context является контекстом измерительного приложения. Из вашего утверждения вы хотите контекст целевого инструментария, который является val appContext = InstrumentationRegistry.getInstrumentation().targetContext

13
задан Carlos P 9 December 2013 в 13:41
поделиться

3 ответа

AddIfNotPresent делает дополнительное деление, которое Содержит, не работает. Смотрите на IL для, Содержит:

IL_000a:  call       instance int32 class System.Collections.Generic.HashSet`1<!T>::InternalGetHashCode(!0)
  IL_000f:  stloc.0
  IL_0010:  ldarg.0
  IL_0011:  ldfld      int32[] class System.Collections.Generic.HashSet`1<!T>::m_buckets
  IL_0016:  ldloc.0
  IL_0017:  ldarg.0
  IL_0018:  ldfld      int32[] class System.Collections.Generic.HashSet`1<!T>::m_buckets
  IL_001d:  ldlen
  IL_001e:  conv.i4
  IL_001f:  rem
  IL_0020:  ldelem.i4
  IL_0021:  ldc.i4.1
  IL_0022:  sub
  IL_0023:  stloc.1

Это вычисляет местоположение блока для хэш-кода. Результат сохраняется в местоположении локальной памяти 1.

AddIfNotPresent делает что-то подобное, но он также сохраняет вычисленное значение в местоположении 2, так, чтобы он мог вставить объект в хеш-таблицу в том положении, если объект не существует. Это делает то сохранение, потому что одно из местоположений изменяется позже в цикле, который идет, ища объект. Так или иначе вот соответствующие нормы для AddIfNotPresent:

IL_0011:  call       instance int32 class System.Collections.Generic.HashSet`1<!T>::InternalGetHashCode(!0)
  IL_0016:  stloc.0
  IL_0017:  ldloc.0
  IL_0018:  ldarg.0
  IL_0019:  ldfld      int32[] class System.Collections.Generic.HashSet`1<!T>::m_buckets
  IL_001e:  ldlen
  IL_001f:  conv.i4
  IL_0020:  rem
  IL_0021:  stloc.1
  IL_0022:  ldarg.0
  IL_0023:  ldfld      int32[] class System.Collections.Generic.HashSet`1<!T>::m_buckets
  IL_0028:  ldloc.0
  IL_0029:  ldarg.0
  IL_002a:  ldfld      int32[] class System.Collections.Generic.HashSet`1<!T>::m_buckets
  IL_002f:  ldlen
  IL_0030:  conv.i4
  IL_0031:  rem
  IL_0032:  ldelem.i4
  IL_0033:  ldc.i4.1
  IL_0034:  sub
  IL_0035:  stloc.2

Так или иначе я думаю, что дополнительное деление - то, что вызывает, Добавляют для взятия большего количества времени, чем Содержит. На первый взгляд похоже, что дополнительное деление могло быть факторизовано, но я не могу сказать наверняка, не проводя немного больше времени, дешифровав IL.

9
ответ дан 2 December 2019 в 01:11
поделиться

Интересный, на моей машине (Dell Latitude D630, двухъядерные 2,2 ГГц) я получаю почти идентичные результаты для обоих тестов, если я не выполняю секундомер против a null действие перед тестами. Например:

Я запускаю тесты с точным кодом, который Вы дали в вопросе:

Without Contains(): 8205794
With Contains():    8207596

Если я изменяю код этим способом:

После:

Stopwatch watch = new Stopwatch();
int size = 10000;
int iterations = 10000;

Добавьте:

watch.Time(null, 0);

Мои результаты становятся:

Without Contains(): 8019129
With Contains():    8275771

Это кажется мне как что-то нечетное, продолжается в Stopwatch это вызывает эти колебания.

1
ответ дан 2 December 2019 в 01:11
поделиться

Мое предположение - то, что Вы запустили свой тест из Visual Studio, которая вызвала встраивание AddIfNotPresent в Add быть подавленным, таким образом, Вы видите результат дополнительного уровня абстракции в вызовах метода.

Если я компилирую и работаю из командной строки для удаления какого-либо обмана VS...

> csc /o+ /t:exe Program.cs
> Program.exe

... затем нет никакого различия в производительности.

Демонстрационные выводы (представитель большего числа тестов):

35036174
35153818

35225763
34862330

35047377
35033323
1
ответ дан 2 December 2019 в 01:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: