Bug 1121830 - DMD: add "num" property to blocks in the output. r=mccr8.

The new "num" property lets identical blocks be aggregated in the output. This
patch only uses the "num" property for dead blocks, because that's where the
greatest potential benefit lies, but it could be used for live blocks as well.

On one test case (a complex PDF file) running with --mode=cumulative
--sample-below=1 this patch had the following effects.

- Change in running speed was negligible.

- Compressed output file size dropped from 8.8 to 5.0 MB.

- Compressed output file size dropped from 297 to 50 MB.

- dmd.py runtime (without stack fixing) dropped from 30 to 8 seconds.

--HG--
extra : rebase_source : 46a32058cd5c31cd823fe3f1accb5e68bcd320f3
This commit is contained in:
Nicholas Nethercote 2015-01-15 20:38:38 -08:00
parent 4dd11eefe4
commit bf937eb0ab
13 changed files with 178 additions and 156 deletions

View File

@ -38,7 +38,6 @@
#include "mozilla/JSONWriter.h"
#include "mozilla/Likely.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/SegmentedVector.h"
// CodeAddressService is defined entirely in the header, so this does not make
// DMD depend on XPCOM's object file.
@ -445,7 +444,7 @@ public:
};
// This lock must be held while manipulating global state such as
// gStackTraceTable, gLiveBlockTable, gDeadBlockList. Note that gOptions is
// gStackTraceTable, gLiveBlockTable, gDeadBlockTable. Note that gOptions is
// *not* protected by this lock because it is only written to by Options(),
// which is only invoked at start-up and in ResetEverything(), which is only
// used by SmokeDMD.cpp.
@ -1036,12 +1035,46 @@ public:
{
aStackTraces.put(AllocStackTrace()); // never null
}
// Hash policy.
typedef DeadBlock Lookup;
static uint32_t hash(const DeadBlock& aB)
{
return mozilla::HashGeneric(aB.ReqSize(),
aB.SlopSize(),
aB.IsSampled(),
aB.AllocStackTrace());
}
static bool match(const DeadBlock& aA, const DeadBlock& aB)
{
return aA.ReqSize() == aB.ReqSize() &&
aA.SlopSize() == aB.SlopSize() &&
aA.IsSampled() == aB.IsSampled() &&
aA.AllocStackTrace() == aB.AllocStackTrace();
}
};
static const size_t kDeadBlockListSegmentSize = 16384;
typedef SegmentedVector<DeadBlock, kDeadBlockListSegmentSize,
InfallibleAllocPolicy> DeadBlockList;
static DeadBlockList* gDeadBlockList = nullptr;
// For each unique DeadBlock value we store a count of how many actual dead
// blocks have that value.
typedef js::HashMap<DeadBlock, size_t, DeadBlock, InfallibleAllocPolicy>
DeadBlockTable;
static DeadBlockTable* gDeadBlockTable = nullptr;
// Add the dead block to the dead block table, if that's appropriate.
void MaybeAddToDeadBlockTable(const DeadBlock& aDb)
{
if (gOptions->IsCumulativeMode() && aDb.AllocStackTrace()) {
AutoLockState lock;
if (DeadBlockTable::AddPtr p = gDeadBlockTable->lookupForAdd(aDb)) {
p->value() += 1;
} else {
gDeadBlockTable->add(p, aDb, 1);
}
}
}
// Add a pointer to each live stack trace into the given StackTraceSet. (A
// stack trace is live if it's used by one of the live blocks.)
@ -1058,8 +1091,8 @@ GatherUsedStackTraces(StackTraceSet& aStackTraces)
r.front().AddStackTracesToTable(aStackTraces);
}
for (auto iter = gDeadBlockList->Iter(); !iter.Done(); iter.Next()) {
iter.Get().AddStackTracesToTable(aStackTraces);
for (auto r = gDeadBlockTable->all(); !r.empty(); r.popFront()) {
r.front().key().AddStackTracesToTable(aStackTraces);
}
}
@ -1248,10 +1281,7 @@ replace_realloc(void* aOldPtr, size_t aSize)
void* ptr = gMallocTable->realloc(aOldPtr, aSize);
if (ptr) {
AllocCallback(ptr, aSize, t);
if (gOptions->IsCumulativeMode() && db.AllocStackTrace()) {
AutoLockState lock;
gDeadBlockList->InfallibleAppend(db);
}
MaybeAddToDeadBlockTable(db);
} else {
// If realloc fails, we undo the prior operations by re-inserting the old
// pointer into the live block table. We don't have to do anything with the
@ -1303,10 +1333,7 @@ replace_free(void* aPtr)
// our update here would remove the newly-malloc'd block.
DeadBlock db;
FreeCallback(aPtr, t, &db);
if (gOptions->IsCumulativeMode() && db.AllocStackTrace()) {
AutoLockState lock;
gDeadBlockList->InfallibleAppend(db);
}
MaybeAddToDeadBlockTable(db);
gMallocTable->free(aPtr);
}
@ -1524,11 +1551,11 @@ Init(const malloc_table_t* aMallocTable)
gLiveBlockTable = InfallibleAllocPolicy::new_<LiveBlockTable>();
gLiveBlockTable->init(8192);
// Create this even if the mode isn't Cumulative, in case the mode is
// changed later on (as is done by SmokeDMD.cpp, for example). It's tiny
// when empty, so space isn't a concern.
gDeadBlockList =
InfallibleAllocPolicy::new_<DeadBlockList>(kDeadBlockListSegmentSize);
// Create this even if the mode isn't Cumulative (albeit with a small
// size), in case the mode is changed later on (as is done by SmokeDMD.cpp,
// for example).
gDeadBlockTable = InfallibleAllocPolicy::new_<DeadBlockTable>();
gDeadBlockTable->init(gOptions->IsCumulativeMode() ? 8192 : 4);
}
gIsDMDInitialized = true;
@ -1579,7 +1606,7 @@ DMDFuncs::ReportOnAlloc(const void* aPtr)
// The version number of the output format. Increment this if you make
// backwards-incompatible changes to the format. See DMD.h for the version
// history.
static const int kOutputVersionNumber = 3;
static const int kOutputVersionNumber = 4;
// Note that, unlike most SizeOf* functions, this function does not take a
// |mozilla::MallocSizeOf| argument. That's because those arguments are
@ -1616,7 +1643,7 @@ SizeOfInternal(Sizes* aSizes)
aSizes->mLiveBlockTable = gLiveBlockTable->sizeOfIncludingThis(MallocSizeOf);
aSizes->mDeadBlockList = gDeadBlockList->SizeOfIncludingThis(MallocSizeOf);
aSizes->mDeadBlockTable = gDeadBlockTable->sizeOfIncludingThis(MallocSizeOf);
}
void
@ -1801,10 +1828,13 @@ AnalyzeImpl(UniquePtr<JSONWriteFunc> aWriter)
}
// Dead blocks.
for (auto iter = gDeadBlockList->Iter(); !iter.Done(); iter.Next()) {
const DeadBlock& b = iter.Get();
for (auto r = gDeadBlockTable->all(); !r.empty(); r.popFront()) {
const DeadBlock& b = r.front().key();
b.AddStackTracesToTable(usedStackTraces);
size_t num = r.front().value();
MOZ_ASSERT(num > 0);
writer.StartObjectElement(writer.SingleLineStyle);
{
if (!b.IsSampled()) {
@ -1814,6 +1844,10 @@ AnalyzeImpl(UniquePtr<JSONWriteFunc> aWriter)
}
}
writer.StringProperty("alloc", isc.ToIdString(b.AllocStackTrace()));
if (num > 1) {
writer.IntProperty("num", num);
}
}
writer.EndObject();
}
@ -1890,9 +1924,10 @@ AnalyzeImpl(UniquePtr<JSONWriteFunc> aWriter)
Show(gLiveBlockTable->capacity(), buf2, kBufLen),
Show(gLiveBlockTable->count(), buf3, kBufLen));
StatusMsg(" Dead block list: %10s bytes (%s entries)\n",
Show(sizes.mDeadBlockList, buf1, kBufLen),
Show(gDeadBlockList->Length(), buf2, kBufLen));
StatusMsg(" Dead block table: %10s bytes (%s entries, %s used)\n",
Show(sizes.mDeadBlockTable, buf1, kBufLen),
Show(gDeadBlockTable->capacity(), buf2, kBufLen),
Show(gDeadBlockTable->count(), buf3, kBufLen));
StatusMsg(" }\n");
StatusMsg(" Data structures that are destroyed after Dump() ends {\n");
@ -1952,7 +1987,7 @@ DMDFuncs::ResetEverything(const char* aOptions)
// Clear all existing blocks.
gLiveBlockTable->clear();
gDeadBlockList->Clear();
gDeadBlockTable->clear();
gSmallBlockActualSizeCounter = 0;
}

