| When_xml_doc_is_missing_then_description_is_empty |
100000 |
120,859.507 μs |
12,137.4212 μs |
665.2930 μs |
14200.0000 |
- |
116406.25 KB |
| When_xml_doc_is_missing_then_description_is_empty_old |
100000 |
2,725,580.867 μs |
281,667.2610 μs |
15,439.1331 μs |
57000.0000 |
- |
472656.25 KB |
| When_xml_doc_with_multiple_breaks_is_read_then_they_are_not_stripped_away |
100000 |
172,524.667 μs |
18,470.1591 μs |
1,012.4117 μs |
58500.0000 |
- |
480469.29 KB |
| When_xml_doc_with_multiple_breaks_is_read_then_they_are_not_stripped_away_old |
100000 |
601,319.133 μs |
290,051.4265 μs |
15,898.6975 μs |
173000.0000 |
1000.0000 |
1420313.57 KB |
| When_description_has_see_tag_then_it_is_converted |
100000 |
187,286.600 μs |
94,192.6960 μs |
5,163.0195 μs |
36000.0000 |
- |
296096.94 KB |
| When_description_has_see_tag_then_it_is_converted_old |
100000 |
681,088.633 μs |
317,488.1082 μs |
17,402.5946 μs |
153000.0000 |
1000.0000 |
1254688.56 KB |
| When_description_has_paramref_tag_then_it_is_converted |
100000 |
144,636.917 μs |
34,561.3856 μs |
1,894.4262 μs |
29000.0000 |
- |
239069.42 KB |
| When_description_has_paramref_tag_then_it_is_converted_old |
100000 |
617,923.267 μs |
48,661.9208 μs |
2,667.3241 μs |
145000.0000 |
1000.0000 |
1184420.41 KB |
| When_description_has_generic_tags_then_it_is_converted |
100000 |
121,884.083 μs |
19,649.2068 μs |
1,077.0393 μs |
20000.0000 |
- |
164844.29 KB |
| When_description_has_generic_tags_then_it_is_converted_old |
100000 |
567,797.267 μs |
219,565.4140 μs |
12,035.1213 μs |
126000.0000 |
1000.0000 |
1032032.33 KB |
| When_type_has_description_then_it_it_resolved |
100000 |
129,652.500 μs |
56,766.0772 μs |
3,111.5403 μs |
27000.0000 |
- |
221882.3 KB |
| When_type_has_description_then_it_it_resolved_old |
100000 |
279,065.700 μs |
137,640.5074 μs |
7,544.5407 μs |
86000.0000 |
- |
707054.36 KB |
| When_we_use_custom_documentation_files_they_are_correctly_loaded |
100000 |
128,535.333 μs |
18,932.1295 μs |
1,037.7339 μs |
27000.0000 |
- |
221882.3 KB |
| When_we_use_custom_documentation_files_they_are_correctly_loaded_old |
100000 |
278,688.933 μs |
190,098.9362 μs |
10,419.9642 μs |
86000.0000 |
- |
707054.36 KB |
| When_parameter_has_inheritdoc_then_it_is_resolved |
100000 |
388,008.333 μs |
121,439.9351 μs |
6,656.5327 μs |
69000.0000 |
- |
570331.98 KB |
| When_parameter_has_inheritdoc_then_it_is_resolved_old |
100000 |
617,516.067 μs |
189,819.8929 μs |
10,404.6689 μs |
190000.0000 |
2000.0000 |
1553967.3 KB |
| When_method_has_inheritdoc_then_it_is_resolved |
100000 |
388,327.700 μs |
135,499.2838 μs |
7,427.1730 μs |
68000.0000 |
- |
558612.99 KB |
| When_method_has_inheritdoc_then_it_is_resolved_old |
100000 |
383,935.267 μs |
188,689.0892 μs |
10,342.6857 μs |
98000.0000 |
- |
807847.27 KB |
| When_property_has_inheritdoc_then_it_is_resolved |
100000 |
356,269.400 μs |
102,935.1776 μs |
5,642.2244 μs |
62000.0000 |
- |
509393.12 KB |
| When_property_has_inheritdoc_then_it_is_resolved_old |
100000 |
337,054.233 μs |
63,085.0747 μs |
3,457.9058 μs |
91000.0000 |
- |
745313.59 KB |
| When_type_is_an_interface_then_description_is_resolved |
100000 |
128,561.883 μs |
16,491.3307 μs |
903.9455 μs |
26500.0000 |
- |
217194.88 KB |
| When_type_is_an_interface_then_description_is_resolved_old |
100000 |
427,854.733 μs |
201,584.9437 μs |
11,049.5510 μs |
108000.0000 |
- |
887529.8 KB |
| When_parameter_has_inheritdoc_on_interface_then_it_is_resolved |
100000 |
282,278.533 μs |
117,860.3894 μs |
6,460.3257 μs |
47000.0000 |
- |
387682.23 KB |
| When_parameter_has_inheritdoc_on_interface_then_it_is_resolved_old |
100000 |
638,184.767 μs |
264,927.5888 μs |
14,521.5752 μs |
196000.0000 |
2000.0000 |
1607092.24 KB |
| When_property_has_inheritdoc_on_interface_then_it_is_resolved |
100000 |
258,612.633 μs |
14,135.8916 μs |
774.8359 μs |
42000.0000 |
- |
347811.74 KB |
| When_property_has_inheritdoc_on_interface_then_it_is_resolved_old |
100000 |
351,675.700 μs |
132,374.2876 μs |
7,255.8814 μs |
95000.0000 |
- |
782032.15 KB |
| When_method_has_inheritdoc_then_on_interface_it_is_resolved |
100000 |
282,699.200 μs |
29,497.1756 μs |
1,616.8397 μs |
46000.0000 |
- |
376734.66 KB |
| When_method_has_inheritdoc_then_on_interface_it_is_resolved_old |
100000 |
385,172.367 μs |
155,013.5693 μs |
8,496.8168 μs |
102000.0000 |
1000.0000 |
835188.57 KB |
| When_class_implements_interface_and_property_has_description_then_property_description_is_used |
100000 |
132,875.200 μs |
3,960.2381 μs |
217.0740 μs |
27000.0000 |
- |
223439.33 KB |
| When_class_implements_interface_and_property_has_description_then_property_description_is_used_old |
100000 |
376,766.867 μs |
148,048.4219 μs |
8,115.0336 μs |
104000.0000 |
- |
850782.16 KB |
| When_class_implements_interface_and_method_has_description_then_method_description_is_used |
100000 |
142,962.417 μs |
8,209.5160 μs |
449.9913 μs |
28000.0000 |
- |
228912.52 KB |
| When_class_implements_interface_and_method_has_description_then_method_description_is_used_old |
100000 |
424,184.900 μs |
69,537.9853 μs |
3,811.6116 μs |
111000.0000 |
- |
908628.83 KB |
| When_class_implements_interface_and_method_has_description_then_method_parameter_description_is_used |
100000 |
115,625.983 μs |
2,306.2521 μs |
126.4135 μs |
22000.0000 |
- |
179692.56 KB |
| When_class_implements_interface_and_method_has_description_then_method_parameter_description_is_used_old |
100000 |
687,318.967 μs |
254,192.5425 μs |
13,933.1510 μs |
204000.0000 |
2000.0000 |
1668032.2 KB |
| When_class_has_description_then_it_is_converted |
100000 |
131,622.650 μs |
72,629.1065 μs |
3,981.0464 μs |
29000.0000 |
- |
240633.07 KB |
| When_class_has_description_then_it_is_converted_old |
100000 |
395,235.800 μs |
167,555.4996 μs |
9,184.2824 μs |
107000.0000 |
- |
878154.53 KB |
| When_method_has_exceptions_then_it_is_converted |
100000 |
190,465.100 μs |
37,521.0015 μs |
2,056.6527 μs |
55000.0000 |
- |
453126.59 KB |
| When_method_has_exceptions_then_it_is_converted_old |
100000 |
603,740.767 μs |
255,448.2207 μs |
14,001.9790 μs |
169000.0000 |
1000.0000 |
1385939.09 KB |
| When_method_has_exceptions_then_exceptions_with_no_code_will_be_ignored |
100000 |
186,864.533 μs |
43,580.8893 μs |
2,388.8156 μs |
55000.0000 |
- |
453126.59 KB |
| When_method_has_exceptions_then_exceptions_with_no_code_will_be_ignored_old |
100000 |
622,202.433 μs |
138,360.9529 μs |
7,584.0307 μs |
171000.0000 |
1000.0000 |
1398466.98 KB |
| When_method_has_only_exceptions_with_no_code_then_error_section_will_not_be_written |
100000 |
170,212.083 μs |
45,516.4586 μs |
2,494.9107 μs |
46500.0000 |
- |
380469.55 KB |
| When_method_has_only_exceptions_with_no_code_then_error_section_will_not_be_written_old |
100000 |
589,140.633 μs |
154,792.2254 μs |
8,484.6842 μs |
159000.0000 |
1000.0000 |
1300001.59 KB |
| When_method_has_no_exceptions_then_it_is_ignored |
100000 |
169,057.350 μs |
85,439.5459 μs |
4,683.2298 μs |
46500.0000 |
- |
381250.4 KB |
| When_method_has_no_exceptions_then_it_is_ignored_old |
100000 |
605,887.400 μs |
56,193.7587 μs |
3,080.1695 μs |
164000.0000 |
1000.0000 |
1339845.36 KB |
| When_method_has_returns_then_it_is_converted |
100000 |
169,595.600 μs |
47,079.1826 μs |
2,580.5689 μs |
46500.0000 |
- |
380469.54 KB |
| When_method_has_returns_then_it_is_converted_old |
100000 |
632,316.367 μs |
102,954.8414 μs |
5,643.3023 μs |
168000.0000 |
1000.0000 |
1372657.04 KB |
| When_method_has_no_returns_then_it_is_ignored |
100000 |
154,807.650 μs |
37,693.7802 μs |
2,066.1233 μs |
43000.0000 |
- |
353126.59 KB |
| When_method_has_no_returns_then_it_is_ignored_old |
100000 |
601,431.833 μs |
166,151.8528 μs |
9,107.3437 μs |
155000.0000 |
1000.0000 |
1270313.3 KB |
| When_method_has_dictionary_args_then_it_is_found |
100000 |
214,225.067 μs |
48,084.7327 μs |
2,635.6865 μs |
57000.0000 |
- |
468009.09 KB |
| When_method_has_dictionary_args_then_it_is_found_old |
100000 |
698,113.633 μs |
123,243.0853 μs |
6,755.3694 μs |
146000.0000 |
1000.0000 |
1196990.77 KB |
Uh oh!
There was an error while loading. Please reload this page.
Summary of the changes (Less than 80 chars)
Related to #8775 (in this specific format)
As discussed in #8775, the current implementation was quite slow.
I intentionally did not introduce any big conceptual changes (yet) and focused only on optimizing the current implementation.
According to the benchmarks below, the general performance has improved by a factor between 2 and 22 (without the
inheritdoc-cases, see below for them) - on average around ×ばつ faster - while memory usage has been reduced significantly to around a third.For
inheritdoc-cases, the situation is a bit different: I discovered that the current implementation mutates the XElement instances retrieved from the XmlDocumentationFileResolver, effectively modifying its internal cache.Here :
graphql-platform/src/HotChocolate/Core/src/Types/Types/Descriptors/Conventions/XmlDocumentationProvider.cs
Lines 320 to 321 in dfe075c
and here:
graphql-platform/src/HotChocolate/Core/src/Types/Types/Descriptors/Conventions/XmlDocumentationProvider.cs
Lines 353 to 354 in dfe075c
This behavior is both undesired (at least I think so) and not thread-safe.
To fix this, I changed the logic to create a copy of the XElement when resolving inheritdoc elements.
This ensures that the cache remains intact and that the implementation is thread-safe.
While this introduces a small performance regression for two out of six inheritdoc cases, I think it is justified since the previous implementation was incorrect and should not be considered a valid baseline: It only replaced the inheritdoc element once within the cached(!) XDocument, meaning that all subsequent calls for the same(!!!) member (which happens all the time in the benchmark) did not need to replace it again and threfore resulting in slightly better, but ultimately incomparable, performance characteristics. Of course, the current behavior could indeed be beneficial at runtime as well, f. e. an interface with many inheritors, but it is not that common as the benchmark indicates.
Overall, even for the
inheritdoc-cases, the performance is still improved or comparable to before, and the memory usage is significantly lower:Note: The PR currently includes the benchmark code so that one can reproduce the results.
I would to remove these benchmarks after the review and applying any suggested change.
Note further: This is a breaking change since I reworked
XmlDocumentationFileResolverto becomeXmlDocumentationResolver.This change is not strictly neccessary, but IIRC it was a 10-20% speed boost - I will reevaluate the concret impact on request if the change seems unlikely to be acceptable.
Full benchmarks: