profile.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // Gathers statistical data, and provides them in convinient form
  2. "use strict";
  3. var partial = require("es5-ext/function/#/partial")
  4. , forEach = require("es5-ext/object/for-each")
  5. , pad = require("es5-ext/string/#/pad")
  6. , compact = require("es5-ext/array/#/compact")
  7. , d = require("d")
  8. , memoize = require("./plain");
  9. var max = Math.max, stats = (exports.statistics = {});
  10. Object.defineProperty(
  11. memoize, "__profiler__",
  12. d(function (conf) {
  13. var id, source, data, stack;
  14. stack = new Error().stack;
  15. if (
  16. !stack ||
  17. !stack
  18. .split("\n")
  19. .slice(3)
  20. .some(function (line) {
  21. if (line.indexOf("/memoizee/") === -1 && line.indexOf(" (native)") === -1) {
  22. source = line.replace(/\n/g, "\\n").trim();
  23. return true;
  24. }
  25. return false;
  26. })
  27. ) {
  28. source = "unknown";
  29. }
  30. id = compact.call([conf.profileName, source]).join(", ");
  31. if (!stats[id]) stats[id] = { initial: 0, cached: 0 };
  32. data = stats[id];
  33. conf.on("set", function () { ++data.initial; });
  34. conf.on("get", function () { ++data.cached; });
  35. })
  36. );
  37. exports.log = function () {
  38. var initial, cached, ordered, ipad, cpad, ppad, toPrc, log;
  39. initial = cached = 0;
  40. ordered = [];
  41. toPrc = function (initialCount, cachedCount) {
  42. if (!initialCount && !cachedCount) {
  43. return "0.00";
  44. }
  45. return ((cachedCount / (initialCount + cachedCount)) * 100).toFixed(2);
  46. };
  47. log = "------------------------------------------------------------\n";
  48. log += "Memoize statistics:\n\n";
  49. forEach(
  50. stats,
  51. function (data, name) {
  52. initial += data.initial;
  53. cached += data.cached;
  54. ordered.push([name, data]);
  55. },
  56. null,
  57. function (nameA, nameB) {
  58. return (
  59. this[nameB].initial +
  60. this[nameB].cached -
  61. (this[nameA].initial + this[nameA].cached)
  62. );
  63. }
  64. );
  65. ipad = partial.call(pad, " ", max(String(initial).length, "Init".length));
  66. cpad = partial.call(pad, " ", max(String(cached).length, "Cache".length));
  67. ppad = partial.call(pad, " ", "%Cache".length);
  68. log +=
  69. ipad.call("Init") +
  70. " " +
  71. cpad.call("Cache") +
  72. " " +
  73. ppad.call("%Cache") +
  74. " Source location\n";
  75. log +=
  76. ipad.call(initial) +
  77. " " +
  78. cpad.call(cached) +
  79. " " +
  80. ppad.call(toPrc(initial, cached)) +
  81. " (all)\n";
  82. ordered.forEach(function (data) {
  83. var name = data[0];
  84. data = data[1];
  85. log +=
  86. ipad.call(data.initial) +
  87. " " +
  88. cpad.call(data.cached) +
  89. " " +
  90. ppad.call(toPrc(data.initial, data.cached)) +
  91. " " +
  92. name +
  93. "\n";
  94. });
  95. log += "------------------------------------------------------------\n";
  96. return log;
  97. };