AvaloniaObject_GetObservable.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. using System;
  2. using System.Runtime.CompilerServices;
  3. using BenchmarkDotNet.Attributes;
  4. #nullable enable
  5. namespace Avalonia.Benchmarks.Base
  6. {
  7. [MemoryDiagnoser]
  8. public class AvaloniaObject_GetObservable
  9. {
  10. private TestClass _target = null!;
  11. public static int result;
  12. public AvaloniaObject_GetObservable()
  13. {
  14. RuntimeHelpers.RunClassConstructor(typeof(TestClass).TypeHandle);
  15. }
  16. [GlobalSetup]
  17. public void Setup()
  18. {
  19. _target = new();
  20. }
  21. [Benchmark(Baseline = true)]
  22. public void PropertyChangedSubscription()
  23. {
  24. var target = _target;
  25. static void ChangeHandler(object? sender, AvaloniaPropertyChangedEventArgs e)
  26. {
  27. if (e.Property == TestClass.StringProperty)
  28. {
  29. var ev = (AvaloniaPropertyChangedEventArgs<string?>)e;
  30. result += ev.NewValue.Value?.Length ?? 0;
  31. }
  32. else if (e.Property == TestClass.Struct1Property)
  33. {
  34. var ev = (AvaloniaPropertyChangedEventArgs<Struct1>)e;
  35. result += ev.NewValue.Value.Int1;
  36. }
  37. else if (e.Property == TestClass.Struct2Property)
  38. {
  39. var ev = (AvaloniaPropertyChangedEventArgs<Struct2>)e;
  40. result += ev.NewValue.Value.Int1;
  41. }
  42. else if (e.Property == TestClass.Struct3Property)
  43. {
  44. var ev = (AvaloniaPropertyChangedEventArgs<Struct3>)e;
  45. result += ev.NewValue.Value.Int1;
  46. }
  47. else if (e.Property == TestClass.Struct4Property)
  48. {
  49. var ev = (AvaloniaPropertyChangedEventArgs<Struct4>)e;
  50. result += ev.NewValue.Value.Int1;
  51. }
  52. else if (e.Property == TestClass.Struct5Property)
  53. {
  54. var ev = (AvaloniaPropertyChangedEventArgs<Struct5>)e;
  55. result += ev.NewValue.Value.Int1;
  56. }
  57. else if (e.Property == TestClass.Struct6Property)
  58. {
  59. var ev = (AvaloniaPropertyChangedEventArgs<Struct6>)e;
  60. result += ev.NewValue.Value.Int1;
  61. }
  62. else if (e.Property == TestClass.Struct7Property)
  63. {
  64. var ev = (AvaloniaPropertyChangedEventArgs<Struct7>)e;
  65. result += ev.NewValue.Value.Int1;
  66. }
  67. else if (e.Property == TestClass.Struct8Property)
  68. {
  69. var ev = (AvaloniaPropertyChangedEventArgs<Struct8>)e;
  70. result += ev.NewValue.Value.Int1;
  71. }
  72. }
  73. target.PropertyChanged += ChangeHandler;
  74. // GetObservable fires with the initial value so to compare like-for-like we also need
  75. // to get the initial value here.
  76. result += target.GetValue(TestClass.StringProperty)?.Length ?? 0;
  77. result += target.GetValue(TestClass.Struct1Property).Int1;
  78. result += target.GetValue(TestClass.Struct2Property).Int1;
  79. result += target.GetValue(TestClass.Struct3Property).Int1;
  80. result += target.GetValue(TestClass.Struct4Property).Int1;
  81. result += target.GetValue(TestClass.Struct5Property).Int1;
  82. result += target.GetValue(TestClass.Struct6Property).Int1;
  83. result += target.GetValue(TestClass.Struct7Property).Int1;
  84. result += target.GetValue(TestClass.Struct8Property).Int1;
  85. for (var i = 0; i < 100; ++i)
  86. {
  87. target.SetValue(TestClass.StringProperty, "foo" + i);
  88. target.SetValue(TestClass.Struct1Property, new(i + 1));
  89. target.SetValue(TestClass.Struct2Property, new(i + 1));
  90. target.SetValue(TestClass.Struct3Property, new(i + 1));
  91. target.SetValue(TestClass.Struct4Property, new(i + 1));
  92. target.SetValue(TestClass.Struct5Property, new(i + 1));
  93. target.SetValue(TestClass.Struct6Property, new(i + 1));
  94. target.SetValue(TestClass.Struct7Property, new(i + 1));
  95. target.SetValue(TestClass.Struct8Property, new(i + 1));
  96. }
  97. target.PropertyChanged -= ChangeHandler;
  98. }
  99. [Benchmark]
  100. public void GetObservables()
  101. {
  102. var target = _target;
  103. var sub1 = target.GetObservable(TestClass.StringProperty).Subscribe(x => result += x?.Length ?? 0);
  104. var sub2 = target.GetObservable(TestClass.Struct1Property).Subscribe(x => result += x.Int1);
  105. var sub3 = target.GetObservable(TestClass.Struct2Property).Subscribe(x => result += x.Int1);
  106. var sub4 = target.GetObservable(TestClass.Struct3Property).Subscribe(x => result += x.Int1);
  107. var sub5 = target.GetObservable(TestClass.Struct4Property).Subscribe(x => result += x.Int1);
  108. var sub6 = target.GetObservable(TestClass.Struct5Property).Subscribe(x => result += x.Int1);
  109. var sub7 = target.GetObservable(TestClass.Struct6Property).Subscribe(x => result += x.Int1);
  110. var sub8 = target.GetObservable(TestClass.Struct7Property).Subscribe(x => result += x.Int1);
  111. var sub9 = target.GetObservable(TestClass.Struct8Property).Subscribe(x => result += x.Int1);
  112. for (var i = 0; i < 100; ++i)
  113. {
  114. target.SetValue(TestClass.StringProperty, "foo" + i);
  115. target.SetValue(TestClass.Struct1Property, new(i + 1));
  116. target.SetValue(TestClass.Struct2Property, new(i + 1));
  117. target.SetValue(TestClass.Struct3Property, new(i + 1));
  118. target.SetValue(TestClass.Struct4Property, new(i + 1));
  119. target.SetValue(TestClass.Struct5Property, new(i + 1));
  120. target.SetValue(TestClass.Struct6Property, new(i + 1));
  121. target.SetValue(TestClass.Struct7Property, new(i + 1));
  122. target.SetValue(TestClass.Struct8Property, new(i + 1));
  123. }
  124. sub1.Dispose();
  125. sub2.Dispose();
  126. sub3.Dispose();
  127. sub4.Dispose();
  128. sub5.Dispose();
  129. sub6.Dispose();
  130. sub7.Dispose();
  131. sub8.Dispose();
  132. sub9.Dispose();
  133. }
  134. private class TestClass : AvaloniaObject
  135. {
  136. public static readonly StyledProperty<string> StringProperty =
  137. AvaloniaProperty.Register<TestClass, string>("String");
  138. public static readonly StyledProperty<Struct1> Struct1Property =
  139. AvaloniaProperty.Register<TestClass, Struct1>("Struct1");
  140. public static readonly StyledProperty<Struct2> Struct2Property =
  141. AvaloniaProperty.Register<TestClass, Struct2>("Struct2");
  142. public static readonly StyledProperty<Struct3> Struct3Property =
  143. AvaloniaProperty.Register<TestClass, Struct3>("Struct3");
  144. public static readonly StyledProperty<Struct4> Struct4Property =
  145. AvaloniaProperty.Register<TestClass, Struct4>("Struct4");
  146. public static readonly StyledProperty<Struct5> Struct5Property =
  147. AvaloniaProperty.Register<TestClass, Struct5>("Struct5");
  148. public static readonly StyledProperty<Struct6> Struct6Property =
  149. AvaloniaProperty.Register<TestClass, Struct6>("Struct6");
  150. public static readonly StyledProperty<Struct7> Struct7Property =
  151. AvaloniaProperty.Register<TestClass, Struct7>("Struct7");
  152. public static readonly StyledProperty<Struct8> Struct8Property =
  153. AvaloniaProperty.Register<TestClass, Struct8>("Struct8");
  154. }
  155. }
  156. }