profile.js 2.5 KB

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