Global Metrics
path: .metrics.loc.lloc
old: 230.0
new: 52.0
path: .metrics.loc.sloc
old: 515.0
new: 224.0
path: .metrics.loc.ploc
old: 388.0
new: 170.0
path: .metrics.loc.blank
old: 72.0
new: 25.0
path: .metrics.loc.cloc
old: 55.0
new: 29.0
path: .metrics.nargs.sum
old: 34.0
new: 6.0
path: .metrics.nargs.average
old: 1.4782608695652173
new: 0.75
path: .metrics.cognitive.sum
old: 196.0
new: 30.0
path: .metrics.cognitive.average
old: 8.521739130434783
new: 3.75
path: .metrics.halstead.estimated_program_length
old: 1644.403252118508
new: 886.8310173464122
path: .metrics.halstead.bugs
old: 4.417962851769083
new: 0.9253160538109342
path: .metrics.halstead.purity_ratio
old: 0.7508690648942958
new: 1.4054374284412237
path: .metrics.halstead.level
old: 0.011251258364422336
new: 0.030713388245148677
path: .metrics.halstead.N1
old: 1324.0
new: 384.0
path: .metrics.halstead.N2
old: 866.0
new: 247.0
path: .metrics.halstead.difficulty
old: 88.87894736842105
new: 32.55909090909091
path: .metrics.halstead.effort
old: 1525860.9961547835
new: 146257.12347442078
path: .metrics.halstead.length
old: 2190.0
new: 631.0
path: .metrics.halstead.n1
old: 39.0
new: 29.0
path: .metrics.halstead.time
old: 84770.05534193241
new: 8125.395748578932
path: .metrics.halstead.n2
old: 190.0
new: 110.0
path: .metrics.halstead.vocabulary
old: 229.0
new: 139.0
path: .metrics.halstead.volume
old: 17167.856295932306
new: 4492.051816888534
path: .metrics.nom.functions
old: 23.0
new: 8.0
path: .metrics.nom.total
old: 23.0
new: 8.0
path: .metrics.nexits.average
old: 3.0869565217391304
new: 1.25
path: .metrics.nexits.sum
old: 71.0
new: 10.0
path: .metrics.mi.mi_visual_studio
old: 0.0
new: 18.853214464268703
path: .metrics.mi.mi_sei
old: -56.0411544625703
new: 0.5182444800644106
path: .metrics.mi.mi_original
old: -13.0596330815017
new: 32.238996733899484
path: .metrics.cyclomatic.average
old: 4.827586206896552
new: 2.2857142857142856
path: .metrics.cyclomatic.sum
old: 140.0
new: 32.0
Spaces Data
Minimal test - lines (30, 51)
path: .spaces[0].spaces[0].metrics.loc.lloc
old: 0.0
new: 1.0
path: .spaces[0].spaces[0].metrics.loc.sloc
old: 7.0
new: 22.0
path: .spaces[0].spaces[0].metrics.loc.ploc
old: 6.0
new: 21.0
path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 16.0
new: 20.0
path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 5.444444444444445
new: 9.0
path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.025097778938159565
new: 0.046968253716542153
path: .spaces[0].spaces[0].metrics.halstead.effort
old: 653.3333333333334
new: 1672.5861727214094
path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 1.6060269822461346
new: 1.5484435539067694
path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.18367346938775508
new: 0.1111111111111111
path: .spaces[0].spaces[0].metrics.halstead.volume
old: 120.0
new: 185.8429080801566
path: .spaces[0].spaces[0].metrics.halstead.n1
old: 7.0
new: 9.0
path: .spaces[0].spaces[0].metrics.halstead.n2
old: 9.0
new: 11.0
path: .spaces[0].spaces[0].metrics.halstead.N1
old: 16.0
new: 21.0
path: .spaces[0].spaces[0].metrics.halstead.length
old: 30.0
new: 43.0
path: .spaces[0].spaces[0].metrics.halstead.N2
old: 14.0
new: 22.0
path: .spaces[0].spaces[0].metrics.halstead.time
old: 36.2962962962963
new: 92.9214540400783
path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 48.18080946738404
new: 66.58307281799108
path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 89.1450191655025
new: 59.09992069024463
path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 114.1212985228373
new: 93.29562322506636
path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 66.73760147534345
new: 54.55884399126688
path: .spaces[0].spaces[0].metrics.nargs.sum
old: 0.0
new: 4.0
path: .spaces[0].spaces[0].metrics.nargs.average
old: 0.0
new: 4.0
Code
struct ObservationWithStack {
explicit ObservationWithStack(mozilla::IOInterposeObserver::Observation& aObs
#ifdef MOZ_GECKO_PROFILER
,
ProfilerBacktrace* aStack
#endif
)
: mObservation(aObs)
#ifdef MOZ_GECKO_PROFILER
,
mStack(aStack)
#endif
{
aObs.Filename(mFilename);
}
mozilla::IOInterposeObserver::Observation mObservation;
#ifdef MOZ_GECKO_PROFILER
ProfilerBacktrace* mStack;
#endif
nsString mFilename;
};
Minimal test - lines (31, 44)
path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 87.97970938710789
new: 60.332377463615366
path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_sei
old: 141.4476605054837
new: 73.24145709716794
path: .spaces[0].spaces[0].spaces[0].metrics.mi.mi_original
old: 150.44530305195448
new: 103.16836546278228
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.length
old: 15.0
new: 28.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.n2
old: 6.0
new: 10.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.volume
old: 49.82892142331043
new: 118.9419703764204
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.difficulty
old: 2.3333333333333335
new: 6.3
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.level
old: 0.42857142857142855
new: 0.15873015873015872
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.vocabulary
old: 10.0
new: 19.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N1
old: 8.0
new: 14.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.N2
old: 7.0
new: 14.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 1.5673183336217955
new: 2.2053073557805156
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.bugs
old: 0.007940556250510787
new: 0.027499778601425103
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.effort
old: 116.26748332105768
new: 749.3344133714484
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.time
old: 6.459304628947649
new: 41.629689631747134
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.n1
old: 4.0
new: 9.0
path: .spaces[0].spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 23.509775004326936
new: 61.74860596185444
path: .spaces[0].spaces[0].spaces[0].metrics.loc.sloc
old: 1.0
new: 14.0
path: .spaces[0].spaces[0].spaces[0].metrics.loc.ploc
old: 1.0
new: 14.0
path: .spaces[0].spaces[0].spaces[0].metrics.loc.lloc
old: 0.0
new: 1.0
path: .spaces[0].spaces[0].spaces[0].metrics.nargs.average
old: 0.0
new: 4.0
path: .spaces[0].spaces[0].spaces[0].metrics.nargs.sum
old: 0.0
new: 4.0
Code
explicit ObservationWithStack(mozilla::IOInterposeObserver::Observation& aObs
#ifdef MOZ_GECKO_PROFILER
,
ProfilerBacktrace* aStack
#endif
)
: mObservation(aObs)
#ifdef MOZ_GECKO_PROFILER
,
mStack(aStack)
#endif
{
aObs.Filename(mFilename);
}
Minimal test - lines (28, 206)
path: .spaces[0].metrics.cognitive.sum
old: 0.0
new: 29.0
path: .spaces[0].metrics.cognitive.average
old: 0.0
new: 4.142857142857143
path: .spaces[0].metrics.cyclomatic.sum
old: 3.0
new: 27.0
path: .spaces[0].metrics.cyclomatic.average
old: 1.0
new: 2.7
path: .spaces[0].metrics.mi.mi_visual_studio
old: 55.13610199277192
new: 21.99866503267546
path: .spaces[0].metrics.mi.mi_original
old: 94.28273440763998
new: 37.61771720587504
path: .spaces[0].metrics.mi.mi_sei
old: 78.02454794791635
new: 4.293782376696974
path: .spaces[0].metrics.nom.total
old: 1.0
new: 7.0
path: .spaces[0].metrics.nom.functions
old: 1.0
new: 7.0
path: .spaces[0].metrics.loc.ploc
old: 15.0
new: 144.0
path: .spaces[0].metrics.loc.lloc
old: 0.0
new: 47.0
path: .spaces[0].metrics.loc.blank
old: 3.0
new: 18.0
path: .spaces[0].metrics.loc.cloc
old: 1.0
new: 17.0
path: .spaces[0].metrics.loc.sloc
old: 19.0
new: 179.0
path: .spaces[0].metrics.nexits.sum
old: 0.0
new: 8.0
path: .spaces[0].metrics.nexits.average
old: 0.0
new: 1.1428571428571428
path: .spaces[0].metrics.nargs.sum
old: 0.0
new: 6.0
path: .spaces[0].metrics.nargs.average
old: 0.0
new: 0.8571428571428571
path: .spaces[0].metrics.halstead.purity_ratio
old: 1.8697373660251153
new: 1.3119805908429767
path: .spaces[0].metrics.halstead.N1
old: 27.0
new: 355.0
path: .spaces[0].metrics.halstead.n2
old: 17.0
new: 94.0
path: .spaces[0].metrics.halstead.difficulty
old: 5.411764705882353
new: 34.244680851063826
path: .spaces[0].metrics.halstead.effort
old: 1256.572851350808
new: 137178.39967213196
path: .spaces[0].metrics.halstead.length
old: 50.0
new: 577.0
path: .spaces[0].metrics.halstead.N2
old: 23.0
new: 222.0
path: .spaces[0].metrics.halstead.bugs
old: 0.0388153816076943
new: 0.8866166851526256
path: .spaces[0].metrics.halstead.level
old: 0.18478260869565216
new: 0.029201615408511964
path: .spaces[0].metrics.halstead.estimated_program_length
old: 93.48686830125575
new: 757.0128009163975
path: .spaces[0].metrics.halstead.vocabulary
old: 25.0
new: 123.0
path: .spaces[0].metrics.halstead.n1
old: 8.0
new: 29.0
path: .spaces[0].metrics.halstead.volume
old: 232.19280948873623
new: 4005.830869580742
path: .spaces[0].metrics.halstead.time
old: 69.80960285282266
new: 7621.022204007331
Code
namespace {
struct ObservationWithStack {
explicit ObservationWithStack(mozilla::IOInterposeObserver::Observation& aObs
#ifdef MOZ_GECKO_PROFILER
,
ProfilerBacktrace* aStack
#endif
)
: mObservation(aObs)
#ifdef MOZ_GECKO_PROFILER
,
mStack(aStack)
#endif
{
aObs.Filename(mFilename);
}
mozilla::IOInterposeObserver::Observation mObservation;
#ifdef MOZ_GECKO_PROFILER
ProfilerBacktrace* mStack;
#endif
nsString mFilename;
};
class MainThreadIOLoggerImpl final : public mozilla::IOInterposeObserver {
public:
MainThreadIOLoggerImpl();
~MainThreadIOLoggerImpl();
bool Init();
void Observe(Observation& aObservation) override;
private:
static void sIOThreadFunc(void* aArg);
void IOThreadFunc();
mozilla::TimeStamp mLogStartTime;
const char* mFileName;
PRThread* mIOThread;
mozilla::IOInterposer::Monitor mMonitor;
bool mShutdownRequired;
std::vector mObservations;
};
static mozilla::StaticAutoPtr sImpl;
MainThreadIOLoggerImpl::MainThreadIOLoggerImpl()
: mFileName(nullptr), mIOThread(nullptr), mShutdownRequired(false) {}
MainThreadIOLoggerImpl::~MainThreadIOLoggerImpl() {
if (!mIOThread) {
return;
}
{
// Scope for lock
mozilla::IOInterposer::MonitorAutoLock lock(mMonitor);
mShutdownRequired = true;
lock.Notify();
}
PR_JoinThread(mIOThread);
mIOThread = nullptr;
}
bool MainThreadIOLoggerImpl::Init() {
if (mFileName) {
// Already initialized
return true;
}
mFileName = PR_GetEnv("MOZ_MAIN_THREAD_IO_LOG");
if (!mFileName) {
// Can't start
return false;
}
mIOThread =
PR_CreateThread(PR_USER_THREAD, &sIOThreadFunc, this, PR_PRIORITY_LOW,
PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0);
if (!mIOThread) {
return false;
}
return true;
}
/* static */
void MainThreadIOLoggerImpl::sIOThreadFunc(void* aArg) {
AUTO_PROFILER_REGISTER_THREAD("MainThreadIOLogger");
NS_SetCurrentThreadName("MainThreadIOLogger");
MainThreadIOLoggerImpl* obj = static_cast(aArg);
obj->IOThreadFunc();
}
void MainThreadIOLoggerImpl::IOThreadFunc() {
PRFileDesc* fd = PR_Open(mFileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
PR_IRUSR | PR_IWUSR | PR_IRGRP);
if (!fd) {
mozilla::IOInterposer::MonitorAutoLock lock(mMonitor);
mShutdownRequired = true;
std::vector().swap(mObservations);
return;
}
mLogStartTime = mozilla::TimeStamp::Now();
{
// Scope for lock
mozilla::IOInterposer::MonitorAutoLock lock(mMonitor);
while (true) {
while (!mShutdownRequired && mObservations.empty()) {
lock.Wait();
}
if (mShutdownRequired) {
break;
}
// Pull events off the shared array onto a local one
std::vector observationsToWrite;
observationsToWrite.swap(mObservations);
// Release the lock so that we're not holding anybody up during I/O
mozilla::IOInterposer::MonitorAutoUnlock unlock(mMonitor);
// Now write the events.
for (auto i = observationsToWrite.begin(), e = observationsToWrite.end();
i != e; ++i) {
if (i->mObservation.ObservedOperation() == OpNextStage) {
PR_fprintf(
fd, "%f,NEXT-STAGE\n",
(mozilla::TimeStamp::Now() - mLogStartTime).ToMilliseconds());
continue;
}
double durationMs = i->mObservation.Duration().ToMilliseconds();
nsAutoCString nativeFilename;
nativeFilename.AssignLiteral("(not available)");
if (!i->mFilename.IsEmpty()) {
if (NS_FAILED(NS_CopyUnicodeToNative(i->mFilename, nativeFilename))) {
nativeFilename.AssignLiteral("(conversion failed)");
}
}
// clang-format off
/**
* Format:
* Start Timestamp (Milliseconds), Operation, Duration (Milliseconds), Event Source, Filename
*/
// clang-format on
if (PR_fprintf(
fd, "%f,%s,%f,%s,%s\n",
(i->mObservation.Start() - mLogStartTime).ToMilliseconds(),
i->mObservation.ObservedOperationString(), durationMs,
i->mObservation.Reference(), nativeFilename.get()) > 0) {
#ifdef MOZ_GECKO_PROFILER
// TODO: Write out the callstack
i->mStack = nullptr;
#endif
}
}
}
}
PR_Close(fd);
}
void MainThreadIOLoggerImpl::Observe(Observation& aObservation) {
if (!mFileName || !IsMainThread()) {
return;
}
mozilla::IOInterposer::MonitorAutoLock lock(mMonitor);
if (mShutdownRequired) {
// The writer thread isn't running. Don't enqueue any more data.
return;
}
// Passing nullptr as aStack parameter for now
mObservations.push_back(ObservationWithStack(aObservation
#ifdef MOZ_GECKO_PROFILER
,
nullptr
#endif
));
lock.Notify();
}
} // namespace
Minimal test - lines (208, 224)
path: .spaces[1].metrics.cognitive.sum
old: 119.0
new: 1.0
path: .spaces[1].metrics.cognitive.average
old: 13.22222222222222
new: 1.0
path: .spaces[1].metrics.mi.mi_original
old: 19.72034018044529
new: 96.33948736024982
path: .spaces[1].metrics.mi.mi_sei
old: -18.2437887787733
new: 82.04272597782098
path: .spaces[1].metrics.mi.mi_visual_studio
old: 11.532362678622976
new: 56.33888149722212
path: .spaces[1].metrics.nargs.sum
old: 19.0
new: 0.0
path: .spaces[1].metrics.nargs.average
old: 2.111111111111111
new: 0.0
path: .spaces[1].metrics.cyclomatic.average
old: 7.0
new: 1.3333333333333333
path: .spaces[1].metrics.cyclomatic.sum
old: 70.0
new: 4.0
path: .spaces[1].metrics.halstead.n2
old: 105.0
new: 12.0
path: .spaces[1].metrics.halstead.length
old: 1139.0
new: 45.0
path: .spaces[1].metrics.halstead.purity_ratio
old: 0.7708248603665095
new: 2.1405004203880074
path: .spaces[1].metrics.halstead.N1
old: 683.0
new: 29.0
path: .spaces[1].metrics.halstead.difficulty
old: 73.82857142857142
new: 9.333333333333334
path: .spaces[1].metrics.halstead.estimated_program_length
old: 877.9695159574544
new: 96.32251891746031
path: .spaces[1].metrics.halstead.n1
old: 34.0
new: 14.0
path: .spaces[1].metrics.halstead.time
old: 33257.61350897473
new: 109.67692675662548
path: .spaces[1].metrics.halstead.effort
old: 598637.0431615452
new: 1974.1846816192583
path: .spaces[1].metrics.halstead.level
old: 0.013544891640866877
new: 0.10714285714285714
path: .spaces[1].metrics.halstead.volume
old: 8108.473881832075
new: 211.51978731634912
path: .spaces[1].metrics.halstead.bugs
old: 2.367669810907326
new: 0.0524570580560377
path: .spaces[1].metrics.halstead.N2
old: 456.0
new: 16.0
path: .spaces[1].metrics.halstead.vocabulary
old: 139.0
new: 26.0
path: .spaces[1].metrics.nexits.average
old: 3.7777777777777777
new: 2.0
path: .spaces[1].metrics.nexits.sum
old: 34.0
new: 2.0
path: .spaces[1].metrics.nom.functions
old: 9.0
new: 1.0
path: .spaces[1].metrics.nom.total
old: 9.0
new: 1.0
path: .spaces[1].metrics.loc.sloc
old: 234.0
new: 17.0
path: .spaces[1].metrics.loc.blank
old: 26.0
new: 3.0
path: .spaces[1].metrics.loc.cloc
old: 20.0
new: 1.0
path: .spaces[1].metrics.loc.lloc
old: 119.0
new: 5.0
path: .spaces[1].metrics.loc.ploc
old: 188.0
new: 13.0
Code
namespace mozilla {
namespace MainThreadIOLogger {
bool Init() {
auto impl = MakeUnique();
if (!impl->Init()) {
return false;
}
sImpl = impl.release();
IOInterposer::Register(IOInterposeObserver::OpAllWithStaging, sImpl);
return true;
}
} // namespace MainThreadIOLogger
} // namespace mozilla
Minimal test - lines (210, 222)
path: .spaces[1].spaces[0].metrics.cyclomatic.sum
old: 2.0
new: 3.0
path: .spaces[1].spaces[0].metrics.cyclomatic.average
old: 2.0
new: 1.5
path: .spaces[1].spaces[0].metrics.loc.sloc
old: 3.0
new: 13.0
path: .spaces[1].spaces[0].metrics.loc.lloc
old: 2.0
new: 5.0
path: .spaces[1].spaces[0].metrics.loc.blank
old: 0.0
new: 2.0
path: .spaces[1].spaces[0].metrics.loc.ploc
old: 3.0
new: 11.0
path: .spaces[1].spaces[0].metrics.halstead.level
old: 0.1111111111111111
new: 0.10476190476190476
path: .spaces[1].spaces[0].metrics.halstead.length
old: 25.0
new: 43.0
path: .spaces[1].spaces[0].metrics.halstead.purity_ratio
old: 1.6055586194967049
new: 2.1245748072980635
path: .spaces[1].spaces[0].metrics.halstead.N2
old: 10.0
new: 15.0
path: .spaces[1].spaces[0].metrics.halstead.vocabulary
old: 14.0
new: 25.0
path: .spaces[1].spaces[0].metrics.halstead.difficulty
old: 9.0
new: 9.545454545454543
path: .spaces[1].spaces[0].metrics.halstead.time
old: 47.59193652572005
new: 105.89399341834788
path: .spaces[1].spaces[0].metrics.halstead.volume
old: 95.1838730514401
new: 199.68581616031315
path: .spaces[1].spaces[0].metrics.halstead.N1
old: 15.0
new: 28.0
path: .spaces[1].spaces[0].metrics.halstead.effort
old: 856.6548574629609
new: 1906.0918815302616
path: .spaces[1].spaces[0].metrics.halstead.estimated_program_length
old: 40.13896548741762
new: 91.35671671381672
path: .spaces[1].spaces[0].metrics.halstead.n1
old: 9.0
new: 14.0
path: .spaces[1].spaces[0].metrics.halstead.bugs
old: 0.030066485534799937
new: 0.05124379671641141
path: .spaces[1].spaces[0].metrics.halstead.n2
old: 5.0
new: 11.0
path: .spaces[1].spaces[0].metrics.mi.mi_sei
old: 110.6858521667939
new: 70.62661870383211
path: .spaces[1].spaces[0].metrics.mi.mi_visual_studio
old: 75.46916151145908
new: 59.1899095356019
path: .spaces[1].spaces[0].metrics.mi.mi_original
old: 129.05226618459503
new: 101.21474530587923
path: .spaces[1].spaces[0].metrics.nexits.sum
old: 0.0
new: 2.0
path: .spaces[1].spaces[0].metrics.nexits.average
old: 0.0
new: 2.0
Code
namespace MainThreadIOLogger {
bool Init() {
auto impl = MakeUnique();
if (!impl->Init()) {
return false;
}
sImpl = impl.release();
IOInterposer::Register(IOInterposeObserver::OpAllWithStaging, sImpl);
return true;
}
} // namespace MainThreadIOLogger