flamegraphPreview.spec.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import {computePreviewConfigView} from 'sentry/components/profiling/flamegraph/flamegraphPreview';
  2. import {Flamegraph} from 'sentry/utils/profiling/flamegraph';
  3. import {SampledProfile} from 'sentry/utils/profiling/profile/sampledProfile';
  4. import {createFrameIndex} from 'sentry/utils/profiling/profile/utils';
  5. import {Rect} from 'sentry/utils/profiling/speedscope';
  6. describe('computePreviewConfigView', function () {
  7. it('uses early exit with 0', function () {
  8. const rawProfile: Profiling.SampledProfile = {
  9. name: 'profile',
  10. startValue: 0,
  11. endValue: 1000,
  12. unit: 'milliseconds',
  13. threadID: 0,
  14. type: 'sampled',
  15. weights: [1, 1],
  16. samples: [
  17. [0, 1],
  18. [0, 1],
  19. ],
  20. };
  21. const profile = SampledProfile.FromProfile(
  22. rawProfile,
  23. createFrameIndex('mobile', [{name: 'f0'}, {name: 'f1'}]),
  24. {type: 'flamechart'}
  25. );
  26. const flamegraph = new Flamegraph(profile, {});
  27. // the view should be taller than the flamegraph
  28. const configView = new Rect(0, 0, 2, 3);
  29. // go from timestamps 0 to 2
  30. const {configView: previewConfigView, mode} = computePreviewConfigView(
  31. flamegraph,
  32. configView,
  33. 0,
  34. 2
  35. );
  36. // y is 0 here because the config view is taller than the flamegraph
  37. expect(previewConfigView).toEqual(new Rect(0, 0, 2, 3));
  38. expect(mode).toEqual('anchorTop');
  39. });
  40. it('uses max depth', function () {
  41. const rawProfile: Profiling.SampledProfile = {
  42. name: 'profile',
  43. startValue: 0,
  44. endValue: 1000,
  45. unit: 'milliseconds',
  46. threadID: 0,
  47. type: 'sampled',
  48. weights: [1, 1],
  49. samples: [
  50. [0, 1, 0],
  51. [1, 0, 1],
  52. ],
  53. };
  54. const profile = SampledProfile.FromProfile(
  55. rawProfile,
  56. createFrameIndex('mobile', [{name: 'f0'}, {name: 'f1'}]),
  57. {type: 'flamechart'}
  58. );
  59. const flamegraph = new Flamegraph(profile, {});
  60. // limit the view to 2 rows tall
  61. const configView = new Rect(0, 0, 2, 2);
  62. // go from timestamps 0 to 2
  63. const {configView: previewConfigView, mode} = computePreviewConfigView(
  64. flamegraph,
  65. configView,
  66. 0,
  67. 2
  68. );
  69. // y is 1 here because the config view has height 2 so it can only
  70. // show 2 frames and we show the inner most frames
  71. expect(previewConfigView).toEqual(new Rect(0, 1, 2, 2));
  72. expect(mode).toEqual('anchorBottom');
  73. });
  74. it('uses max depth in window', function () {
  75. const rawProfile: Profiling.SampledProfile = {
  76. name: 'profile',
  77. startValue: 0,
  78. endValue: 1000,
  79. unit: 'milliseconds',
  80. threadID: 0,
  81. type: 'sampled',
  82. weights: [1, 1, 1],
  83. samples: [
  84. [0, 1, 0, 1],
  85. [1, 0, 1],
  86. [0, 1, 0],
  87. ],
  88. };
  89. const profile = SampledProfile.FromProfile(
  90. rawProfile,
  91. createFrameIndex('mobile', [{name: 'f0'}, {name: 'f1'}]),
  92. {type: 'flamechart'}
  93. );
  94. const flamegraph = new Flamegraph(profile, {});
  95. // limit the view to 2 rows talls
  96. const configView = new Rect(0, 0, 3, 2);
  97. // go from timestamps 1 to 3 to exclude the first stack
  98. const {configView: previewConfigView, mode} = computePreviewConfigView(
  99. flamegraph,
  100. configView,
  101. 1,
  102. 3
  103. );
  104. // y is 1 here because the config view has height 2 so it can only
  105. // show 2 frames and we show the inner most frames
  106. expect(previewConfigView).toEqual(new Rect(1, 1, 2, 2));
  107. expect(mode).toEqual('anchorBottom');
  108. });
  109. it('uses 0 when view is taller than profile', function () {
  110. const rawProfile: Profiling.SampledProfile = {
  111. name: 'profile',
  112. startValue: 0,
  113. endValue: 1000,
  114. unit: 'milliseconds',
  115. threadID: 0,
  116. type: 'sampled',
  117. weights: [1, 1],
  118. samples: [
  119. [0, 1],
  120. [1, 0],
  121. ],
  122. };
  123. const profile = SampledProfile.FromProfile(
  124. rawProfile,
  125. createFrameIndex('mobile', [{name: 'f0'}, {name: 'f1'}]),
  126. {type: 'flamechart'}
  127. );
  128. const flamegraph = new Flamegraph(profile, {});
  129. // make taller than profile's deepest stack
  130. const configView = new Rect(0, 0, 2, 3);
  131. const {configView: previewConfigView, mode} = computePreviewConfigView(
  132. flamegraph,
  133. configView,
  134. 0,
  135. 2
  136. );
  137. // y is 0 here because the config view has height 3
  138. // so the whole flamechart fits
  139. expect(previewConfigView).toEqual(new Rect(0, 0, 2, 3));
  140. expect(mode).toEqual('anchorTop');
  141. });
  142. it('uses parent frame depth', function () {
  143. const rawProfile: Profiling.SampledProfile = {
  144. name: 'profile',
  145. startValue: 0,
  146. endValue: 1000,
  147. unit: 'milliseconds',
  148. threadID: 0,
  149. type: 'sampled',
  150. weights: [2, 2],
  151. samples: [
  152. [0, 1, 0, 1],
  153. [0, 1, 1, 1],
  154. ],
  155. };
  156. const profile = SampledProfile.FromProfile(
  157. rawProfile,
  158. createFrameIndex('mobile', [{name: 'f0'}, {name: 'f1'}]),
  159. {type: 'flamechart'}
  160. );
  161. const flamegraph = new Flamegraph(profile, {});
  162. const configView = new Rect(0, 0, 4, 2);
  163. const {configView: previewConfigView, mode} = computePreviewConfigView(
  164. flamegraph,
  165. configView,
  166. 1,
  167. 3
  168. );
  169. // y is 1 here because we found a frame `f1` that is wraps
  170. // around the window at depth 1
  171. expect(previewConfigView).toEqual(new Rect(1, 1, 2, 2));
  172. expect(mode).toEqual('anchorTop');
  173. });
  174. it('uses max depth because there is room above parent to show more', function () {
  175. const rawProfile: Profiling.SampledProfile = {
  176. name: 'profile',
  177. startValue: 0,
  178. endValue: 1000,
  179. unit: 'milliseconds',
  180. threadID: 0,
  181. type: 'sampled',
  182. weights: [2, 2],
  183. samples: [
  184. [0, 1, 0],
  185. [0, 1, 1],
  186. ],
  187. };
  188. const profile = SampledProfile.FromProfile(
  189. rawProfile,
  190. createFrameIndex('mobile', [{name: 'f0'}, {name: 'f1'}]),
  191. {type: 'flamechart'}
  192. );
  193. const flamegraph = new Flamegraph(profile, {});
  194. const configView = new Rect(0, 0, 4, 3);
  195. const {configView: previewConfigView, mode} = computePreviewConfigView(
  196. flamegraph,
  197. configView,
  198. 1,
  199. 3
  200. );
  201. // y is 0 here because the config view has height 3
  202. // so the whole flamechart fits even though the parent
  203. // is at depth 1
  204. expect(previewConfigView).toEqual(new Rect(1, 0, 2, 3));
  205. expect(mode).toEqual('anchorTop');
  206. });
  207. });