Global Metrics
path: .metrics.nargs.sum
old: 8.0
new: 13.0
path: .metrics.nargs.average
old: 0.8888888888888888
new: 0.52
path: .metrics.mi.mi_sei
old: 19.00998817955523
new: -24.20339226551669
path: .metrics.mi.mi_original
old: 38.381766447533096
new: 12.126494475652976
path: .metrics.mi.mi_visual_studio
old: 22.445477454697716
new: 7.091517237223963
path: .metrics.cyclomatic.sum
old: 31.0
new: 62.0
path: .metrics.cyclomatic.average
old: 2.5833333333333335
new: 1.8235294117647056
path: .metrics.nom.total
old: 9.0
new: 25.0
path: .metrics.nom.closures
old: 1.0
new: 0.0
path: .metrics.nom.functions
old: 8.0
new: 25.0
path: .metrics.cognitive.average
old: 2.888888888888889
new: 1.36
path: .metrics.cognitive.sum
old: 26.0
new: 34.0
path: .metrics.nexits.average
old: 0.7777777777777778
new: 0.52
path: .metrics.nexits.sum
old: 7.0
new: 13.0
path: .metrics.halstead.n2
old: 85.0
new: 180.0
path: .metrics.halstead.N2
old: 168.0
new: 395.0
path: .metrics.halstead.estimated_program_length
old: 685.6796784304042
new: 1502.1136429613348
path: .metrics.halstead.difficulty
old: 28.65882352941177
new: 34.013888888888886
path: .metrics.halstead.n1
old: 29.0
new: 31.0
path: .metrics.halstead.purity_ratio
old: 1.5339590121485551
new: 1.4961291264555128
path: .metrics.halstead.volume
old: 3054.301836331639
new: 7751.983585462014
path: .metrics.halstead.length
old: 447.0
new: 1004.0
path: .metrics.halstead.time
old: 4862.927629610374
new: 14648.617130244187
path: .metrics.halstead.bugs
old: 0.6571415880758816
new: 1.3706445199274797
path: .metrics.halstead.N1
old: 279.0
new: 609.0
path: .metrics.halstead.effort
old: 87532.69733298675
new: 263675.1083443954
path: .metrics.halstead.level
old: 0.03489326765188834
new: 0.02939975500204165
path: .metrics.halstead.vocabulary
old: 114.0
new: 211.0
path: .metrics.loc.sloc
old: 176.0
new: 425.0
path: .metrics.loc.blank
old: 11.0
new: 72.0
path: .metrics.loc.ploc
old: 117.0
new: 292.0
path: .metrics.loc.cloc
old: 48.0
new: 61.0
path: .metrics.loc.lloc
old: 52.0
new: 76.0
Spaces Data
Minimal test - lines (172, 176)
path: .spaces[0].spaces[7].metrics.cyclomatic.sum
old: 3.0
new: 2.0
path: .spaces[0].spaces[7].metrics.cyclomatic.average
old: 3.0
new: 2.0
path: .spaces[0].spaces[7].metrics.loc.sloc
old: 10.0
new: 5.0
path: .spaces[0].spaces[7].metrics.loc.lloc
old: 3.0
new: 1.0
path: .spaces[0].spaces[7].metrics.loc.ploc
old: 10.0
new: 5.0
path: .spaces[0].spaces[7].metrics.nargs.average
old: 5.0
new: 0.0
path: .spaces[0].spaces[7].metrics.nargs.sum
old: 5.0
new: 0.0
path: .spaces[0].spaces[7].metrics.cognitive.average
old: 1.0
new: 0.0
path: .spaces[0].spaces[7].metrics.cognitive.sum
old: 1.0
new: 0.0
path: .spaces[0].spaces[7].metrics.halstead.n1
old: 10.0
new: 8.0
path: .spaces[0].spaces[7].metrics.halstead.estimated_program_length
old: 76.2388309575275
new: 43.65148445440323
path: .spaces[0].spaces[7].metrics.halstead.purity_ratio
old: 1.5558945093372958
new: 2.297446550231749
path: .spaces[0].spaces[7].metrics.halstead.volume
old: 218.5121493132276
new: 74.23092131656186
path: .spaces[0].spaces[7].metrics.halstead.n2
old: 12.0
new: 7.0
path: .spaces[0].spaces[7].metrics.halstead.time
old: 96.10488048498436
new: 18.85229747722206
path: .spaces[0].spaces[7].metrics.halstead.N1
old: 30.0
new: 11.0
path: .spaces[0].spaces[7].metrics.halstead.length
old: 49.0
new: 19.0
path: .spaces[0].spaces[7].metrics.halstead.difficulty
old: 7.916666666666667
new: 4.571428571428571
path: .spaces[0].spaces[7].metrics.halstead.effort
old: 1729.8878487297184
new: 339.3413545899971
path: .spaces[0].spaces[7].metrics.halstead.vocabulary
old: 22.0
new: 15.0
path: .spaces[0].spaces[7].metrics.halstead.N2
old: 19.0
new: 8.0
path: .spaces[0].spaces[7].metrics.halstead.level
old: 0.1263157894736842
new: 0.21875
path: .spaces[0].spaces[7].metrics.halstead.bugs
old: 0.04803495379905817
new: 0.016216978391790506
path: .spaces[0].spaces[7].metrics.mi.mi_sei
old: 76.08260249653999
new: 100.61223333965796
path: .spaces[0].spaces[7].metrics.mi.mi_visual_studio
old: 61.401488356125995
new: 71.38582789270771
path: .spaces[0].spaces[7].metrics.mi.mi_original
old: 104.99654508897544
new: 122.06976569653015
Code
void nsAvailableMemoryWatcher::SendMemoryPressureEvent() {
MemoryPressureState state =
OngoingMemoryPressure() ? MemPressure_Ongoing : MemPressure_New;
NS_DispatchEventualMemoryPressure(state);
}
Minimal test - lines (92, 92)
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.bugs
old: 0.006944786620971931
new: 0.0017471609294725976
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.level
old: 0.4
new: 0.6666666666666666
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.vocabulary
old: 9.0
new: 4.0
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.volume
old: 38.039100017307746
new: 8.0
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.time
old: 5.2832083357371875
new: 0.6666666666666666
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.difficulty
old: 2.5
new: 1.5
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.length
old: 12.0
new: 4.0
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.estimated_program_length
old: 19.60964047443681
new: 4.754887502163468
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.n2
old: 4.0
new: 1.0
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.N1
old: 8.0
new: 3.0
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.effort
old: 95.09775004326936
new: 12.0
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.purity_ratio
old: 1.6341367062030674
new: 1.188721875540867
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.N2
old: 4.0
new: 1.0
path: .spaces[0].spaces[1].spaces[0].metrics.halstead.n1
old: 5.0
new: 3.0
path: .spaces[0].spaces[1].spaces[0].metrics.loc.ploc
old: 4.0
new: 1.0
path: .spaces[0].spaces[1].spaces[0].metrics.loc.cloc
old: 2.0
new: 0.0
path: .spaces[0].spaces[1].spaces[0].metrics.loc.sloc
old: 6.0
new: 1.0
path: .spaces[0].spaces[1].spaces[0].metrics.loc.lloc
old: 2.0
new: 0.0
path: .spaces[0].spaces[1].spaces[0].metrics.mi.mi_original
old: 122.82270079006472
new: 159.95690398326485
path: .spaces[0].spaces[1].spaces[0].metrics.mi.mi_visual_studio
old: 71.82614081290335
new: 93.54204911302038
path: .spaces[0].spaces[1].spaces[0].metrics.mi.mi_sei
old: 140.5892017250539
new: 155.17000000000002
Code
~nsAvailableMemoryWatcher(){};
Minimal test - lines (133, 145)
path: .spaces[0].spaces[4].metrics.loc.ploc
old: 43.0
new: 11.0
path: .spaces[0].spaces[4].metrics.loc.sloc
old: 58.0
new: 13.0
path: .spaces[0].spaces[4].metrics.loc.blank
old: 0.0
new: 2.0
path: .spaces[0].spaces[4].metrics.loc.cloc
old: 15.0
new: 0.0
path: .spaces[0].spaces[4].metrics.loc.lloc
old: 26.0
new: 5.0
path: .spaces[0].spaces[4].metrics.halstead.N1
old: 101.0
new: 29.0
path: .spaces[0].spaces[4].metrics.halstead.purity_ratio
old: 1.775526754090705
new: 2.157631600949801
path: .spaces[0].spaces[4].metrics.halstead.time
old: 827.3113510662622
new: 120.33522986244468
path: .spaces[0].spaces[4].metrics.halstead.length
old: 161.0
new: 47.0
path: .spaces[0].spaces[4].metrics.halstead.N2
old: 60.0
new: 18.0
path: .spaces[0].spaces[4].metrics.halstead.level
old: 0.06333333333333334
new: 0.10317460317460318
path: .spaces[0].spaces[4].metrics.halstead.difficulty
old: 15.789473684210526
new: 9.692307692307692
path: .spaces[0].spaces[4].metrics.halstead.n1
old: 20.0
new: 14.0
path: .spaces[0].spaces[4].metrics.halstead.vocabulary
old: 58.0
new: 27.0
path: .spaces[0].spaces[4].metrics.halstead.estimated_program_length
old: 285.8598074086035
new: 101.40868524464064
path: .spaces[0].spaces[4].metrics.halstead.volume
old: 943.134940215539
new: 223.47971260168305
path: .spaces[0].spaces[4].metrics.halstead.bugs
old: 0.2017621687013634
new: 0.05580275104439644
path: .spaces[0].spaces[4].metrics.halstead.n2
old: 38.0
new: 13.0
path: .spaces[0].spaces[4].metrics.halstead.effort
old: 14891.60431919272
new: 2166.034137524005
path: .spaces[0].spaces[4].metrics.cyclomatic.average
old: 8.0
new: 3.0
path: .spaces[0].spaces[4].metrics.cyclomatic.sum
old: 8.0
new: 3.0
path: .spaces[0].spaces[4].metrics.cognitive.average
old: 5.0
new: 1.0
path: .spaces[0].spaces[4].metrics.cognitive.sum
old: 10.0
new: 1.0
path: .spaces[0].spaces[4].metrics.nexits.average
old: 2.5
new: 0.0
path: .spaces[0].spaces[4].metrics.nexits.sum
old: 5.0
new: 0.0
path: .spaces[0].spaces[4].metrics.mi.mi_sei
old: 58.31935790013438
new: 69.78207625488035
path: .spaces[0].spaces[4].metrics.mi.mi_visual_studio
old: 39.62861667233742
new: 58.847574905570255
path: .spaces[0].spaces[4].metrics.mi.mi_original
old: 67.76493450969699
new: 100.62935308852514
path: .spaces[0].spaces[4].metrics.nom.total
old: 2.0
new: 1.0
path: .spaces[0].spaces[4].metrics.nom.closures
old: 1.0
new: 0.0
Code
void nsAvailableMemoryWatcher::Shutdown() {
nsCOMPtr observerService = services::GetObserverService();
MOZ_ASSERT(observerService);
for (auto topic : kObserverTopics) {
Unused << observerService->RemoveObserver(this, topic);
}
if (mTimer) {
mTimer->Cancel();
mTimer = nullptr;
}
}
Minimal test - lines (159, 170)
path: .spaces[0].spaces[6].metrics.loc.blank
old: 0.0
new: 1.0
path: .spaces[0].spaces[6].metrics.loc.ploc
old: 10.0
new: 11.0
path: .spaces[0].spaces[6].metrics.loc.lloc
old: 4.0
new: 5.0
path: .spaces[0].spaces[6].metrics.loc.sloc
old: 10.0
new: 12.0
path: .spaces[0].spaces[6].metrics.cyclomatic.sum
old: 2.0
new: 3.0
path: .spaces[0].spaces[6].metrics.cyclomatic.average
old: 2.0
new: 3.0
path: .spaces[0].spaces[6].metrics.cognitive.average
old: 1.0
new: 2.0
path: .spaces[0].spaces[6].metrics.cognitive.sum
old: 1.0
new: 2.0
path: .spaces[0].spaces[6].metrics.mi.mi_visual_studio
old: 61.80996864927052
new: 60.019763600423126
path: .spaces[0].spaces[6].metrics.mi.mi_sei
old: 76.98850700054253
new: 72.67387575203644
path: .spaces[0].spaces[6].metrics.mi.mi_original
old: 105.6950463902526
new: 102.63379575672354
path: .spaces[0].spaces[6].metrics.halstead.n2
old: 13.0
new: 11.0
path: .spaces[0].spaces[6].metrics.halstead.volume
old: 199.68581616031315
new: 195.0419599705384
path: .spaces[0].spaces[6].metrics.halstead.difficulty
old: 7.384615384615385
new: 8.909090909090908
path: .spaces[0].spaces[6].metrics.halstead.bugs
old: 0.043184591013155665
new: 0.048178474062131174
path: .spaces[0].spaces[6].metrics.halstead.level
old: 0.13541666666666666
new: 0.11224489795918367
path: .spaces[0].spaces[6].metrics.halstead.estimated_program_length
old: 91.12526634448808
new: 91.35671671381672
path: .spaces[0].spaces[6].metrics.halstead.effort
old: 1474.602950106928
new: 1737.6465524647963
path: .spaces[0].spaces[6].metrics.halstead.purity_ratio
old: 2.11919224056949
new: 2.1751599217575412
path: .spaces[0].spaces[6].metrics.halstead.N1
old: 27.0
new: 28.0
path: .spaces[0].spaces[6].metrics.halstead.time
old: 81.92238611705154
new: 96.53591958137758
path: .spaces[0].spaces[6].metrics.halstead.length
old: 43.0
new: 42.0
path: .spaces[0].spaces[6].metrics.halstead.n1
old: 12.0
new: 14.0
path: .spaces[0].spaces[6].metrics.halstead.N2
old: 16.0
new: 14.0
Code
bool nsAvailableMemoryWatcher::IsCommitSpaceLow(const MEMORYSTATUSEX& aStat) {
if ((kLowCommitSpaceThreshold != 0) &&
(aStat.ullAvailPageFile < kLowCommitSpaceThreshold)) {
sNumLowCommitSpaceEvents++;
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::LowCommitSpaceEvents,
uint32_t(sNumLowCommitSpaceEvents));
return true;
}
return false;
}
Minimal test - lines (148, 156)
path: .spaces[0].spaces[5].metrics.cyclomatic.average
old: 1.0
new: 3.0
path: .spaces[0].spaces[5].metrics.cyclomatic.sum
old: 1.0
new: 3.0
path: .spaces[0].spaces[5].metrics.nexits.average
old: 0.0
new: 2.0
path: .spaces[0].spaces[5].metrics.nexits.sum
old: 0.0
new: 2.0
path: .spaces[0].spaces[5].metrics.loc.ploc
old: 1.0
new: 8.0
path: .spaces[0].spaces[5].metrics.loc.sloc
old: 1.0
new: 9.0
path: .spaces[0].spaces[5].metrics.loc.lloc
old: 1.0
new: 4.0
path: .spaces[0].spaces[5].metrics.loc.blank
old: 0.0
new: 1.0
path: .spaces[0].spaces[5].metrics.nargs.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[5].metrics.nargs.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[5].metrics.cognitive.average
old: 0.0
new: 2.0
path: .spaces[0].spaces[5].metrics.cognitive.sum
old: 0.0
new: 2.0
path: .spaces[0].spaces[5].metrics.mi.mi_visual_studio
old: 89.35513233151332
new: 63.7918815961899
path: .spaces[0].spaces[5].metrics.mi.mi_sei
old: 144.8408406278255
new: 81.97972298573713
path: .spaces[0].spaces[5].metrics.mi.mi_original
old: 152.79727628688778
new: 109.08411752948474
path: .spaces[0].spaces[5].metrics.halstead.estimated_program_length
old: 20.264662506490403
new: 76.63504134881501
path: .spaces[0].spaces[5].metrics.halstead.difficulty
old: 3.0
new: 7.944444444444445
path: .spaces[0].spaces[5].metrics.halstead.n2
old: 3.0
new: 9.0
path: .spaces[0].spaces[5].metrics.halstead.n1
old: 6.0
new: 13.0
path: .spaces[0].spaces[5].metrics.halstead.N1
old: 7.0
new: 20.0
path: .spaces[0].spaces[5].metrics.halstead.effort
old: 95.09775004326936
new: 1098.2589091899522
path: .spaces[0].spaces[5].metrics.halstead.volume
old: 31.69925001442312
new: 138.24238017775622
path: .spaces[0].spaces[5].metrics.halstead.N2
old: 3.0
new: 11.0
path: .spaces[0].spaces[5].metrics.halstead.bugs
old: 0.006944786620971931
new: 0.035482583648985856
path: .spaces[0].spaces[5].metrics.halstead.level
old: 0.3333333333333333
new: 0.12587412587412586
path: .spaces[0].spaces[5].metrics.halstead.vocabulary
old: 9.0
new: 22.0
path: .spaces[0].spaces[5].metrics.halstead.length
old: 10.0
new: 31.0
path: .spaces[0].spaces[5].metrics.halstead.time
old: 5.2832083357371875
new: 61.01438384388624
path: .spaces[0].spaces[5].metrics.halstead.purity_ratio
old: 2.0264662506490403
new: 2.4720981080262905
Code
bool nsAvailableMemoryWatcher::IsVirtualMemoryLow(const MEMORYSTATUSEX& aStat) {
if ((kLowVirtualMemoryThreshold != 0) &&
(aStat.ullAvailVirtual < kLowVirtualMemoryThreshold)) {
sNumLowVirtualMemEvents++;
return true;
}
return false;
}
Minimal test - lines (113, 114)
path: .spaces[0].spaces[2].metrics.mi.mi_visual_studio
old: 65.63997397571175
new: 81.0934572754703
path: .spaces[0].spaces[2].metrics.mi.mi_original
old: 112.2443554984671
new: 138.6698119410542
path: .spaces[0].spaces[2].metrics.mi.mi_sei
old: 86.53898263161697
new: 124.45921787575575
path: .spaces[0].spaces[2].metrics.cyclomatic.sum
old: 3.0
new: 1.0
path: .spaces[0].spaces[2].metrics.cyclomatic.average
old: 1.5
new: 1.0
path: .spaces[0].spaces[2].metrics.loc.sloc
old: 9.0
new: 2.0
path: .spaces[0].spaces[2].metrics.loc.lloc
old: 4.0
new: 0.0
path: .spaces[0].spaces[2].metrics.loc.ploc
old: 9.0
new: 2.0
path: .spaces[0].spaces[2].metrics.halstead.n1
old: 7.0
new: 5.0
path: .spaces[0].spaces[2].metrics.halstead.N1
old: 13.0
new: 9.0
path: .spaces[0].spaces[2].metrics.halstead.level
old: 0.17857142857142858
new: 0.34285714285714286
path: .spaces[0].spaces[2].metrics.halstead.N2
old: 8.0
new: 7.0
path: .spaces[0].spaces[2].metrics.halstead.difficulty
old: 5.6
new: 2.9166666666666665
path: .spaces[0].spaces[2].metrics.halstead.estimated_program_length
old: 31.26112492884004
new: 27.11941547876375
path: .spaces[0].spaces[2].metrics.halstead.time
old: 23.421755004711553
new: 8.96889678905966
path: .spaces[0].spaces[2].metrics.halstead.effort
old: 421.59159008480793
new: 161.44014220307386
path: .spaces[0].spaces[2].metrics.halstead.bugs
old: 0.018741601728696464
new: 0.009882946238954084
path: .spaces[0].spaces[2].metrics.halstead.n2
old: 5.0
new: 6.0
path: .spaces[0].spaces[2].metrics.halstead.purity_ratio
old: 1.4886249966114304
new: 1.6949634674227343
path: .spaces[0].spaces[2].metrics.halstead.volume
old: 75.28421251514428
new: 55.35090589819676
path: .spaces[0].spaces[2].metrics.halstead.vocabulary
old: 12.0
new: 11.0
path: .spaces[0].spaces[2].metrics.halstead.length
old: 21.0
new: 16.0
path: .spaces[0].spaces[2].metrics.cognitive.average
old: 1.0
new: 0.0
path: .spaces[0].spaces[2].metrics.cognitive.sum
old: 1.0
new: 0.0
Code
nsAvailableMemoryWatcher::nsAvailableMemoryWatcher()
: mTimer(nullptr), mUnderMemoryPressure(false), mSavedReport(false) {}
Minimal test - lines (57, 103)
path: .spaces[0].spaces[1].metrics.cyclomatic.sum
old: 2.0
new: 3.0
path: .spaces[0].spaces[1].metrics.nom.functions
old: 1.0
new: 2.0
path: .spaces[0].spaces[1].metrics.nom.total
old: 1.0
new: 2.0
path: .spaces[0].spaces[1].metrics.loc.ploc
old: 6.0
new: 31.0
path: .spaces[0].spaces[1].metrics.loc.lloc
old: 2.0
new: 1.0
path: .spaces[0].spaces[1].metrics.loc.blank
old: 0.0
new: 9.0
path: .spaces[0].spaces[1].metrics.loc.cloc
old: 2.0
new: 7.0
path: .spaces[0].spaces[1].metrics.loc.sloc
old: 8.0
new: 47.0
path: .spaces[0].spaces[1].metrics.halstead.bugs
old: 0.008930931841887613
new: 0.11022749495637564
path: .spaces[0].spaces[1].metrics.halstead.effort
old: 138.68421881310115
new: 6013.354243047388
path: .spaces[0].spaces[1].metrics.halstead.time
old: 7.704678822950064
new: 334.0752357248549
path: .spaces[0].spaces[1].metrics.halstead.length
old: 14.0
new: 119.0
path: .spaces[0].spaces[1].metrics.halstead.n1
old: 5.0
new: 14.0
path: .spaces[0].spaces[1].metrics.halstead.N1
old: 9.0
new: 74.0
path: .spaces[0].spaces[1].metrics.halstead.level
old: 0.32
new: 0.1111111111111111
path: .spaces[0].spaces[1].metrics.halstead.vocabulary
old: 9.0
new: 49.0
path: .spaces[0].spaces[1].metrics.halstead.N2
old: 5.0
new: 45.0
path: .spaces[0].spaces[1].metrics.halstead.volume
old: 44.37895002019237
new: 668.1504714497098
path: .spaces[0].spaces[1].metrics.halstead.n2
old: 4.0
new: 35.0
path: .spaces[0].spaces[1].metrics.halstead.purity_ratio
old: 1.400688605316915
new: 1.9565367605200024
path: .spaces[0].spaces[1].metrics.halstead.estimated_program_length
old: 19.60964047443681
new: 232.82787450188027
path: .spaces[0].spaces[1].metrics.halstead.difficulty
old: 3.125
new: 9.0
path: .spaces[0].spaces[1].metrics.nexits.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[1].metrics.nexits.average
old: 0.0
new: 0.5
path: .spaces[0].spaces[1].metrics.mi.mi_sei
old: 128.4580146497127
new: 59.67281030747717
path: .spaces[0].spaces[1].metrics.mi.mi_original
old: 117.13066768124412
new: 74.1141391471737
path: .spaces[0].spaces[1].metrics.mi.mi_visual_studio
old: 68.49746648025972
new: 43.341601840452455
Code
class nsAvailableMemoryWatcher final : public nsIObserver,
public nsITimerCallback {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSITIMERCALLBACK
nsAvailableMemoryWatcher();
nsresult Init();
private:
// Fire a low-memory notification if we have less than this many bytes of
// virtual address space available.
# if defined(HAVE_64BIT_BUILD)
static const size_t kLowVirtualMemoryThreshold = 0;
# else
static const size_t kLowVirtualMemoryThreshold = 384 * 1024 * 1024;
# endif
// Fire a low-memory notification if we have less than this many bytes of
// commit space (physical memory plus page file) left.
static const size_t kLowCommitSpaceThreshold = 384 * 1024 * 1024;
// Don't fire a low-memory notification more often than this interval.
static const uint32_t kLowMemoryNotificationIntervalMS = 10000;
// Poll the amount of free memory at this rate.
static const uint32_t kPollingIntervalMS = 1000;
// Observer topics we subscribe to, see below.
static const char* const kObserverTopics[];
static bool IsVirtualMemoryLow(const MEMORYSTATUSEX& aStat);
static bool IsCommitSpaceLow(const MEMORYSTATUSEX& aStat);
~nsAvailableMemoryWatcher(){};
bool OngoingMemoryPressure() { return mUnderMemoryPressure; }
void AdjustPollingInterval(const bool aLowMemory);
void SendMemoryPressureEvent();
void MaybeSendMemoryPressureStopEvent();
void MaybeSaveMemoryReport();
void Shutdown();
nsCOMPtr mTimer;
bool mUnderMemoryPressure;
bool mSavedReport;
};
Minimal test - lines (35, 397)
path: .spaces[0].metrics.halstead.N2
old: 162.0
new: 349.0
path: .spaces[0].metrics.halstead.n1
old: 29.0
new: 31.0
path: .spaces[0].metrics.halstead.bugs
old: 0.6623494331190752
new: 1.308090879472304
path: .spaces[0].metrics.halstead.length
old: 441.0
new: 914.0
path: .spaces[0].metrics.halstead.time
old: 4920.850040420995
new: 13657.34415269519
path: .spaces[0].metrics.halstead.level
old: 0.033631332481907195
new: 0.02791385525464461
path: .spaces[0].metrics.halstead.n2
old: 79.0
new: 151.0
path: .spaces[0].metrics.halstead.estimated_program_length
old: 638.8801279646907
new: 1246.57920126008
path: .spaces[0].metrics.halstead.purity_ratio
old: 1.448707773162564
new: 1.363872211444289
path: .spaces[0].metrics.halstead.difficulty
old: 29.73417721518987
new: 35.824503311258276
path: .spaces[0].metrics.halstead.N1
old: 279.0
new: 565.0
path: .spaces[0].metrics.halstead.vocabulary
old: 108.0
new: 182.0
path: .spaces[0].metrics.halstead.volume
old: 2978.9053884540895
new: 6862.124301141608
path: .spaces[0].metrics.halstead.effort
old: 88575.30072757792
new: 245832.19474851343
path: .spaces[0].metrics.cyclomatic.sum
old: 30.0
new: 56.0
path: .spaces[0].metrics.cyclomatic.average
old: 2.727272727272727
new: 1.8666666666666667
path: .spaces[0].metrics.nom.closures
old: 1.0
new: 0.0
path: .spaces[0].metrics.nom.functions
old: 8.0
new: 24.0
path: .spaces[0].metrics.nom.total
old: 9.0
new: 24.0
path: .spaces[0].metrics.nargs.sum
old: 8.0
new: 13.0
path: .spaces[0].metrics.nargs.average
old: 0.8888888888888888
new: 0.5416666666666666
path: .spaces[0].metrics.cognitive.sum
old: 26.0
new: 31.0
path: .spaces[0].metrics.cognitive.average
old: 2.888888888888889
new: 1.2916666666666667
path: .spaces[0].metrics.loc.cloc
old: 42.0
new: 50.0
path: .spaces[0].metrics.loc.blank
old: 9.0
new: 64.0
path: .spaces[0].metrics.loc.lloc
old: 52.0
new: 69.0
path: .spaces[0].metrics.loc.sloc
old: 162.0
new: 363.0
path: .spaces[0].metrics.loc.ploc
old: 111.0
new: 249.0
path: .spaces[0].metrics.nexits.average
old: 0.7777777777777778
new: 0.5416666666666666
path: .spaces[0].metrics.nexits.sum
old: 7.0
new: 13.0
path: .spaces[0].metrics.mi.mi_sei
old: 20.659265851248648
new: -18.72301930709246
path: .spaces[0].metrics.mi.mi_original
old: 40.08452116714089
new: 16.695057929009295
path: .spaces[0].metrics.mi.mi_visual_studio
old: 23.441240448620405
new: 9.763191771350463
Code
namespace {
#if defined(XP_WIN)
# if (NTDDI_VERSION < NTDDI_WINBLUE) || \
(NTDDI_VERSION == NTDDI_WINBLUE && !defined(WINBLUE_KBSPRING14))
// Definitions for heap optimization that require the Windows SDK to target the
// Windows 8.1 Update
static const HEAP_INFORMATION_CLASS HeapOptimizeResources =
static_cast(3);
static const DWORD HEAP_OPTIMIZE_RESOURCES_CURRENT_VERSION = 1;
typedef struct _HEAP_OPTIMIZE_RESOURCES_INFORMATION {
DWORD Version;
DWORD Flags;
} HEAP_OPTIMIZE_RESOURCES_INFORMATION, *PHEAP_OPTIMIZE_RESOURCES_INFORMATION;
# endif
Atomic sNumLowVirtualMemEvents;
Atomic sNumLowCommitSpaceEvents;
class nsAvailableMemoryWatcher final : public nsIObserver,
public nsITimerCallback {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
NS_DECL_NSITIMERCALLBACK
nsAvailableMemoryWatcher();
nsresult Init();
private:
// Fire a low-memory notification if we have less than this many bytes of
// virtual address space available.
# if defined(HAVE_64BIT_BUILD)
static const size_t kLowVirtualMemoryThreshold = 0;
# else
static const size_t kLowVirtualMemoryThreshold = 384 * 1024 * 1024;
# endif
// Fire a low-memory notification if we have less than this many bytes of
// commit space (physical memory plus page file) left.
static const size_t kLowCommitSpaceThreshold = 384 * 1024 * 1024;
// Don't fire a low-memory notification more often than this interval.
static const uint32_t kLowMemoryNotificationIntervalMS = 10000;
// Poll the amount of free memory at this rate.
static const uint32_t kPollingIntervalMS = 1000;
// Observer topics we subscribe to, see below.
static const char* const kObserverTopics[];
static bool IsVirtualMemoryLow(const MEMORYSTATUSEX& aStat);
static bool IsCommitSpaceLow(const MEMORYSTATUSEX& aStat);
~nsAvailableMemoryWatcher(){};
bool OngoingMemoryPressure() { return mUnderMemoryPressure; }
void AdjustPollingInterval(const bool aLowMemory);
void SendMemoryPressureEvent();
void MaybeSendMemoryPressureStopEvent();
void MaybeSaveMemoryReport();
void Shutdown();
nsCOMPtr mTimer;
bool mUnderMemoryPressure;
bool mSavedReport;
};
const char* const nsAvailableMemoryWatcher::kObserverTopics[] = {
"quit-application",
"user-interaction-active",
"user-interaction-inactive",
};
NS_IMPL_ISUPPORTS(nsAvailableMemoryWatcher, nsIObserver, nsITimerCallback)
nsAvailableMemoryWatcher::nsAvailableMemoryWatcher()
: mTimer(nullptr), mUnderMemoryPressure(false), mSavedReport(false) {}
nsresult nsAvailableMemoryWatcher::Init() {
mTimer = NS_NewTimer();
nsCOMPtr observerService = services::GetObserverService();
MOZ_ASSERT(observerService);
for (auto topic : kObserverTopics) {
nsresult rv = observerService->AddObserver(this, topic,
/* ownsWeak */ false);
NS_ENSURE_SUCCESS(rv, rv);
}
MOZ_TRY(mTimer->InitWithCallback(this, kPollingIntervalMS,
nsITimer::TYPE_REPEATING_SLACK));
return NS_OK;
}
void nsAvailableMemoryWatcher::Shutdown() {
nsCOMPtr observerService = services::GetObserverService();
MOZ_ASSERT(observerService);
for (auto topic : kObserverTopics) {
Unused << observerService->RemoveObserver(this, topic);
}
if (mTimer) {
mTimer->Cancel();
mTimer = nullptr;
}
}
/* static */
bool nsAvailableMemoryWatcher::IsVirtualMemoryLow(const MEMORYSTATUSEX& aStat) {
if ((kLowVirtualMemoryThreshold != 0) &&
(aStat.ullAvailVirtual < kLowVirtualMemoryThreshold)) {
sNumLowVirtualMemEvents++;
return true;
}
return false;
}
/* static */
bool nsAvailableMemoryWatcher::IsCommitSpaceLow(const MEMORYSTATUSEX& aStat) {
if ((kLowCommitSpaceThreshold != 0) &&
(aStat.ullAvailPageFile < kLowCommitSpaceThreshold)) {
sNumLowCommitSpaceEvents++;
CrashReporter::AnnotateCrashReport(
CrashReporter::Annotation::LowCommitSpaceEvents,
uint32_t(sNumLowCommitSpaceEvents));
return true;
}
return false;
}
void nsAvailableMemoryWatcher::SendMemoryPressureEvent() {
MemoryPressureState state =
OngoingMemoryPressure() ? MemPressure_Ongoing : MemPressure_New;
NS_DispatchEventualMemoryPressure(state);
}
void nsAvailableMemoryWatcher::MaybeSendMemoryPressureStopEvent() {
if (OngoingMemoryPressure()) {
NS_DispatchEventualMemoryPressure(MemPressure_Stopping);
}
}
void nsAvailableMemoryWatcher::MaybeSaveMemoryReport() {
if (!mSavedReport && OngoingMemoryPressure()) {
nsCOMPtr cr =
do_GetService("@mozilla.org/toolkit/crash-reporter;1");
if (cr) {
if (NS_SUCCEEDED(cr->SaveMemoryReport())) {
mSavedReport = true;
}
}
}
}
void nsAvailableMemoryWatcher::AdjustPollingInterval(const bool aLowMemory) {
if (aLowMemory) {
// We entered a low-memory state, wait for a longer interval before polling
// again as there's no point in rapidly sending further notifications.
mTimer->SetDelay(kLowMemoryNotificationIntervalMS);
} else if (OngoingMemoryPressure()) {
// We were under memory pressure but we're not anymore, resume polling at
// a faster pace.
mTimer->SetDelay(kPollingIntervalMS);
}
}
// Timer callback, polls memory stats to detect low-memory conditions. This
// will send memory-pressure events if memory is running low and adjust the
// polling interval accordingly.
NS_IMETHODIMP
nsAvailableMemoryWatcher::Notify(nsITimer* aTimer) {
MEMORYSTATUSEX stat;
stat.dwLength = sizeof(stat);
bool success = GlobalMemoryStatusEx(&stat);
if (success) {
bool lowMemory = IsVirtualMemoryLow(stat) || IsCommitSpaceLow(stat);
if (lowMemory) {
SendMemoryPressureEvent();
} else {
MaybeSendMemoryPressureStopEvent();
}
if (lowMemory) {
MaybeSaveMemoryReport();
} else {
mSavedReport = false; // Save a new report if memory gets low again
}
AdjustPollingInterval(lowMemory);
mUnderMemoryPressure = lowMemory;
}
return NS_OK;
}
// Observer service callback, used to stop the polling timer when the user
// stops interacting with Firefox and resuming it when they interact again.
// Also used to shut down the service if the application is quitting.
NS_IMETHODIMP
nsAvailableMemoryWatcher::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
if (strcmp(aTopic, "quit-application") == 0) {
Shutdown();
} else if (strcmp(aTopic, "user-interaction-inactive") == 0) {
mTimer->Cancel();
} else if (strcmp(aTopic, "user-interaction-active") == 0) {
mTimer->InitWithCallback(this, kPollingIntervalMS,
nsITimer::TYPE_REPEATING_SLACK);
} else {
MOZ_ASSERT_UNREACHABLE("Unknown topic");
}
return NS_OK;
}
static int64_t LowMemoryEventsVirtualDistinguishedAmount() {
return sNumLowVirtualMemEvents;
}
static int64_t LowMemoryEventsCommitSpaceDistinguishedAmount() {
return sNumLowCommitSpaceEvents;
}
class LowEventsReporter final : public nsIMemoryReporter {
~LowEventsReporter() {}
public:
NS_DECL_ISUPPORTS
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData, bool aAnonymize) override {
// clang-format off
MOZ_COLLECT_REPORT(
"low-memory-events/virtual", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
LowMemoryEventsVirtualDistinguishedAmount(),
"Number of low-virtual-memory events fired since startup. We fire such an "
"event if we notice there is less than predefined amount of virtual address "
"space available (if zero, this behavior is disabled, see "
"xpcom/base/AvailableMemoryTracker.cpp). The process will probably crash if "
"it runs out of virtual address space, so this event is dire.");
MOZ_COLLECT_REPORT(
"low-memory-events/commit-space", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
LowMemoryEventsCommitSpaceDistinguishedAmount(),
"Number of low-commit-space events fired since startup. We fire such an "
"event if we notice there is less than a predefined amount of commit space "
"available (if zero, this behavior is disabled, see "
"xpcom/base/AvailableMemoryTracker.cpp). Windows will likely kill the process "
"if it runs out of commit space, so this event is dire.");
// clang-format on
return NS_OK;
}
};
NS_IMPL_ISUPPORTS(LowEventsReporter, nsIMemoryReporter)
#endif // defined(XP_WIN)
/**
* This runnable is executed in response to a memory-pressure event; we spin
* the event-loop when receiving the memory-pressure event in the hope that
* other observers will synchronously free some memory that we'll be able to
* purge here.
*/
class nsJemallocFreeDirtyPagesRunnable final : public Runnable {
~nsJemallocFreeDirtyPagesRunnable() = default;
#if defined(XP_WIN)
void OptimizeSystemHeap();
#endif
public:
NS_DECL_NSIRUNNABLE
nsJemallocFreeDirtyPagesRunnable()
: Runnable("nsJemallocFreeDirtyPagesRunnable") {}
};
NS_IMETHODIMP
nsJemallocFreeDirtyPagesRunnable::Run() {
MOZ_ASSERT(NS_IsMainThread());
#if defined(MOZ_MEMORY)
jemalloc_free_dirty_pages();
#endif
#if defined(XP_WIN)
OptimizeSystemHeap();
#endif
return NS_OK;
}
#if defined(XP_WIN)
void nsJemallocFreeDirtyPagesRunnable::OptimizeSystemHeap() {
// HeapSetInformation exists prior to Windows 8.1, but the
// HeapOptimizeResources information class does not.
if (IsWin8Point1OrLater()) {
HEAP_OPTIMIZE_RESOURCES_INFORMATION heapOptInfo = {
HEAP_OPTIMIZE_RESOURCES_CURRENT_VERSION};
::HeapSetInformation(nullptr, HeapOptimizeResources, &heapOptInfo,
sizeof(heapOptInfo));
}
}
#endif // defined(XP_WIN)
/**
* The memory pressure watcher is used for listening to memory-pressure events
* and reacting upon them. We use one instance per process currently only for
* cleaning up dirty unused pages held by jemalloc.
*/
class nsMemoryPressureWatcher final : public nsIObserver {
~nsMemoryPressureWatcher() = default;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
void Init();
};
NS_IMPL_ISUPPORTS(nsMemoryPressureWatcher, nsIObserver)
/**
* Initialize and subscribe to the memory-pressure events. We subscribe to the
* observer service in this method and not in the constructor because we need
* to hold a strong reference to 'this' before calling the observer service.
*/
void nsMemoryPressureWatcher::Init() {
nsCOMPtr os = services::GetObserverService();
if (os) {
os->AddObserver(this, "memory-pressure", /* ownsWeak */ false);
}
}
/**
* Reacts to all types of memory-pressure events, launches a runnable to
* free dirty pages held by jemalloc.
*/
NS_IMETHODIMP
nsMemoryPressureWatcher::Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) {
MOZ_ASSERT(!strcmp(aTopic, "memory-pressure"), "Unknown topic");
nsCOMPtr runnable = new nsJemallocFreeDirtyPagesRunnable();
NS_DispatchToMainThread(runnable);
return NS_OK;
}
} // namespace
Minimal test - lines (48, 51)
path: .spaces[0].spaces[0].metrics.nexits.average
old: 0.0
new: null
path: .spaces[0].spaces[0].metrics.mi.mi_original
old: 112.52433481121324
new: 132.56043812602817
path: .spaces[0].spaces[0].metrics.mi.mi_visual_studio
old: 65.80370456796095
new: 77.52072405030886
path: .spaces[0].spaces[0].metrics.mi.mi_sei
old: 86.94290739766731
new: 115.6452545698808
path: .spaces[0].spaces[0].metrics.cognitive.sum
old: 2.0
new: 0.0
path: .spaces[0].spaces[0].metrics.cognitive.average
old: 2.0
new: null
path: .spaces[0].spaces[0].metrics.nom.functions
old: 1.0
new: 0.0
path: .spaces[0].spaces[0].metrics.nom.total
old: 1.0
new: 0.0
path: .spaces[0].spaces[0].metrics.halstead.n1
old: 11.0
new: 3.0
path: .spaces[0].spaces[0].metrics.halstead.time
old: 56.36226073555473
new: 1.723308333814104
path: .spaces[0].spaces[0].metrics.halstead.vocabulary
old: 22.0
new: 6.0
path: .spaces[0].spaces[0].metrics.halstead.length
old: 35.0
new: 8.0
path: .spaces[0].spaces[0].metrics.halstead.n2
old: 11.0
new: 3.0
path: .spaces[0].spaces[0].metrics.halstead.difficulty
old: 6.5
new: 1.5
path: .spaces[0].spaces[0].metrics.halstead.level
old: 0.15384615384615383
new: 0.6666666666666666
path: .spaces[0].spaces[0].metrics.halstead.N1
old: 22.0
new: 5.0
path: .spaces[0].spaces[0].metrics.halstead.effort
old: 1014.5206932399852
new: 31.019550008653873
path: .spaces[0].spaces[0].metrics.halstead.bugs
old: 0.033655239474984285
new: 0.003290806962640765
path: .spaces[0].spaces[0].metrics.halstead.purity_ratio
old: 2.174499874572015
new: 1.188721875540867
path: .spaces[0].spaces[0].metrics.halstead.volume
old: 156.0801066523054
new: 20.67970000576925
path: .spaces[0].spaces[0].metrics.halstead.N2
old: 13.0
new: 3.0
path: .spaces[0].spaces[0].metrics.halstead.estimated_program_length
old: 76.10749561002054
new: 9.509775004326936
path: .spaces[0].spaces[0].metrics.nargs.average
old: 0.0
new: null
path: .spaces[0].spaces[0].metrics.cyclomatic.sum
old: 3.0
new: 1.0
path: .spaces[0].spaces[0].metrics.cyclomatic.average
old: 3.0
new: 1.0
path: .spaces[0].spaces[0].metrics.loc.lloc
old: 3.0
new: 0.0
path: .spaces[0].spaces[0].metrics.loc.ploc
old: 7.0
new: 4.0
path: .spaces[0].spaces[0].metrics.loc.sloc
old: 7.0
new: 4.0
Code
typedef struct _HEAP_OPTIMIZE_RESOURCES_INFORMATION {
DWORD Version;
DWORD Flags;
} HEAP_OPTIMIZE_RESOURCES_INFORMATION, *PHEAP_OPTIMIZE_RESOURCES_INFORMATION;
Minimal test - lines (116, 131)
path: .spaces[0].spaces[3].metrics.nexits.average
old: 0.0
new: 1.0
path: .spaces[0].spaces[3].metrics.nexits.sum
old: 0.0
new: 1.0
path: .spaces[0].spaces[3].metrics.cyclomatic.sum
old: 7.0
new: 2.0
path: .spaces[0].spaces[3].metrics.cyclomatic.average
old: 7.0
new: 2.0
path: .spaces[0].spaces[3].metrics.halstead.n2
old: 13.0
new: 20.0
path: .spaces[0].spaces[3].metrics.halstead.time
old: 303.6752136752136
new: 141.75
path: .spaces[0].spaces[3].metrics.halstead.N2
old: 22.0
new: 27.0
path: .spaces[0].spaces[3].metrics.halstead.effort
old: 5466.153846153846
new: 2551.5
path: .spaces[0].spaces[3].metrics.halstead.length
old: 68.0
new: 63.0
path: .spaces[0].spaces[3].metrics.halstead.purity_ratio
old: 1.894357927812681
new: 2.05489066518097
path: .spaces[0].spaces[3].metrics.halstead.estimated_program_length
old: 128.8163390912623
new: 129.45811190640111
path: .spaces[0].spaces[3].metrics.halstead.N1
old: 46.0
new: 36.0
path: .spaces[0].spaces[3].metrics.halstead.volume
old: 340.0
new: 315.0
path: .spaces[0].spaces[3].metrics.halstead.n1
old: 19.0
new: 12.0
path: .spaces[0].spaces[3].metrics.halstead.bugs
old: 0.10343479209370732
new: 0.06224088994278901
path: .spaces[0].spaces[3].metrics.halstead.difficulty
old: 16.076923076923077
new: 8.1
path: .spaces[0].spaces[3].metrics.halstead.level
old: 0.06220095693779904
new: 0.1234567901234568
path: .spaces[0].spaces[3].metrics.cognitive.average
old: 11.0
new: 0.0
path: .spaces[0].spaces[3].metrics.cognitive.sum
old: 11.0
new: 0.0
path: .spaces[0].spaces[3].metrics.mi.mi_sei
old: 88.55099294884796
new: 81.4685300984352
path: .spaces[0].spaces[3].metrics.mi.mi_original
old: 83.44889007576754
new: 95.71068497782224
path: .spaces[0].spaces[3].metrics.mi.mi_visual_studio
old: 48.80052051214476
new: 55.97116080574401
path: .spaces[0].spaces[3].metrics.loc.sloc
old: 31.0
new: 16.0
path: .spaces[0].spaces[3].metrics.loc.lloc
old: 9.0
new: 5.0
path: .spaces[0].spaces[3].metrics.loc.blank
old: 0.0
new: 2.0
path: .spaces[0].spaces[3].metrics.loc.cloc
old: 14.0
new: 1.0
path: .spaces[0].spaces[3].metrics.loc.ploc
old: 17.0
new: 13.0
path: .spaces[0].spaces[3].metrics.nargs.average
old: 2.0
new: 0.0
path: .spaces[0].spaces[3].metrics.nargs.sum
old: 2.0
new: 0.0
Code
nsresult nsAvailableMemoryWatcher::Init() {
mTimer = NS_NewTimer();
nsCOMPtr observerService = services::GetObserverService();
MOZ_ASSERT(observerService);
for (auto topic : kObserverTopics) {
nsresult rv = observerService->AddObserver(this, topic,
/* ownsWeak */ false);
NS_ENSURE_SUCCESS(rv, rv);
}
MOZ_TRY(mTimer->InitWithCallback(this, kPollingIntervalMS,
nsITimer::TYPE_REPEATING_SLACK));
return NS_OK;
}