View File

@ -29,7 +29,7 @@ struct Sizes
size_t mStackTracesUnused;
size_t mStackTraceTable;
size_t mLiveBlockTable;
size_t mDeadBlockList;
size_t mDeadBlockTable;
Sizes() { Clear(); }
void Clear() { memset(this, 0, sizeof(Sizes)); }
@ -147,11 +147,13 @@ ClearReports()
// // backwards-incompatible changes are made. A mandatory integer.
// //
// // Version history:
// // - 1: The original format. Implemented in bug 1044709.
// // - 2: Added the "mode" property under "invocation". Added in bug 1094552.
// // - 3: The "dmdEnvVar" property under "invocation" can now be |null| if
// // the |DMD| environment variable is not defined. Done in bug 1100851.
// "version": 3,
// // - 1: Bug 1044709. The original format.
// // - 2: Bug 1094552. Added the "mode" property under "invocation".
// // - 3: Bug 1100851. The "dmdEnvVar" property under "invocation" can now
// // be |null| if the |DMD| environment variable is not defined.
// // - 4: Bug 1121830. Added the "num" property in "blockList" object.
// //
// "version": 4,
//
// // Information about how DMD was invoked. A mandatory object.
// "invocation": {
@ -184,7 +186,13 @@ ClearReports()
//
// // The stack trace at which the block was allocated. A mandatory
// // string which indexes into the "traceTable" object.
// "alloc": "A"
// "alloc": "A",
//
// // The number of heap blocks with exactly the above properties. This
// // is mandatory if it is greater than one, but omitted otherwise.
// // (Blocks with identical properties don't have to be aggregated via
// // this property, but it can greatly reduce output file size.)
// "num": 5
// },
//
// // An example of a sampled heap block.
@ -233,11 +241,12 @@ ClearReports()
// }
// }
//
// Implementation note: normally, this wouldn't be templated, but in that case,
// the function is compiled, which makes the destructor for the UniquePtr fire
// up, and that needs JSONWriteFunc to be fully defined. That, in turn,
// requires to include JSONWriter.h, which includes double-conversion.h, which
// ends up breaking various things built with -Werror for various reasons.
// Implementation note: normally, this function wouldn't be templated, but in
// that case, the function is compiled, which makes the destructor for the
// UniquePtr fire up, and that needs JSONWriteFunc to be fully defined. That,
// in turn, requires to include JSONWriter.h, which includes
// double-conversion.h, which ends up breaking various things built with
// -Werror for various reasons.
//
template <typename JSONWriteFunc>
inline void

