Global Metrics

path: .metrics.halstead.N2
old: 186.0
new: 290.0

path: .metrics.halstead.estimated_program_length
old: 316.1839163704497
new: 746.3477154631084

path: .metrics.halstead.time
old: 3693.016598721668
new: 9945.521983479792

path: .metrics.halstead.bugs
old: 0.5469923532661695
new: 1.0587956210253442

path: .metrics.halstead.n1
old: 13.0
new: 26.0

path: .metrics.halstead.difficulty
old: 25.1875
new: 39.68421052631579

path: .metrics.halstead.length
old: 445.0
new: 652.0

path: .metrics.halstead.level
old: 0.03970223325062035
new: 0.02519893899204244

path: .metrics.halstead.volume
old: 2639.1781152154845
new: 4511.098830703036

path: .metrics.halstead.N1
old: 259.0
new: 362.0

path: .metrics.halstead.effort
old: 66474.29877699002
new: 179019.39570263625

path: .metrics.halstead.n2
old: 48.0
new: 95.0

path: .metrics.halstead.purity_ratio
old: 0.7105256547650555
new: 1.1447050850661171

path: .metrics.halstead.vocabulary
old: 61.0
new: 121.0

path: .metrics.loc.lloc
old: 5.0
new: 56.0

path: .metrics.loc.sloc
old: 158.0
new: 207.0

path: .metrics.loc.blank
old: 27.0
new: 37.0

path: .metrics.loc.ploc
old: 104.0
new: 134.0

path: .metrics.loc.cloc
old: 27.0
new: 36.0

path: .metrics.nargs.sum
old: 6.0
new: 18.0

path: .metrics.nargs.average
old: 0.5
new: 1.5

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

path: .metrics.cyclomatic.sum
old: 21.0
new: 33.0

path: .metrics.mi.mi_original
old: 43.18920176104744
new: 33.26561610994288

path: .metrics.mi.mi_visual_studio
old: 25.256843135115464
new: 19.45357667248122

path: .metrics.mi.mi_sei
old: 18.622475304416284
new: 5.753531510842887

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

path: .metrics.cognitive.sum
old: 0.0
new: 9.0

path: .metrics.nexits.sum
old: 5.0
new: 11.0

path: .metrics.nexits.average
old: 0.4166666666666667
new: 0.9166666666666666

Spaces Data

Minimal test - lines (33, 53)

path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 18.472850423126204
new: 53.62150385269314

path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 45.38810238831371
new: 89.42769789171422

path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 26.54274993468638
new: 52.29689935187966

path: .spaces[0].spaces[0].metrics.loc.lloc
old: 5.0
new: 7.0

path: .spaces[0].spaces[0].metrics.loc.blank
old: 26.0
new: 3.0

path: .spaces[0].spaces[0].metrics.loc.ploc
old: 98.0
new: 18.0

path: .spaces[0].spaces[0].metrics.loc.sloc
old: 143.0
new: 21.0

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

path: .spaces[0].spaces[0].metrics.nexits.average
old: 0.4166666666666667
new: 3.0

path: .spaces[0].spaces[0].metrics.nexits.sum
old: 5.0
new: 3.0

path: .spaces[0].spaces[0].metrics.cyclomatic.sum
old: 19.0
new: 3.0

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

path: .spaces[0].spaces[0].metrics.cognitive.average
old: 0.0
new: 2.0

path: .spaces[0].spaces[0].metrics.cognitive.sum
old: 0.0
new: 2.0

path: .spaces[0].spaces[0].metrics.nargs.sum
old: 6.0
new: 3.0

path: .spaces[0].spaces[0].metrics.nargs.average
old: 0.5
new: 3.0

path: .spaces[0].spaces[0].metrics.halstead.N2
old: 182.0
new: 34.0

path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 0.67099796743334
new: 1.6389880198771285

path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 26.288888888888888
new: 13.421052631578949

path: .spaces[0].spaces[0].metrics.halstead.length
old: 440.0
new: 85.0

path: .spaces[0].spaces[0].metrics.halstead.volume
old: 2577.5116378561315
new: 432.4343415062788

path: .spaces[0].spaces[0].metrics.halstead.effort
old: 67759.91705741786
new: 5803.724057057952

path: .spaces[0].spaces[0].metrics.halstead.time
old: 3764.439836523214
new: 322.42911428099734

