Global Metrics

path: .metrics.halstead.level
old: 0.07138047138047138
new: 0.10016420361247948

path: .metrics.halstead.difficulty
old: 14.00943396226415
new: 9.98360655737705

path: .metrics.halstead.length
old: 205.0
new: 208.0

path: .metrics.halstead.n1
old: 15.0
new: 14.0

path: .metrics.halstead.time
old: 971.2661821004372
new: 718.5946458674811

path: .metrics.halstead.estimated_program_length
old: 362.1831430259773
new: 415.07794650014256

path: .metrics.halstead.n2
old: 53.0
new: 61.0

path: .metrics.halstead.volume
old: 1247.9298824563195
new: 1295.5942876231431

path: .metrics.halstead.vocabulary
old: 68.0
new: 75.0

path: .metrics.halstead.N2
old: 99.0
new: 87.0

path: .metrics.halstead.N1
old: 106.0
new: 121.0

path: .metrics.halstead.bugs
old: 0.2245359717882912
new: 0.18367486671363364

path: .metrics.halstead.effort
old: 17482.79127780787
new: 12934.703625614658

path: .metrics.halstead.purity_ratio
old: 1.7667470391511089
new: 1.9955670504814549

path: .metrics.loc.lloc
old: 3.0
new: 0.0

path: .metrics.loc.ploc
old: 59.0
new: 57.0

path: .metrics.loc.sloc
old: 121.0
new: 91.0

path: .metrics.loc.cloc
old: 44.0
new: 16.0

path: .metrics.mi.mi_sei
old: 42.87689616065896
new: 40.2121863514636

path: .metrics.mi.mi_original
old: 53.47613807153961
new: 58.817107147639135

path: .metrics.mi.mi_visual_studio
old: 31.272595363473457
new: 34.395969092186625

path: .metrics.cyclomatic.average
old: 1.0
new: 1.6

path: .metrics.cyclomatic.sum
old: 12.0
new: 8.0

path: .metrics.nom.total
old: 5.0
new: 0.0

path: .metrics.nom.functions
old: 5.0
new: 0.0

path: .metrics.cognitive.average
old: 0.0
new: null

path: .metrics.nexits.average
old: 0.6
new: null

path: .metrics.nexits.sum
old: 3.0
new: 0.0

path: .metrics.nargs.sum
old: 3.0
new: 0.0

path: .metrics.nargs.average
old: 0.6
new: null

Spaces Data

Minimal test - lines (24, 87)

path: .spaces[1].spaces[0].metrics.cyclomatic.average
old: 1.0
new: 2.5

path: .spaces[1].spaces[0].metrics.cyclomatic.sum
old: 1.0
new: 5.0

path: .spaces[1].spaces[0].metrics.loc.blank
old: 0.0
new: 13.0

path: .spaces[1].spaces[0].metrics.loc.cloc
old: 0.0
new: 5.0

path: .spaces[1].spaces[0].metrics.loc.sloc
old: 1.0
new: 64.0

path: .spaces[1].spaces[0].metrics.loc.ploc
old: 1.0
new: 46.0

path: .spaces[1].spaces[0].metrics.halstead.level
old: null
new: 0.09890109890109892

path: .spaces[1].spaces[0].metrics.halstead.purity_ratio
old: null
new: 1.857484153192009

path: .spaces[1].spaces[0].metrics.halstead.N2
old: 1.0
new: 78.0

path: .spaces[1].spaces[0].metrics.halstead.effort
old: 0.0
new: 12063.998581837894

path: .spaces[1].spaces[0].metrics.halstead.n1
old: 0.0
new: 14.0

path: .spaces[1].spaces[0].metrics.halstead.length
old: 1.0
new: 196.0

path: .spaces[1].spaces[0].metrics.halstead.difficulty
old: 0.0
new: 10.11111111111111

path: .spaces[1].spaces[0].metrics.halstead.n2
old: 1.0
new: 54.0

path: .spaces[1].spaces[0].metrics.halstead.N1
old: 0.0
new: 118.0

path: .spaces[1].spaces[0].metrics.halstead.vocabulary
old: 1.0
new: 68.0

path: .spaces[1].spaces[0].metrics.halstead.time
old: 0.0
new: 670.2221434354385

path: .spaces[1].spaces[0].metrics.halstead.bugs
old: 0.0
new: 0.17533674109695083

path: .spaces[1].spaces[0].metrics.halstead.estimated_program_length
old: null
new: 364.06689402563376

