SVG icon indicating copy to clipboard operation
SVG copied to clipboard

Memory usage optimization for SvgElement

Open wieslawsoltes opened this issue 3 years ago • 3 comments

Reference Issue

What does this implement/fix? Explain your changes.

Defers memory allocation until needed when creating new SvgElement's from 712 bytes to 200 bytes.

Any other comments?

dotnet run -c Release -f netcoreapp3.1 -- -f '*SvgDocument_*'
  • master branch
|                             Method |      Mean |     Error |    StdDev |   Op/s | Rank |     Gen 0 |    Gen 1 |    Gen 2 | Allocated |
|----------------------------------- |----------:|----------:|----------:|-------:|-----:|----------:|---------:|---------:|----------:|
| SvgDocument_Open_AJ_Digital_Camera |  5.214 ms | 0.0724 ms | 0.0605 ms | 191.77 |    2 |  492.1875 | 203.1250 |        - |   2.79 MB |
|      SvgDocument_Open_Issue_134_01 | 29.884 ms | 0.5288 ms | 0.4687 ms |  33.46 |    3 | 2031.2500 | 812.5000 | 406.2500 |  11.72 MB |
|             SvgDocument_Open_Tiger |  4.766 ms | 0.0774 ms | 0.0647 ms | 209.83 |    1 |  398.4375 | 195.3125 |        - |   2.23 MB |
  • SvgElementMemoryUsageOptimization branch
|                             Method |      Mean |     Error |    StdDev |   Op/s | Rank |     Gen 0 |    Gen 1 |    Gen 2 | Allocated |
|----------------------------------- |----------:|----------:|----------:|-------:|-----:|----------:|---------:|---------:|----------:|
| SvgDocument_Open_AJ_Digital_Camera |  4.831 ms | 0.0554 ms | 0.0491 ms | 206.99 |    2 |  445.3125 | 218.7500 |        - |   2.46 MB |
|      SvgDocument_Open_Issue_134_01 | 27.144 ms | 0.5050 ms | 0.5816 ms |  36.84 |    3 | 1812.5000 | 656.2500 | 218.7500 |  10.66 MB |
|             SvgDocument_Open_Tiger |  4.397 ms | 0.0491 ms | 0.0410 ms | 227.42 |    1 |  367.1875 | 132.8125 |        - |   1.91 MB |

wieslawsoltes avatar Jan 16 '21 17:01 wieslawsoltes

  • master
|                         Method |       Mean |     Error |    StdDev |          Op/s | Ratio | Rank |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------- |-----------:|----------:|----------:|--------------:|------:|-----:|-------:|------:|------:|----------:|
|      SvgElement_new_EmptyClass |   1.897 ns | 0.0141 ns | 0.0125 ns | 527,034,350.4 | 0.008 |    1 |      - |     - |     - |         - |
| SvgElement_new_SvgElementEmpty | 239.817 ns | 2.9742 ns | 2.7821 ns |   4,169,837.8 | 1.000 |    2 | 0.1702 |     - |     - |     712 B |
  • defer initialization of _nodes
|                         Method |       Mean |     Error |    StdDev |          Op/s | Ratio | Rank |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------- |-----------:|----------:|----------:|--------------:|------:|-----:|-------:|------:|------:|----------:|
|      SvgElement_new_EmptyClass |   1.904 ns | 0.0210 ns | 0.0186 ns | 525,156,053.4 | 0.008 |    1 |      - |     - |     - |         - |
| SvgElement_new_SvgElementEmpty | 227.216 ns | 3.2265 ns | 2.6943 ns |   4,401,091.9 | 1.000 |    2 | 0.1624 |     - |     - |     680 B |
  • defer initialization of _eventHandlers
|                         Method |       Mean |     Error |    StdDev |          Op/s | Ratio | Rank |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------- |-----------:|----------:|----------:|--------------:|------:|-----:|-------:|------:|------:|----------:|
|      SvgElement_new_EmptyClass |   1.905 ns | 0.0279 ns | 0.0233 ns | 524,995,126.5 | 0.008 |    1 |      - |     - |     - |         - |
| SvgElement_new_SvgElementEmpty | 232.512 ns | 4.4016 ns | 6.8527 ns |   4,300,859.1 | 1.000 |    2 | 0.1547 |     - |     - |     648 B |
  • defer initialization of _children
|                         Method |       Mean |     Error |    StdDev |          Op/s | Ratio | Rank |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------- |-----------:|----------:|----------:|--------------:|------:|-----:|-------:|------:|------:|----------:|
|      SvgElement_new_EmptyClass |   1.406 ns | 0.0114 ns | 0.0101 ns | 711,160,475.5 | 0.007 |    1 |      - |     - |     - |         - |
| SvgElement_new_SvgElementEmpty | 213.413 ns | 1.9136 ns | 1.5979 ns |   4,685,749.5 | 1.000 |    2 | 0.1376 |     - |     - |     576 B |
  • defer initialization of _styles
|                         Method |       Mean |     Error |    StdDev |          Op/s | Ratio | Rank |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------- |-----------:|----------:|----------:|--------------:|------:|-----:|-------:|------:|------:|----------:|
|      SvgElement_new_EmptyClass |   1.886 ns | 0.0244 ns | 0.0216 ns | 530,298,131.8 |  0.01 |    1 |      - |     - |     - |         - |
| SvgElement_new_SvgElementEmpty | 160.923 ns | 2.1405 ns | 1.7874 ns |   6,214,149.2 |  1.00 |    2 | 0.1204 |     - |     - |     504 B |
  • defer initialization of _customAttributes
|                         Method |      Mean |     Error |    StdDev |          Op/s | Ratio | Rank |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------- |----------:|----------:|----------:|--------------:|------:|-----:|-------:|------:|------:|----------:|
|      SvgElement_new_EmptyClass |  1.903 ns | 0.0368 ns | 0.0362 ns | 525,505,200.1 |  0.14 |    1 |      - |     - |     - |         - |
| SvgElement_new_SvgElementEmpty | 13.735 ns | 0.2923 ns | 0.4636 ns |  72,804,361.3 |  1.00 |    2 | 0.0478 |     - |     - |     200 B |

wieslawsoltes avatar Jan 16 '21 17:01 wieslawsoltes

https://docs.microsoft.com/en-us/dotnet/api/system.xml.xmltextreader?view=net-5.0#remarks

Starting with the .NET Framework 2.0, we recommend that you create XmlReader instances by using the XmlReader.Create method to take advantage of new functionality.

|                        Method |     Mean |    Error |   StdDev |        Op/s | Rank |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|------------------------------ |---------:|---------:|---------:|------------:|-----:|-------:|------:|------:|----------:|
| SvgDocument_new_XmlTextReader | 777.1 ns | 15.45 ns | 35.82 ns | 1,286,812.8 |    1 | 2.4090 |     - |     - |   9.84 KB |

Empty XmlTextReader allocates 10KB !

wieslawsoltes avatar Jan 17 '21 13:01 wieslawsoltes

I think this can now be merged because. The Roslyn Compiler can soon do switches on ReadonlySpans see issue. https://github.com/dotnet/csharplang/issues/1881

inforithmics avatar Mar 15 '22 12:03 inforithmics