path: .spaces[0].spaces[0].metrics.halstead.N1
old: 258.0
new: 51.0

path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.5540223976157168
new: 0.10765063158981984

path: .spaces[0].spaces[0].metrics.halstead.n1
old: 13.0
new: 15.0

path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 58.0
new: 34.0

path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.03803888419273035
new: 0.07450980392156863

path: .spaces[0].spaces[0].metrics.halstead.n2
old: 45.0
new: 19.0

path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 295.2391056706696
new: 139.3139816895559

path: .spaces[0].spaces[0].metrics.nom.functions
old: 12.0
new: 1.0

path: .spaces[0].spaces[0].metrics.nom.total
old: 12.0
new: 1.0

Code

static int32_t GetPathFromFd(int32_t aFd, char* aBuf, size_t aBufSize) {
#ifdef XP_MACOSX
  NS_ASSERTION(aBufSize >= MAXPATHLEN,
               "aBufSize should be a least MAXPATHLEN long");

  return fcntl(aFd, F_GETPATH, aBuf);
#else
  char procPath[32];
  if (PR_snprintf(procPath, sizeof(procPath), "/proc/self/fd/%i", aFd) ==
      (PRUint32)-1) {
    return -1;
  }

  int32_t ret = readlink(procPath, aBuf, aBufSize - 1);
  if (ret > -1) {
    aBuf[ret] = '\0';
  }

  return ret;
#endif
}

Minimal test - lines (23, 132)

path: .spaces[0].metrics.loc.lloc
old: 5.0
new: 24.0

path: .spaces[0].metrics.loc.ploc
old: 100.0
new: 77.0

path: .spaces[0].metrics.loc.cloc
old: 20.0
new: 11.0

path: .spaces[0].metrics.loc.sloc
old: 145.0
new: 110.0

path: .spaces[0].metrics.loc.blank
old: 25.0
new: 22.0

path: .spaces[0].metrics.nargs.sum
old: 6.0
new: 18.0

path: .spaces[0].metrics.nargs.average
old: 0.5
new: 1.8

path: .spaces[0].metrics.nexits.average
old: 0.4166666666666667
new: 0.9

path: .spaces[0].metrics.nexits.sum
old: 5.0
new: 9.0

path: .spaces[0].metrics.nom.total
old: 12.0
new: 10.0

path: .spaces[0].metrics.nom.functions
old: 12.0
new: 10.0

path: .spaces[0].metrics.mi.mi_original
old: 44.887669958624855
new: 49.795021505548235

path: .spaces[0].metrics.mi.mi_sei
old: 18.30143787298541
new: 21.395908323821786

path: .spaces[0].metrics.mi.mi_visual_studio
old: 26.25009939100869
new: 29.11989561727967

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

path: .spaces[0].metrics.cyclomatic.sum
old: 20.0
new: 17.0

path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 5.0

path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 0.5

path: .spaces[0].metrics.halstead.effort
old: 67235.92449977026
new: 77706.21435976328

path: .spaces[0].metrics.halstead.level
old: 0.03867171080285834
new: 0.035162746495604656

path: .spaces[0].metrics.halstead.purity_ratio
old: 0.683686801616418
new: 1.36121128996583

path: .spaces[0].metrics.halstead.time
old: 3735.329138876126
new: 4317.011908875738

path: .spaces[0].metrics.halstead.volume
old: 2600.1282278179337
new: 2732.3639166654707

path: .spaces[0].metrics.halstead.N1
old: 259.0
new: 231.0

path: .spaces[0].metrics.halstead.estimated_program_length
old: 302.1895663144568
new: 563.5414740458536

path: .spaces[0].metrics.halstead.n2
old: 46.0
new: 74.0

path: .spaces[0].metrics.halstead.vocabulary
old: 59.0
new: 97.0

path: .spaces[0].metrics.halstead.length
old: 442.0
new: 414.0

path: .spaces[0].metrics.halstead.bugs
old: 0.5511625056702443
new: 0.6069914585407531

path: .spaces[0].metrics.halstead.n1
old: 13.0
new: 23.0

path: .spaces[0].metrics.halstead.difficulty
old: 25.85869565217391
new: 28.43918918918919

Code