path: .spaces[1].spaces[0].metrics.halstead.volume
old: 0.0
new: 1193.1427168850664

path: .spaces[1].spaces[0].metrics.mi.mi_visual_studio
old: null
new: 38.38449977970829

path: .spaces[1].spaces[0].metrics.mi.mi_original
old: null
new: 65.63749462330118

path: .spaces[1].spaces[0].metrics.mi.mi_sei
old: null
new: 40.4835027586595

Code

class ProfilerChild final : public PProfilerChild,
                            public mozilla::ipc::IShmemAllocator {
  NS_INLINE_DECL_REFCOUNTING(ProfilerChild)

  ProfilerChild();

  // Collects and returns a profile.
  // This method can be used to grab a profile just before PProfiler is torn
  // down. The collected profile should then be sent through a different
  // message channel that is guaranteed to stay open long enough.
  nsCString GrabShutdownProfile();

  void Destroy();

  // This should be called regularly from outside of the profiler lock.
  static void ProcessPendingUpdate();

  static bool IsLockedOnCurrentThread();

 private:
  virtual ~ProfilerChild();

  mozilla::ipc::IPCResult RecvStart(const ProfilerInitParams& params) override;
  mozilla::ipc::IPCResult RecvEnsureStarted(
      const ProfilerInitParams& params) override;
  mozilla::ipc::IPCResult RecvStop() override;
  mozilla::ipc::IPCResult RecvPause() override;
  mozilla::ipc::IPCResult RecvResume() override;
  mozilla::ipc::IPCResult RecvPauseSampling() override;
  mozilla::ipc::IPCResult RecvResumeSampling() override;
  mozilla::ipc::IPCResult RecvAwaitNextChunkManagerUpdate(
      AwaitNextChunkManagerUpdateResolver&& aResolve) override;
  mozilla::ipc::IPCResult RecvDestroyReleasedChunksAtOrBefore(
      const TimeStamp& aTimeStamp) override;
  mozilla::ipc::IPCResult RecvGatherProfile(
      GatherProfileResolver&& aResolve) override;
  mozilla::ipc::IPCResult RecvClearAllPages() override;

  void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;

  FORWARD_SHMEM_ALLOCATOR_TO(PProfilerChild)

  void SetupChunkManager();
  void ResetChunkManager();
  void ResolveChunkUpdate(
      PProfilerChild::AwaitNextChunkManagerUpdateResolver& aResolve);
  void ProcessChunkManagerUpdate(
      ProfileBufferControlledChunkManager::Update&& aUpdate);

  nsCOMPtr mThread;
  bool mDestroyed;

  ProfileBufferControlledChunkManager* mChunkManager = nullptr;
  AwaitNextChunkManagerUpdateResolver mAwaitNextChunkManagerUpdateResolver;
  ProfileBufferControlledChunkManager::Update mChunkManagerUpdate;

  struct ProfilerChildAndUpdate {
    RefPtr mProfilerChild;
    ProfileBufferControlledChunkManager::Update mUpdate;
  };
  static DataMutexBase
      sPendingChunkManagerUpdate;
};

Minimal test - lines (18, 89)

path: .spaces[1].metrics.nexits.average
old: 0.6
new: null

path: .spaces[1].metrics.nexits.sum
old: 3.0
new: 0.0

path: .spaces[1].metrics.loc.cloc
old: 38.0
new: 9.0

path: .spaces[1].metrics.loc.ploc
old: 51.0
new: 48.0

path: .spaces[1].metrics.loc.lloc
old: 3.0
new: 0.0

path: .spaces[1].metrics.loc.blank
old: 13.0
new: 15.0

path: .spaces[1].metrics.loc.sloc
old: 102.0
new: 72.0

path: .spaces[1].metrics.cyclomatic.average
old: 1.0
new: 2.0

path: .spaces[1].metrics.cyclomatic.sum
old: 10.0
new: 6.0

path: .spaces[1].metrics.nargs.average
old: 0.6
new: null

path: .spaces[1].metrics.nargs.sum
old: 3.0
new: 0.0

path: .spaces[1].metrics.nom.total
old: 5.0
new: 0.0

path: .spaces[1].metrics.nom.functions
old: 5.0
new: 0.0

path: .spaces[1].metrics.halstead.n2
old: 48.0
new: 55.0

path: .spaces[1].metrics.halstead.length
old: 198.0
new: 199.0

path: .spaces[1].metrics.halstead.volume
old: 1183.5014248529835
new: 1215.5963668988556

