No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

HashSetPerformanceTests.cs 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. using NUnit.Framework;
  2. using UnityEngine;
  3. using Unity.Collections.LowLevel.Unsafe;
  4. using Unity.PerformanceTesting;
  5. using Unity.PerformanceTesting.Benchmark;
  6. using System.Runtime.CompilerServices;
  7. using System.Threading;
  8. using System.Collections.Generic;
  9. namespace Unity.Collections.PerformanceTests
  10. {
  11. static class HashSetUtil
  12. {
  13. static public void AllocInt(ref NativeHashSet<int> container, int capacity, bool addValues)
  14. {
  15. if (capacity >= 0)
  16. {
  17. Random.InitState(0);
  18. container = new NativeHashSet<int>(capacity, Allocator.Persistent);
  19. if (addValues)
  20. {
  21. for (int i = 0; i < capacity; i++)
  22. container.Add(i);
  23. }
  24. }
  25. else
  26. container.Dispose();
  27. }
  28. static public void AllocInt(ref NativeHashSet<int> containerA, ref NativeHashSet<int> containerB, int capacity, bool addValues)
  29. {
  30. AllocInt(ref containerA, capacity, false);
  31. AllocInt(ref containerB, capacity, false);
  32. if (!addValues)
  33. return;
  34. for (int i = 0; i < capacity; i++)
  35. {
  36. containerA.Add(Random.Range(0, capacity * 2));
  37. containerB.Add(Random.Range(0, capacity * 2));
  38. }
  39. }
  40. static public void AllocInt(ref UnsafeHashSet<int> container, int capacity, bool addValues)
  41. {
  42. if (capacity >= 0)
  43. {
  44. Random.InitState(0);
  45. container = new UnsafeHashSet<int>(capacity, Allocator.Persistent);
  46. if (addValues)
  47. {
  48. for (int i = 0; i < capacity; i++)
  49. container.Add(i);
  50. }
  51. }
  52. else
  53. container.Dispose();
  54. }
  55. static public void AllocInt(ref UnsafeHashSet<int> containerA, ref UnsafeHashSet<int> containerB, int capacity, bool addValues)
  56. {
  57. AllocInt(ref containerA, capacity, false);
  58. AllocInt(ref containerB, capacity, false);
  59. if (!addValues)
  60. return;
  61. for (int i = 0; i < capacity; i++)
  62. {
  63. containerA.Add(Random.Range(0, capacity * 2));
  64. containerB.Add(Random.Range(0, capacity * 2));
  65. }
  66. }
  67. static public object AllocBclContainer(int capacity, bool addValues)
  68. {
  69. if (capacity < 0)
  70. return null;
  71. Random.InitState(0);
  72. var bclContainer = new HashSet<int>(capacity);
  73. if (addValues)
  74. {
  75. for (int i = 0; i < capacity; i++)
  76. bclContainer.Add(i);
  77. }
  78. return bclContainer;
  79. }
  80. static public object AllocBclContainerTuple(int capacity, bool addValues)
  81. {
  82. var tuple = new System.Tuple<HashSet<int>, HashSet<int>>(
  83. (HashSet<int>)AllocBclContainer(capacity, false),
  84. (HashSet<int>)AllocBclContainer(capacity, false));
  85. if (addValues)
  86. {
  87. for (int i = 0; i < capacity; i++)
  88. {
  89. tuple.Item1.Add(Random.Range(0, capacity * 2));
  90. tuple.Item2.Add(Random.Range(0, capacity * 2));
  91. }
  92. }
  93. return tuple;
  94. }
  95. static public void CreateRandomKeys(int capacity, ref UnsafeList<int> keys)
  96. {
  97. if (capacity >= 0)
  98. {
  99. keys = new UnsafeList<int>(capacity, Allocator.Persistent);
  100. Random.InitState(0);
  101. for (int i = 0; i < capacity; i++)
  102. {
  103. int randKey = Random.Range(0, capacity);
  104. keys.Add(randKey);
  105. }
  106. }
  107. else
  108. keys.Dispose();
  109. }
  110. }
  111. struct HashSetIsEmpty100k : IBenchmarkContainer
  112. {
  113. const int kIterations = 100_000;
  114. NativeHashSet<int> nativeContainer;
  115. UnsafeHashSet<int> unsafeContainer;
  116. public void AllocNativeContainer(int capacity) => HashSetUtil.AllocInt(ref nativeContainer, capacity, true);
  117. public void AllocUnsafeContainer(int capacity) => HashSetUtil.AllocInt(ref unsafeContainer, capacity, true);
  118. public object AllocBclContainer(int capacity) => HashSetUtil.AllocBclContainer(capacity, true);
  119. [MethodImpl(MethodImplOptions.NoOptimization)]
  120. public void MeasureNativeContainer()
  121. {
  122. var reader = nativeContainer.AsReadOnly();
  123. for (int i = 0; i < kIterations; i++)
  124. _ = reader.IsEmpty;
  125. }
  126. [MethodImpl(MethodImplOptions.NoOptimization)]
  127. public void MeasureUnsafeContainer()
  128. {
  129. var reader = unsafeContainer.AsReadOnly();
  130. for (int i = 0; i < kIterations; i++)
  131. _ = reader.IsEmpty;
  132. }
  133. [MethodImpl(MethodImplOptions.NoOptimization)]
  134. public void MeasureBclContainer(object container)
  135. {
  136. var bclContainer = (HashSet<int>)container;
  137. for (int i = 0; i < kIterations; i++)
  138. _ = bclContainer.Count == 0;
  139. }
  140. }
  141. struct HashSetCount100k : IBenchmarkContainer
  142. {
  143. const int kIterations = 100_000;
  144. NativeHashSet<int> nativeContainer;
  145. UnsafeHashSet<int> unsafeContainer;
  146. public void AllocNativeContainer(int capacity) => HashSetUtil.AllocInt(ref nativeContainer, capacity, true);
  147. public void AllocUnsafeContainer(int capacity) => HashSetUtil.AllocInt(ref unsafeContainer, capacity, true);
  148. public object AllocBclContainer(int capacity) => HashSetUtil.AllocBclContainer(capacity, true);
  149. [MethodImpl(MethodImplOptions.NoOptimization)]
  150. public void MeasureNativeContainer()
  151. {
  152. var reader = nativeContainer.AsReadOnly();
  153. for (int i = 0; i < kIterations; i++)
  154. _ = reader.Count;
  155. }
  156. [MethodImpl(MethodImplOptions.NoOptimization)]
  157. public void MeasureUnsafeContainer()
  158. {
  159. var reader = unsafeContainer.AsReadOnly();
  160. for (int i = 0; i < kIterations; i++)
  161. _ = reader.Count;
  162. }
  163. [MethodImpl(MethodImplOptions.NoOptimization)]
  164. public void MeasureBclContainer(object container)
  165. {
  166. var bclContainer = (HashSet<int>)container;
  167. for (int i = 0; i < kIterations; i++)
  168. _ = bclContainer.Count;
  169. }
  170. }
  171. struct HashSetToNativeArray : IBenchmarkContainer
  172. {
  173. NativeHashSet<int> nativeContainer;
  174. UnsafeHashSet<int> unsafeContainer;
  175. public void AllocNativeContainer(int capacity) => HashSetUtil.AllocInt(ref nativeContainer, capacity, true);
  176. public void AllocUnsafeContainer(int capacity) => HashSetUtil.AllocInt(ref unsafeContainer, capacity, true);
  177. public object AllocBclContainer(int capacity) => HashSetUtil.AllocBclContainer(capacity, true);
  178. public void MeasureNativeContainer()
  179. {
  180. var asArray = nativeContainer.ToNativeArray(Allocator.Temp);
  181. asArray.Dispose();
  182. }
  183. public void MeasureUnsafeContainer()
  184. {
  185. var asArray = unsafeContainer.ToNativeArray(Allocator.Temp);
  186. asArray.Dispose();
  187. }
  188. public void MeasureBclContainer(object container)
  189. {
  190. var bclContainer = (HashSet<int>)container;
  191. int[] asArray = new int[bclContainer.Count];
  192. bclContainer.CopyTo(asArray, 0);
  193. }
  194. }
  195. struct HashSetInsert : IBenchmarkContainer
  196. {
  197. int capacity;
  198. NativeHashSet<int> nativeContainer;
  199. UnsafeHashSet<int> unsafeContainer;
  200. void IBenchmarkContainer.SetParams(int capacity, params int[] args) => this.capacity = capacity;
  201. public void AllocNativeContainer(int capacity) => HashSetUtil.AllocInt(ref nativeContainer, capacity, false);
  202. public void AllocUnsafeContainer(int capacity) => HashSetUtil.AllocInt(ref unsafeContainer, capacity, false);
  203. public object AllocBclContainer(int capacity) => HashSetUtil.AllocBclContainer(capacity, false);
  204. public void MeasureNativeContainer()
  205. {
  206. for (int i = 0; i < capacity; i++)
  207. nativeContainer.Add(i);
  208. }
  209. public void MeasureUnsafeContainer()
  210. {
  211. for (int i = 0; i < capacity; i++)
  212. unsafeContainer.Add(i);
  213. }
  214. public void MeasureBclContainer(object container)
  215. {
  216. var bclContainer = (HashSet<int>)container;
  217. for (int i = 0; i < capacity; i++)
  218. bclContainer.Add(i);
  219. }
  220. }
  221. struct HashSetAddGrow : IBenchmarkContainer
  222. {
  223. int capacity;
  224. int toAdd;
  225. NativeHashSet<int> nativeContainer;
  226. UnsafeHashSet<int> unsafeContainer;
  227. void IBenchmarkContainer.SetParams(int capacity, params int[] args)
  228. {
  229. this.capacity = capacity;
  230. toAdd = args[0];
  231. }
  232. public void AllocNativeContainer(int capacity) => HashSetUtil.AllocInt(ref nativeContainer, capacity, true);
  233. public void AllocUnsafeContainer(int capacity) => HashSetUtil.AllocInt(ref unsafeContainer, capacity, true);
  234. public object AllocBclContainer(int capacity) => HashSetUtil.AllocBclContainer(capacity, true);
  235. public void MeasureNativeContainer()
  236. {
  237. // Intentionally setting capacity small and growing by adding more items
  238. for (int i = capacity; i < capacity + toAdd; i++)
  239. nativeContainer.Add(i);
  240. }
  241. public void MeasureUnsafeContainer()
  242. {
  243. // Intentionally setting capacity small and growing by adding more items
  244. for (int i = capacity; i < capacity + toAdd; i++)
  245. unsafeContainer.Add(i);
  246. }
  247. public void MeasureBclContainer(object container)
  248. {
  249. var bclContainer = (HashSet<int>)container;
  250. // Intentionally setting capacity small and growing by adding more items
  251. for (int i = capacity; i < capacity + toAdd; i++)
  252. bclContainer.Add(i);
  253. }
  254. }
  255. struct HashSetContains : IBenchmarkContainer
  256. {
  257. int capacity;
  258. NativeHashSet<int> nativeContainer;
  259. UnsafeHashSet<int> unsafeContainer;
  260. UnsafeList<int> keys;
  261. void IBenchmarkContainer.SetParams(int capacity, params int[] args) => this.capacity = capacity;
  262. public void AllocNativeContainer(int capacity)
  263. {
  264. HashSetUtil.AllocInt(ref nativeContainer, capacity, false);
  265. HashSetUtil.CreateRandomKeys(capacity, ref keys);
  266. for (int i = 0; i < capacity; i++)
  267. nativeContainer.Add(keys[i]);
  268. }
  269. public void AllocUnsafeContainer(int capacity)
  270. {
  271. HashSetUtil.AllocInt(ref unsafeContainer, capacity, false);
  272. HashSetUtil.CreateRandomKeys(capacity, ref keys);
  273. for (int i = 0; i < capacity; i++)
  274. unsafeContainer.Add(keys[i]);
  275. }
  276. public object AllocBclContainer(int capacity)
  277. {
  278. object container = HashSetUtil.AllocBclContainer(capacity, false);
  279. var bclContainer = (HashSet<int>)container;
  280. HashSetUtil.CreateRandomKeys(capacity, ref keys);
  281. for (int i = 0; i < capacity; i++)
  282. bclContainer.Add(keys[i]);
  283. return container;
  284. }
  285. public void MeasureNativeContainer()
  286. {
  287. var reader = nativeContainer.AsReadOnly();
  288. bool data = false;
  289. for (int i = 0; i < capacity; i++)
  290. Volatile.Write(ref data, reader.Contains(keys[i]));
  291. }
  292. public void MeasureUnsafeContainer()
  293. {
  294. var reader = unsafeContainer.AsReadOnly();
  295. bool data = false;
  296. for (int i = 0; i < capacity; i++)
  297. Volatile.Write(ref data, reader.Contains(keys[i]));
  298. }
  299. public void MeasureBclContainer(object container)
  300. {
  301. var bclContainer = (HashSet<int>)container;
  302. bool data = false;
  303. for (int i = 0; i < capacity; i++)
  304. Volatile.Write(ref data, bclContainer.Contains(keys[i]));
  305. }
  306. }
  307. struct HashSetRemove : IBenchmarkContainer
  308. {
  309. NativeHashSet<int> nativeContainer;
  310. UnsafeHashSet<int> unsafeContainer;
  311. UnsafeList<int> keys;
  312. public void AllocNativeContainer(int capacity)
  313. {
  314. HashSetUtil.AllocInt(ref nativeContainer, capacity, false);
  315. HashSetUtil.CreateRandomKeys(capacity, ref keys);
  316. for (int i = 0; i < capacity; i++)
  317. nativeContainer.Add(keys[i]);
  318. }
  319. public void AllocUnsafeContainer(int capacity)
  320. {
  321. HashSetUtil.AllocInt(ref unsafeContainer, capacity, false);
  322. HashSetUtil.CreateRandomKeys(capacity, ref keys);
  323. for (int i = 0; i < capacity; i++)
  324. unsafeContainer.Add(keys[i]);
  325. }
  326. public object AllocBclContainer(int capacity)
  327. {
  328. object container = HashSetUtil.AllocBclContainer(capacity, false);
  329. var bclContainer = (HashSet<int>)container;
  330. HashSetUtil.CreateRandomKeys(capacity, ref keys);
  331. for (int i = 0; i < capacity; i++)
  332. bclContainer.Add(keys[i]);
  333. return container;
  334. }
  335. public void MeasureNativeContainer()
  336. {
  337. int insertions = keys.Length;
  338. for (int i = 0; i < insertions; i++)
  339. nativeContainer.Remove(keys[i]);
  340. }
  341. public void MeasureUnsafeContainer()
  342. {
  343. int insertions = keys.Length;
  344. for (int i = 0; i < insertions; i++)
  345. unsafeContainer.Remove(keys[i]);
  346. }
  347. public void MeasureBclContainer(object container)
  348. {
  349. var bclContainer = (HashSet<int>)container;
  350. int insertions = keys.Length;
  351. for (int i = 0; i < insertions; i++)
  352. bclContainer.Remove(keys[i]);
  353. }
  354. }
  355. struct HashSetForEach : IBenchmarkContainer
  356. {
  357. NativeHashSet<int> nativeContainer;
  358. UnsafeHashSet<int> unsafeContainer;
  359. public int total;
  360. public void AllocNativeContainer(int capacity) => HashSetUtil.AllocInt(ref nativeContainer, capacity, true);
  361. public void AllocUnsafeContainer(int capacity) => HashSetUtil.AllocInt(ref unsafeContainer, capacity, true);
  362. public object AllocBclContainer(int capacity) => HashSetUtil.AllocBclContainer(capacity, true);
  363. public void MeasureNativeContainer()
  364. {
  365. int keep = 0;
  366. foreach (var value in nativeContainer)
  367. Volatile.Write(ref keep, value);
  368. }
  369. public void MeasureUnsafeContainer()
  370. {
  371. int keep = 0;
  372. foreach (var value in unsafeContainer)
  373. Volatile.Write(ref keep, value);
  374. }
  375. public void MeasureBclContainer(object container)
  376. {
  377. int keep = 0;
  378. var bclContainer = (HashSet<int>)container;
  379. foreach (var value in bclContainer)
  380. Volatile.Write(ref keep, value);
  381. }
  382. }
  383. struct HashSetUnionWith : IBenchmarkContainer
  384. {
  385. NativeHashSet<int> nativeContainer;
  386. NativeHashSet<int> nativeContainerOther;
  387. UnsafeHashSet<int> unsafeContainer;
  388. UnsafeHashSet<int> unsafeContainerOther;
  389. public int total;
  390. public void AllocNativeContainer(int capacity) => HashSetUtil.AllocInt(ref nativeContainer, ref nativeContainerOther, capacity, true);
  391. public void AllocUnsafeContainer(int capacity) => HashSetUtil.AllocInt(ref unsafeContainer, ref unsafeContainerOther, capacity, true);
  392. public object AllocBclContainer(int capacity) => HashSetUtil.AllocBclContainerTuple(capacity, true);
  393. public void MeasureNativeContainer() => nativeContainer.UnionWith(nativeContainerOther);
  394. public void MeasureUnsafeContainer() => unsafeContainer.UnionWith(unsafeContainerOther);
  395. public void MeasureBclContainer(object container)
  396. {
  397. var dotnetContainer = (System.Tuple<HashSet<int>, HashSet<int>>)container;
  398. dotnetContainer.Item1.UnionWith(dotnetContainer.Item2);
  399. }
  400. }
  401. struct HashSetIntersectWith : IBenchmarkContainer
  402. {
  403. NativeHashSet<int> nativeContainer;
  404. NativeHashSet<int> nativeContainerOther;
  405. UnsafeHashSet<int> unsafeContainer;
  406. UnsafeHashSet<int> unsafeContainerOther;
  407. public int total;
  408. public void AllocNativeContainer(int capacity) => HashSetUtil.AllocInt(ref nativeContainer, ref nativeContainerOther, capacity, true);
  409. public void AllocUnsafeContainer(int capacity) => HashSetUtil.AllocInt(ref unsafeContainer, ref unsafeContainerOther, capacity, true);
  410. public object AllocBclContainer(int capacity) => HashSetUtil.AllocBclContainerTuple(capacity, true);
  411. public void MeasureNativeContainer() => nativeContainer.IntersectWith(nativeContainerOther);
  412. public void MeasureUnsafeContainer() => unsafeContainer.IntersectWith(unsafeContainerOther);
  413. public void MeasureBclContainer(object container)
  414. {
  415. var dotnetContainer = (System.Tuple<HashSet<int>, HashSet<int>>)container;
  416. dotnetContainer.Item1.IntersectWith(dotnetContainer.Item2);
  417. }
  418. }
  419. struct HashSetExceptWith : IBenchmarkContainer
  420. {
  421. NativeHashSet<int> nativeContainer;
  422. NativeHashSet<int> nativeContainerOther;
  423. UnsafeHashSet<int> unsafeContainer;
  424. UnsafeHashSet<int> unsafeContainerOther;
  425. public int total;
  426. public void AllocNativeContainer(int capacity) => HashSetUtil.AllocInt(ref nativeContainer, ref nativeContainerOther, capacity, true);
  427. public void AllocUnsafeContainer(int capacity) => HashSetUtil.AllocInt(ref unsafeContainer, ref unsafeContainerOther, capacity, true);
  428. public object AllocBclContainer(int capacity) => HashSetUtil.AllocBclContainerTuple(capacity, true);
  429. public void MeasureNativeContainer() => nativeContainer.ExceptWith(nativeContainerOther);
  430. public void MeasureUnsafeContainer() => unsafeContainer.ExceptWith(unsafeContainerOther);
  431. public void MeasureBclContainer(object container)
  432. {
  433. var dotnetContainer = (System.Tuple<HashSet<int>, HashSet<int>>)container;
  434. dotnetContainer.Item1.ExceptWith(dotnetContainer.Item2);
  435. }
  436. }
  437. [Benchmark(typeof(BenchmarkContainerType))]
  438. class HashSet
  439. {
  440. #if UNITY_EDITOR
  441. [UnityEditor.MenuItem(BenchmarkContainerConfig.kMenuItemIndividual + nameof(HashSet))]
  442. static void RunIndividual()
  443. => BenchmarkContainerConfig.RunBenchmark(typeof(HashSet));
  444. #endif
  445. [Test, Performance]
  446. [Category("Performance")]
  447. public unsafe void IsEmpty_x_100k(
  448. [Values(0, 100)] int capacity,
  449. [Values] BenchmarkContainerType type)
  450. {
  451. BenchmarkContainerRunner<HashSetIsEmpty100k>.Run(capacity, type);
  452. }
  453. [Test, Performance]
  454. [Category("Performance")]
  455. public unsafe void Count_x_100k(
  456. [Values(0, 100)] int capacity,
  457. [Values] BenchmarkContainerType type)
  458. {
  459. BenchmarkContainerRunner<HashSetCount100k>.Run(capacity, type);
  460. }
  461. [Test, Performance]
  462. [Category("Performance")]
  463. public unsafe void ToNativeArray(
  464. [Values(10000, 100000, 1000000)] int capacity,
  465. [Values] BenchmarkContainerType type)
  466. {
  467. BenchmarkContainerRunner<HashSetToNativeArray>.Run(capacity, type);
  468. }
  469. [Test, Performance]
  470. [Category("Performance")]
  471. public unsafe void Insert(
  472. [Values(10000, 100000, 1000000)] int insertions,
  473. [Values] BenchmarkContainerType type)
  474. {
  475. BenchmarkContainerRunner<HashSetInsert>.Run(insertions, type);
  476. }
  477. [Test, Performance]
  478. [Category("Performance")]
  479. [BenchmarkTestFootnote("Incrementally grows from `capacity` until reaching size of `growTo`")]
  480. public unsafe void AddGrow(
  481. [Values(4, 65536)] int capacity,
  482. [Values(1024 * 1024)] int growTo,
  483. [Values] BenchmarkContainerType type)
  484. {
  485. BenchmarkContainerRunner<HashSetAddGrow>.Run(capacity, type, growTo);
  486. }
  487. [Test, Performance]
  488. [Category("Performance")]
  489. public unsafe void Contains(
  490. [Values(10000, 100000, 1000000)] int insertions,
  491. [Values] BenchmarkContainerType type)
  492. {
  493. BenchmarkContainerRunner<HashSetContains>.Run(insertions, type);
  494. }
  495. [Test, Performance]
  496. [Category("Performance")]
  497. public unsafe void Remove(
  498. [Values(10000, 100000, 1000000)] int insertions,
  499. [Values] BenchmarkContainerType type)
  500. {
  501. BenchmarkContainerRunner<HashSetRemove>.Run(insertions, type);
  502. }
  503. [Test, Performance]
  504. [Category("Performance")]
  505. public unsafe void Foreach(
  506. [Values(10000, 100000, 1000000)] int insertions,
  507. [Values] BenchmarkContainerType type)
  508. {
  509. BenchmarkContainerRunner<HashSetForEach>.Run(insertions, type);
  510. }
  511. [Test, Performance]
  512. [Category("Performance")]
  513. public unsafe void UnionWith(
  514. [Values(10000, 100000, 1000000)] int insertions,
  515. [Values] BenchmarkContainerType type)
  516. {
  517. BenchmarkContainerRunner<HashSetUnionWith>.Run(insertions, type);
  518. }
  519. [Test, Performance]
  520. [Category("Performance")]
  521. public unsafe void IntersectWith(
  522. [Values(10000, 100000, 1000000)] int insertions,
  523. [Values] BenchmarkContainerType type)
  524. {
  525. BenchmarkContainerRunner<HashSetIntersectWith>.Run(insertions, type);
  526. }
  527. [Test, Performance]
  528. [Category("Performance")]
  529. public unsafe void ExceptWith(
  530. [Values(10000, 100000, 1000000)] int insertions,
  531. [Values] BenchmarkContainerType type)
  532. {
  533. BenchmarkContainerRunner<HashSetExceptWith>.Run(insertions, type);
  534. }
  535. }
  536. }