View File

@ -20,7 +20,7 @@ import sys
import tempfile
# The DMD output version this script handles.
outputVersion = 3
outputVersion = 4
# If --ignore-alloc-fns is specified, stack frames containing functions that
# match these strings will be removed from the *start* of stack traces. (Once
@ -408,14 +408,19 @@ def getDigestFromFile(args, inputFile):
slopSize = 0
isSampled = True
usableSize = reqSize + slopSize
heapUsableSize += usableSize
heapBlocks += 1
if 'num' in block:
num = block['num']
else:
num = 1
record.numBlocks += 1
record.reqSize += reqSize
record.slopSize += slopSize
record.usableSize += usableSize
usableSize = reqSize + slopSize
heapUsableSize += num * usableSize
heapBlocks += num
record.numBlocks += num
record.reqSize += num * reqSize
record.slopSize += num * slopSize
record.usableSize += num * usableSize
record.isSampled = record.isSampled or isSampled
if record.allocatedAtDesc == None:
record.allocatedAtDesc = \
@ -428,7 +433,7 @@ def getDigestFromFile(args, inputFile):
if 'reps' in block and record.reportedAtDescs == []:
f = lambda k: buildTraceDescription(traceTable, frameTable, k)
record.reportedAtDescs = map(f, reportedAtTraceKeys)
record.usableSizes[(usableSize, isSampled)] += 1
record.usableSizes[(usableSize, isSampled)] += num
# All the processed data for a single DMD file is called a "digest".
digest = {}