namespace {

/* Original IO methods */
PRCloseFN sCloseFn = nullptr;
PRReadFN sReadFn = nullptr;
PRWriteFN sWriteFn = nullptr;
PRFsyncFN sFSyncFn = nullptr;
PRFileInfoFN sFileInfoFn = nullptr;
PRFileInfo64FN sFileInfo64Fn = nullptr;

static int32_t GetPathFromFd(int32_t aFd, char* aBuf, size_t aBufSize) {
#ifdef XP_MACOSX
  NS_ASSERTION(aBufSize >= MAXPATHLEN,
               "aBufSize should be a least MAXPATHLEN long");

  return fcntl(aFd, F_GETPATH, aBuf);
#else
  char procPath[32];
  if (PR_snprintf(procPath, sizeof(procPath), "/proc/self/fd/%i", aFd) ==
      (PRUint32)-1) {
    return -1;
  }

  int32_t ret = readlink(procPath, aBuf, aBufSize - 1);
  if (ret > -1) {
    aBuf[ret] = '\0';
  }

  return ret;
#endif
}

/**
 * RAII class for timing the duration of an NSPR I/O call and reporting the
 * result to the mozilla::IOInterposeObserver API.
 */
class NSPRIOAutoObservation : public mozilla::IOInterposeObserver::Observation {
 public:
  explicit NSPRIOAutoObservation(mozilla::IOInterposeObserver::Operation aOp,
                                 PRFileDesc* aFd)
      : mozilla::IOInterposeObserver::Observation(aOp, "NSPRIOInterposer") {
    char filename[MAXPATHLEN];
    if (mShouldReport && aFd &&
        GetPathFromFd(PR_FileDesc2NativeHandle(aFd), filename,
                      sizeof(filename)) != -1) {
      CopyUTF8toUTF16(mozilla::MakeStringSpan(filename), mFilename);
    } else {
      mFilename.Truncate();
    }
  }

  void Filename(nsAString& aFilename) override { aFilename = mFilename; }

  ~NSPRIOAutoObservation() override { Report(); }

 private:
  nsString mFilename;
};

PRStatus PR_CALLBACK interposedClose(PRFileDesc* aFd) {
  // If we don't have a valid original function pointer something is very wrong.
  NS_ASSERTION(sCloseFn, "NSPR IO Interposing: sCloseFn is NULL");

  NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpClose, aFd);
  return sCloseFn(aFd);
}

int32_t PR_CALLBACK interposedRead(PRFileDesc* aFd, void* aBuf, int32_t aAmt) {
  // If we don't have a valid original function pointer something is very wrong.
  NS_ASSERTION(sReadFn, "NSPR IO Interposing: sReadFn is NULL");

  NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpRead, aFd);
  return sReadFn(aFd, aBuf, aAmt);
}

int32_t PR_CALLBACK interposedWrite(PRFileDesc* aFd, const void* aBuf,
                                    int32_t aAmt) {
  // If we don't have a valid original function pointer something is very wrong.
  NS_ASSERTION(sWriteFn, "NSPR IO Interposing: sWriteFn is NULL");

  NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpWrite, aFd);
  return sWriteFn(aFd, aBuf, aAmt);
}

PRStatus PR_CALLBACK interposedFSync(PRFileDesc* aFd) {
  // If we don't have a valid original function pointer something is very wrong.
  NS_ASSERTION(sFSyncFn, "NSPR IO Interposing: sFSyncFn is NULL");

  NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpFSync, aFd);
  return sFSyncFn(aFd);
}

PRStatus PR_CALLBACK interposedFileInfo(PRFileDesc* aFd, PRFileInfo* aInfo) {
  // If we don't have a valid original function pointer something is very wrong.
  NS_ASSERTION(sFileInfoFn, "NSPR IO Interposing: sFileInfoFn is NULL");

  NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpStat, aFd);
  return sFileInfoFn(aFd, aInfo);
}

PRStatus PR_CALLBACK interposedFileInfo64(PRFileDesc* aFd,
                                          PRFileInfo64* aInfo) {
  // If we don't have a valid original function pointer something is very wrong.
  NS_ASSERTION(sFileInfo64Fn, "NSPR IO Interposing: sFileInfo64Fn is NULL");

  NSPRIOAutoObservation timer(mozilla::IOInterposeObserver::OpStat, aFd);
  return sFileInfo64Fn(aFd, aInfo);
}

}  // namespace