performance.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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 { Task } = require("devtools/shared/task");
  7. const { Actor, ActorClassWithSpec } = require("devtools/shared/protocol");
  8. const { actorBridgeWithSpec } = require("devtools/server/actors/common");
  9. const { performanceSpec } = require("devtools/shared/specs/performance");
  10. loader.lazyRequireGetter(this, "events", "sdk/event/core");
  11. loader.lazyRequireGetter(this, "extend", "sdk/util/object", true);
  12. loader.lazyRequireGetter(this, "PerformanceRecorder",
  13. "devtools/server/performance/recorder", true);
  14. loader.lazyRequireGetter(this, "normalizePerformanceFeatures",
  15. "devtools/shared/performance/recording-utils", true);
  16. const PIPE_TO_FRONT_EVENTS = new Set([
  17. "recording-started", "recording-stopping", "recording-stopped",
  18. "profiler-status", "timeline-data", "console-profile-start"
  19. ]);
  20. const RECORDING_STATE_CHANGE_EVENTS = new Set([
  21. "recording-started", "recording-stopping", "recording-stopped"
  22. ]);
  23. /**
  24. * This actor wraps the Performance module at devtools/shared/shared/performance.js
  25. * and provides RDP definitions.
  26. *
  27. * @see devtools/shared/shared/performance.js for documentation.
  28. */
  29. var PerformanceActor = ActorClassWithSpec(performanceSpec, {
  30. traits: {
  31. features: {
  32. withMarkers: true,
  33. withTicks: true,
  34. withMemory: true,
  35. withFrames: true,
  36. withGCEvents: true,
  37. withDocLoadingEvents: true,
  38. withAllocations: true,
  39. },
  40. },
  41. initialize: function (conn, tabActor) {
  42. Actor.prototype.initialize.call(this, conn);
  43. this._onRecorderEvent = this._onRecorderEvent.bind(this);
  44. this.bridge = new PerformanceRecorder(conn, tabActor);
  45. events.on(this.bridge, "*", this._onRecorderEvent);
  46. },
  47. /**
  48. * `disconnect` method required to call destroy, since this
  49. * actor is not managed by a parent actor.
  50. */
  51. disconnect: function () {
  52. this.destroy();
  53. },
  54. destroy: function () {
  55. events.off(this.bridge, "*", this._onRecorderEvent);
  56. this.bridge.destroy();
  57. Actor.prototype.destroy.call(this);
  58. },
  59. connect: function (config) {
  60. this.bridge.connect({ systemClient: config.systemClient });
  61. return { traits: this.traits };
  62. },
  63. canCurrentlyRecord: function () {
  64. return this.bridge.canCurrentlyRecord();
  65. },
  66. startRecording: Task.async(function* (options = {}) {
  67. if (!this.bridge.canCurrentlyRecord().success) {
  68. return null;
  69. }
  70. let normalizedOptions = normalizePerformanceFeatures(options, this.traits.features);
  71. let recording = yield this.bridge.startRecording(normalizedOptions);
  72. this.manage(recording);
  73. return recording;
  74. }),
  75. stopRecording: actorBridgeWithSpec("stopRecording"),
  76. isRecording: actorBridgeWithSpec("isRecording"),
  77. getRecordings: actorBridgeWithSpec("getRecordings"),
  78. getConfiguration: actorBridgeWithSpec("getConfiguration"),
  79. setProfilerStatusInterval: actorBridgeWithSpec("setProfilerStatusInterval"),
  80. /**
  81. * Filter which events get piped to the front.
  82. */
  83. _onRecorderEvent: function (eventName, ...data) {
  84. // If this is a recording state change, call
  85. // a method on the related PerformanceRecordingActor so it can
  86. // update its internal state.
  87. if (RECORDING_STATE_CHANGE_EVENTS.has(eventName)) {
  88. let recording = data[0];
  89. let extraData = data[1];
  90. recording._setState(eventName, extraData);
  91. }
  92. if (PIPE_TO_FRONT_EVENTS.has(eventName)) {
  93. events.emit(this, eventName, ...data);
  94. }
  95. },
  96. });
  97. exports.PerformanceActor = PerformanceActor;