View File

@ -260,6 +260,11 @@ TestUnsampled(const char* aTestName, int aNum, const char* aMode, int aSeven)
//free(y);
//free(z);
// Do some allocations that will only show up in cumulative mode.
for (int i = 0; i < 100; i++) {
free(malloc(128));
}
if (aNum == 2) {
// Analyze 2.
Analyze(Move(f));

View File

@ -10,137 +10,138 @@ Invocation {
#-----------------------------------------------------------------
Cumulative {
1 block in heap block record 1 of 16
100 blocks in heap block record 1 of 17
12,800 bytes (12,800 requested / 0 slop)
Individual block sizes: 128 x 100
42.40% of the heap (42.40% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 2 of 17
8,192 bytes (7,169 requested / 1,023 slop)
47.10% of the heap (47.10% cumulative)
27.13% of the heap (69.53% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 2 of 16
1 block in heap block record 3 of 17
4,096 bytes (4,096 requested / 0 slop)
23.55% of the heap (70.65% cumulative)
13.57% of the heap (83.09% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
10 blocks in heap block record 3 of 16
10 blocks in heap block record 4 of 17
1,120 bytes (1,000 requested / 120 slop)
Individual block sizes: 112 x 10
6.44% of the heap (77.09% cumulative)
3.71% of the heap (86.80% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 4 of 16
1 block in heap block record 5 of 17
1,024 bytes (1,024 requested / 0 slop)
5.89% of the heap (82.98% cumulative)
3.39% of the heap (90.20% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 5 of 16
1 block in heap block record 6 of 17
1,024 bytes (1,023 requested / 1 slop)
5.89% of the heap (88.87% cumulative)
3.39% of the heap (93.59% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
6 blocks in heap block record 6 of 16
6 blocks in heap block record 7 of 17
528 bytes (528 requested / 0 slop)
Individual block sizes: 128; 112; 96; 80; 64; 48
3.04% of the heap (91.90% cumulative)
1.75% of the heap (95.34% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
6 blocks in heap block record 7 of 16
6 blocks in heap block record 8 of 17
528 bytes (528 requested / 0 slop)
Individual block sizes: 128; 112; 96; 80; 64; 48
3.04% of the heap (94.94% cumulative)
1.75% of the heap (97.09% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 8 of 16
1 block in heap block record 9 of 17
512 bytes (512 requested / 0 slop)
2.94% of the heap (97.88% cumulative)
1.70% of the heap (98.78% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 9 of 16
1 block in heap block record 10 of 17
80 bytes (79 requested / 1 slop)
0.46% of the heap (98.34% cumulative)
0.26% of the heap (99.05% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 10 of 16
1 block in heap block record 11 of 17
80 bytes (78 requested / 2 slop)
0.46% of the heap (98.80% cumulative)
0.26% of the heap (99.31% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 11 of 16
1 block in heap block record 12 of 17
80 bytes (77 requested / 3 slop)
0.46% of the heap (99.26% cumulative)
0.26% of the heap (99.58% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 12 of 16
1 block in heap block record 13 of 17
64 bytes (64 requested / 0 slop)
0.37% of the heap (99.63% cumulative)
0.21% of the heap (99.79% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 13 of 16
1 block in heap block record 14 of 17
32 bytes (30 requested / 2 slop)
0.18% of the heap (99.82% cumulative)
0.11% of the heap (99.89% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 14 of 16
1 block in heap block record 15 of 17
16 bytes (10 requested / 6 slop)
0.09% of the heap (99.91% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 15 of 16
8 bytes (8 requested / 0 slop)
0.05% of the heap (99.95% cumulative)
Allocated at {
#01: ... DMD.cpp ...
@ -148,9 +149,18 @@ Cumulative {
}
Cumulative {
1 block in heap block record 16 of 16
1 block in heap block record 16 of 17
8 bytes (8 requested / 0 slop)
0.05% of the heap (100.00% cumulative)
0.03% of the heap (99.97% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
}
Cumulative {
1 block in heap block record 17 of 17
8 bytes (8 requested / 0 slop)
0.03% of the heap (100.00% cumulative)
Allocated at {
#01: ... DMD.cpp ...
}
@ -159,6 +169,6 @@ Cumulative {
#-----------------------------------------------------------------
Summary {
Total: 17,392 bytes in 35 blocks
Total: 30,192 bytes in 135 blocks
}

View File

@ -1,33 +1,24 @@
{
"version": 3,
"version": 4,
"invocation": {
"dmdEnvVar": "--mode=dark-matter --sample-below=127",
"mode": "dark-matter",
"sampleBelowSize": 127
},
"blockList": [
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A", "num": 4},
{"req": 4096, "alloc": "B"},
{"req": 4096, "alloc": "B"},
{"req": 4096, "alloc": "B"},
{"req": 4096, "alloc": "B", "num": 3},
{"req": 4096, "alloc": "B"},
{"req": 4096, "alloc": "C"},
{"req": 4096, "alloc": "C"},
{"req": 4096, "alloc": "C"},
{"req": 4096, "alloc": "C"},
{"req": 4096, "alloc": "C", "num": 2},
{"req": 4096, "alloc": "C", "num": 2},
{"req": 4096, "alloc": "D", "reps": ["R1"]},
{"req": 4096, "alloc": "D", "reps": ["R1"]},
{"req": 4096, "alloc": "D", "reps": ["R1"], "num": 2},
{"req": 2000, "slop": 48, "alloc": "D", "reps": ["R1"]},
{"req": 15360, "alloc": "F"},
{"req": 512, "alloc": "F"},
{"req": 512, "alloc": "F"},
{"req": 512, "alloc": "F", "num": 2},
{ "alloc": "F"},
{"req": 1024, "alloc": "F", "reps": ["R1"]},
{ "alloc": "F", "reps": ["R1"]},

View File

@ -1,28 +1,19 @@
{
"version": 3,
"version": 4,
"invocation": {
"dmdEnvVar": "--sample-below=63",
"mode": "dark-matter",
"sampleBelowSize": 63
},
"blockList": [
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A", "num": 4},
{"req": 8192, "alloc": "B"},
{"req": 8192, "alloc": "B"},
{"req": 4000, "slop": 96, "alloc": "C"},
{"req": 4000, "slop": 96, "alloc": "C"},
{"req": 4000, "slop": 96, "alloc": "C"},
{"req": 4000, "slop": 96, "alloc": "C"},
{"req": 4000, "slop": 96, "alloc": "C", "num": 4},
{"req": 4096, "alloc": "E"},
{"req": 4096, "alloc": "E"},
{"req": 4096, "alloc": "E"},
{"req": 4096, "alloc": "E"},
{"req": 4096, "alloc": "E", "num": 4},
{"req": 2000, "slop": 48, "alloc": "F"},
{"req": 1000, "slop": 24, "alloc": "F", "reps": ["R1"]},
@ -32,14 +23,10 @@
{"req": 512, "alloc": "F"},
{"req": 128, "alloc": "F"},
{ "alloc": "F", "reps": ["R1", "R2"]},
{"req": 64, "alloc": "F"},
{"req": 64, "alloc": "F"},
{"req": 64, "alloc": "F"},
{"req": 64, "alloc": "F"},
{"req": 64, "alloc": "F", "num": 4},
{ "alloc": "F"},
{"req": 4096, "alloc": "G"},
{"req": 4096, "alloc": "G"},
{"req": 4096, "alloc": "G", "num": 2},
{"req": 20480, "alloc": "G"}
],
"traceTable": {

View File

@ -1,25 +1,16 @@
{
"version": 3,
"version": 4,
"invocation": {
"dmdEnvVar": "--mode=live --sample-below=127",
"mode": "live",
"sampleBelowSize": 127
},
"blockList": [
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A", "num": 4},
{"req": 4096, "alloc": "B"},
{"req": 4096, "alloc": "B"},
{"req": 4096, "alloc": "B"},
{"req": 4096, "alloc": "B"},
{"req": 4096, "alloc": "B", "num": 4},
{"req": 4096, "alloc": "C"},
{"req": 4096, "alloc": "C"},
{"req": 4096, "alloc": "C"},
{"req": 4096, "alloc": "C"},
{"req": 4096, "alloc": "C", "num": 4},
{"req": 4096, "alloc": "D"},
{"req": 4096, "alloc": "D"},

View File

@ -1,23 +1,18 @@
{
"version": 3,
"version": 4,
"invocation": {
"dmdEnvVar": "--mode=live --sample-below=63",
"mode": "live",
"sampleBelowSize": 63
},
"blockList": [
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A"},
{"req": 4096, "alloc": "A", "num": 3},
{"req": 4096, "alloc": "A"},
{"req": 8192, "alloc": "B"},
{"req": 8192, "alloc": "B"},
{"req": 4000, "slop": 96, "alloc": "C"},
{"req": 4000, "slop": 96, "alloc": "C"},
{"req": 4000, "slop": 96, "alloc": "C"},
{"req": 4000, "slop": 96, "alloc": "C"},
{"req": 4000, "slop": 96, "alloc": "C", "num": 4},
{"req": 4096, "alloc": "E"},
{"req": 4096, "alloc": "E"},
@ -26,16 +21,10 @@
{"req": 2000, "slop": 48, "alloc": "F"},
{"req": 1000, "slop": 24, "alloc": "F"},
{"req": 512, "alloc": "F"},
{"req": 512, "alloc": "F"},
{"req": 512, "alloc": "F"},
{"req": 512, "alloc": "F"},
{"req": 512, "alloc": "F", "num": 4},
{"req": 128, "alloc": "F"},
{ "alloc": "F"},
{"req": 64, "alloc": "F"},
{"req": 64, "alloc": "F"},
{"req": 64, "alloc": "F"},
{"req": 64, "alloc": "F"},
{"req": 64, "alloc": "F", "num": 4},
{ "alloc": "F"},
{"req": 4096, "alloc": "G"},

View File

@ -1,5 +1,5 @@
{
"version": 3,
"version": 4,
"invocation": {
"dmdEnvVar": null,
"mode": "dark-matter",

View File

@ -1,5 +1,5 @@
{
"version": 3,
"version": 4,
"invocation": {
"dmdEnvVar": "--mode=live",
"mode": "live",

View File

@ -957,7 +957,7 @@ public:
"Memory used by DMD's live block table.");
REPORT("explicit/dmd/dead-block-list",
sizes.mDeadBlockList,
sizes.mDeadBlockTable,
"Memory used by DMD's dead block list.");
#undef REPORT