metrics.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. //
  2. // Copyright (c) 2014-2015, THUNDERBEAST GAMES LLC All rights reserved
  3. // LICENSE: Atomic Game Engine Editor and Tools EULA
  4. // Please see LICENSE_ATOMIC_EDITOR_AND_TOOLS.md in repository root for
  5. // license information: https://github.com/AtomicGameEngine/AtomicGameEngine
  6. //
  7. // Wraps the performance API / performance API polyfill
  8. import performance = require("modules/usertiming");
  9. const METRICS_ENABLED = true;
  10. /**
  11. * Decorator to wrap a function with enter/exit profile
  12. * @param {Object} target
  13. * @param {string} propertyKey
  14. * @param {TypedPropertyDescriptor<any>} descriptor
  15. * @return {TypedPropertyDesciptor<any>}
  16. */
  17. export function profileDecorator(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
  18. const originalMethod = descriptor.value;
  19. descriptor.value = function(...args: any[]) {
  20. let result;
  21. start(propertyKey);
  22. try {
  23. result = originalMethod.apply(this, args);
  24. } finally {
  25. stop(propertyKey);
  26. return result;
  27. }
  28. };
  29. return descriptor;
  30. }
  31. /**
  32. * add a start mark to the profiler
  33. * @param {string} key
  34. */
  35. export function start(key: string) {
  36. if (METRICS_ENABLED) {
  37. performance.mark(key + "_start");
  38. }
  39. }
  40. /**
  41. * Add a stop mark to the profiler and capture a measurement
  42. * @param {string} key
  43. */
  44. export function stop(key: string) {
  45. if (METRICS_ENABLED) {
  46. performance.mark(key + "_stop");
  47. performance.measure(key, key + "_start", key + "_stop");
  48. }
  49. }
  50. export interface MetricRollup {
  51. key: string;
  52. timesCalled: number;
  53. avgDuration: number;
  54. totalDuration: number;
  55. }
  56. /**
  57. * Returns an array of metric rollups
  58. * @return {[MetricRollup]}
  59. */
  60. export function getMetricRollups(): MetricRollup[] {
  61. if (METRICS_ENABLED) {
  62. const metrics = {};
  63. performance.getEntriesByType("measure").forEach((entry) => {
  64. if (!metrics[entry.name]) {
  65. metrics[entry.name] = [];
  66. }
  67. metrics[entry.name].push(entry);
  68. });
  69. const vals = [];
  70. for (let mname in metrics) {
  71. let totalduration = 0;
  72. let metricBlock = metrics[mname];
  73. for (let i = 0; i < metricBlock.length; i++) {
  74. totalduration += metricBlock[i].duration;
  75. }
  76. vals.push({
  77. key: mname,
  78. timesCalled: metricBlock.length,
  79. avgDuration: totalduration / metricBlock.length,
  80. totalDuration: totalduration
  81. });
  82. }
  83. return vals;
  84. } else {
  85. return [];
  86. }
  87. }
  88. /**
  89. * Write metrics to the console
  90. */
  91. export function logMetrics() {
  92. getMetricRollups().forEach((metric) => {
  93. console.log(`${metric.key} Called: ${metric.timesCalled}, Average Duration:${metric.avgDuration}, Total Duration: ${metric.totalDuration}`);
  94. });
  95. }