path: .spaces[1].metrics.halstead.N1
old: 105.0
new: 120.0

path: .spaces[1].metrics.halstead.effort
old: 17197.755079894916
new: 12222.26892536486

path: .spaces[1].metrics.halstead.N2
old: 93.0
new: 79.0

path: .spaces[1].metrics.halstead.time
old: 955.4308377719398
new: 679.0149402980477

path: .spaces[1].metrics.halstead.vocabulary
old: 63.0
new: 69.0

path: .spaces[1].metrics.halstead.estimated_program_length
old: 326.6815589687433
new: 371.27775315266274

path: .spaces[1].metrics.halstead.difficulty
old: 14.53125
new: 10.054545454545456

path: .spaces[1].metrics.halstead.level
old: 0.06881720430107527
new: 0.09945750452079566

path: .spaces[1].metrics.halstead.purity_ratio
old: 1.6499068634785017
new: 1.8657173525259432

path: .spaces[1].metrics.halstead.bugs
old: 0.22208876296002028
new: 0.1768669291419222

path: .spaces[1].metrics.halstead.n1
old: 15.0
new: 14.0

path: .spaces[1].metrics.cognitive.average
old: 0.0
new: null

path: .spaces[1].metrics.mi.mi_original
old: 56.97903073379355
new: 63.40246049594151

path: .spaces[1].metrics.mi.mi_sei
old: 48.06247790853008
new: 42.41769747770328

path: .spaces[1].metrics.mi.mi_visual_studio
old: 33.32107060455763
new: 37.07746227832837

Code

namespace mozilla {

// The ProfilerChild actor is created in all processes except for the main
// process. The corresponding ProfilerParent actor is created in the main
// process, and it will notify us about profiler state changes and request
// profiles from us.
class ProfilerChild final : public PProfilerChild,
                            public mozilla::ipc::IShmemAllocator {
  NS_INLINE_DECL_REFCOUNTING(ProfilerChild)

  ProfilerChild();

  // Collects and returns a profile.
  // This method can be used to grab a profile just before PProfiler is torn
  // down. The collected profile should then be sent through a different
  // message channel that is guaranteed to stay open long enough.
  nsCString GrabShutdownProfile();

  void Destroy();

  // This should be called regularly from outside of the profiler lock.
  static void ProcessPendingUpdate();

  static bool IsLockedOnCurrentThread();

 private:
  virtual ~ProfilerChild();

  mozilla::ipc::IPCResult RecvStart(const ProfilerInitParams& params) override;
  mozilla::ipc::IPCResult RecvEnsureStarted(
      const ProfilerInitParams& params) override;
  mozilla::ipc::IPCResult RecvStop() override;
  mozilla::ipc::IPCResult RecvPause() override;
  mozilla::ipc::IPCResult RecvResume() override;
  mozilla::ipc::IPCResult RecvPauseSampling() override;
  mozilla::ipc::IPCResult RecvResumeSampling() override;
  mozilla::ipc::IPCResult RecvAwaitNextChunkManagerUpdate(
      AwaitNextChunkManagerUpdateResolver&& aResolve) override;
  mozilla::ipc::IPCResult RecvDestroyReleasedChunksAtOrBefore(
      const TimeStamp& aTimeStamp) override;
  mozilla::ipc::IPCResult RecvGatherProfile(
      GatherProfileResolver&& aResolve) override;
  mozilla::ipc::IPCResult RecvClearAllPages() override;

  void ActorDestroy(ActorDestroyReason aActorDestroyReason) override;

  FORWARD_SHMEM_ALLOCATOR_TO(PProfilerChild)

  void SetupChunkManager();
  void ResetChunkManager();
  void ResolveChunkUpdate(
      PProfilerChild::AwaitNextChunkManagerUpdateResolver& aResolve);
  void ProcessChunkManagerUpdate(
      ProfileBufferControlledChunkManager::Update&& aUpdate);

  nsCOMPtr mThread;
  bool mDestroyed;

  ProfileBufferControlledChunkManager* mChunkManager = nullptr;
  AwaitNextChunkManagerUpdateResolver mAwaitNextChunkManagerUpdateResolver;
  ProfileBufferControlledChunkManager::Update mChunkManagerUpdate;

  struct ProfilerChildAndUpdate {
    RefPtr mProfilerChild;
    ProfileBufferControlledChunkManager::Update mUpdate;
  };
  static DataMutexBase
      sPendingChunkManagerUpdate;
};

}  // namespace mozilla