performance.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. const { Cu } = require("chrome");
  6. const { Front, FrontClassWithSpec, custom, preEvent } = require("devtools/shared/protocol");
  7. const { PerformanceRecordingFront } = require("devtools/shared/fronts/performance-recording");
  8. const { performanceSpec } = require("devtools/shared/specs/performance");
  9. const { Task } = require("devtools/shared/task");
  10. loader.lazyRequireGetter(this, "PerformanceIO",
  11. "devtools/client/performance/modules/io");
  12. loader.lazyRequireGetter(this, "LegacyPerformanceFront",
  13. "devtools/client/performance/legacy/front", true);
  14. loader.lazyRequireGetter(this, "getSystemInfo",
  15. "devtools/shared/system", true);
  16. const PerformanceFront = FrontClassWithSpec(performanceSpec, {
  17. initialize: function (client, form) {
  18. Front.prototype.initialize.call(this, client, form);
  19. this.actorID = form.performanceActor;
  20. this.manage(this);
  21. },
  22. destroy: function () {
  23. Front.prototype.destroy.call(this);
  24. },
  25. /**
  26. * Conenct to the server, and handle once-off tasks like storing traits
  27. * or system info.
  28. */
  29. connect: custom(Task.async(function* () {
  30. let systemClient = yield getSystemInfo();
  31. let { traits } = yield this._connect({ systemClient });
  32. this._traits = traits;
  33. return this._traits;
  34. }), {
  35. impl: "_connect"
  36. }),
  37. get traits() {
  38. if (!this._traits) {
  39. Cu.reportError("Cannot access traits of PerformanceFront before " +
  40. "calling `connect()`.");
  41. }
  42. return this._traits;
  43. },
  44. /**
  45. * Pass in a PerformanceRecording and get a normalized value from 0 to 1 of how much
  46. * of this recording's lifetime remains without being overwritten.
  47. *
  48. * @param {PerformanceRecording} recording
  49. * @return {number?}
  50. */
  51. getBufferUsageForRecording: function (recording) {
  52. if (!recording.isRecording()) {
  53. return void 0;
  54. }
  55. let {
  56. position: currentPosition,
  57. totalSize,
  58. generation: currentGeneration
  59. } = this._currentBufferStatus;
  60. let {
  61. position: origPosition,
  62. generation: origGeneration
  63. } = recording.getStartingBufferStatus();
  64. let normalizedCurrent = (totalSize * (currentGeneration - origGeneration)) +
  65. currentPosition;
  66. let percent = (normalizedCurrent - origPosition) / totalSize;
  67. // Clamp between 0 and 1; can get negative percentage values when a new
  68. // recording starts and the currentBufferStatus has not yet been updated. Rather
  69. // than fetching another status update, just clamp to 0, and this will be updated
  70. // on the next profiler-status event.
  71. if (percent < 0) {
  72. return 0;
  73. } else if (percent > 1) {
  74. return 1;
  75. }
  76. return percent;
  77. },
  78. /**
  79. * Loads a recording from a file.
  80. *
  81. * @param {nsILocalFile} file
  82. * The file to import the data from.
  83. * @return {Promise<PerformanceRecordingFront>}
  84. */
  85. importRecording: function (file) {
  86. return PerformanceIO.loadRecordingFromFile(file).then(recordingData => {
  87. let model = new PerformanceRecordingFront();
  88. model._imported = true;
  89. model._label = recordingData.label || "";
  90. model._duration = recordingData.duration;
  91. model._markers = recordingData.markers;
  92. model._frames = recordingData.frames;
  93. model._memory = recordingData.memory;
  94. model._ticks = recordingData.ticks;
  95. model._allocations = recordingData.allocations;
  96. model._profile = recordingData.profile;
  97. model._configuration = recordingData.configuration || {};
  98. model._systemHost = recordingData.systemHost;
  99. model._systemClient = recordingData.systemClient;
  100. return model;
  101. });
  102. },
  103. /**
  104. * Store profiler status when the position has been update so we can
  105. * calculate recording's buffer percentage usage after emitting the event.
  106. */
  107. _onProfilerStatus: preEvent("profiler-status", function (data) {
  108. this._currentBufferStatus = data;
  109. }),
  110. /**
  111. * For all PerformanceRecordings that are recording, and needing realtime markers,
  112. * apply the timeline data to the front PerformanceRecording (so we only have one event
  113. * for each timeline data chunk as they could be shared amongst several recordings).
  114. */
  115. _onTimelineEvent: preEvent("timeline-data", function (type, data, recordings) {
  116. for (let recording of recordings) {
  117. recording._addTimelineData(type, data);
  118. }
  119. }),
  120. });
  121. exports.PerformanceFront = PerformanceFront;
  122. exports.createPerformanceFront = function createPerformanceFront(target) {
  123. // If we force legacy mode, or the server does not have a performance actor (< Fx42),
  124. // use our LegacyPerformanceFront which will handle
  125. // the communication over RDP to other underlying actors.
  126. if (target.TEST_PERFORMANCE_LEGACY_FRONT || !target.form.performanceActor) {
  127. return new LegacyPerformanceFront(target);
  128. }
  129. // If our server has a PerformanceActor implementation, set this
  130. // up like a normal front.
  131. return new PerformanceFront(target.client, target.form);
  132. };