зеркало из https://github.com/mozilla/gecko-dev.git
Bug 827523 (part 3) - DMD: Add --max-frames and --max-records options. r=jlebar.
--HG-- extra : rebase_source : 9840bcfa2d8fc1127a6f367a94e1d8488ae41c6a
This commit is contained in:
Родитель
d5ea3d0aef
Коммит
8685a2fb2b
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
@ -73,13 +73,6 @@ static const malloc_table_t* gMallocTable = nullptr;
|
|||
// This enables/disables DMD.
|
||||
static bool gIsDMDRunning = false;
|
||||
|
||||
enum Mode {
|
||||
Normal, // run normally
|
||||
Test, // do some basic correctness tests
|
||||
Stress // do some performance stress tests
|
||||
};
|
||||
static Mode gMode = Normal;
|
||||
|
||||
// This provides infallible allocations (they abort on OOM). We use it for all
|
||||
// of DMD's own allocations, which fall into the following three cases.
|
||||
// - Direct allocations (the easy case).
|
||||
|
@ -276,11 +269,64 @@ static char gBuf4[kBufLen];
|
|||
|
||||
static const size_t kNoSize = size_t(-1);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Options (Part 1)
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
class Options
|
||||
{
|
||||
template <typename T>
|
||||
struct NumOption
|
||||
{
|
||||
const T mDefault;
|
||||
const T mMax;
|
||||
T mActual;
|
||||
NumOption(T aDefault, T aMax)
|
||||
: mDefault(aDefault), mMax(aMax), mActual(aDefault)
|
||||
{}
|
||||
};
|
||||
|
||||
enum Mode {
|
||||
Normal, // run normally
|
||||
Test, // do some basic correctness tests
|
||||
Stress // do some performance stress tests
|
||||
};
|
||||
|
||||
char* mDMDEnvVar; // a saved copy, for printing during Dump()
|
||||
|
||||
NumOption<size_t> mSampleBelowSize;
|
||||
NumOption<uint32_t> mMaxFrames;
|
||||
NumOption<uint32_t> mMaxRecords;
|
||||
Mode mMode;
|
||||
|
||||
void BadArg(const char* aArg);
|
||||
static const char* ValueIfMatch(const char* aArg, const char* aOptionName);
|
||||
static bool GetLong(const char* aArg, const char* aOptionName,
|
||||
long aMin, long aMax, long* aN);
|
||||
|
||||
public:
|
||||
Options(const char* aDMDEnvVar);
|
||||
|
||||
const char* DMDEnvVar() const { return mDMDEnvVar; }
|
||||
|
||||
size_t SampleBelowSize() const { return mSampleBelowSize.mActual; }
|
||||
size_t MaxFrames() const { return mMaxFrames.mActual; }
|
||||
size_t MaxRecords() const { return mMaxRecords.mActual; }
|
||||
|
||||
void SetSampleBelowSize(size_t aN) { mSampleBelowSize.mActual = aN; }
|
||||
|
||||
bool IsTestMode() const { return mMode == Test; }
|
||||
bool IsStressMode() const { return mMode == Stress; }
|
||||
};
|
||||
|
||||
static Options *gOptions;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// The global lock
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// MutexBase implements the platform-specific parts of a mutex.
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
||||
class MutexBase
|
||||
|
@ -703,10 +749,14 @@ public:
|
|||
|
||||
class StackTrace
|
||||
{
|
||||
public:
|
||||
static const uint32_t MaxFrames = 24;
|
||||
|
||||
private:
|
||||
uint32_t mLength; // The number of PCs.
|
||||
void* mPcs[MaxFrames]; // The PCs themselves.
|
||||
void* mPcs[MaxFrames]; // The PCs themselves. If --max-frames is less
|
||||
// than 24, this array is bigger than necessary,
|
||||
// but that case is unusual.
|
||||
|
||||
public:
|
||||
StackTrace() : mLength(0) {}
|
||||
|
@ -800,8 +850,8 @@ StackTrace::Get(Thread* aT)
|
|||
{
|
||||
AutoUnlockState unlock;
|
||||
uint32_t skipFrames = 2;
|
||||
rv = NS_StackWalk(StackWalkCallback, skipFrames, MaxFrames, &tmp, 0,
|
||||
nullptr);
|
||||
rv = NS_StackWalk(StackWalkCallback, skipFrames,
|
||||
gOptions->MaxFrames(), &tmp, 0, nullptr);
|
||||
}
|
||||
|
||||
if (rv == NS_OK) {
|
||||
|
@ -1075,7 +1125,6 @@ GCStackTraces()
|
|||
// malloc/free callbacks
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static size_t gSampleBelowSize = 0;
|
||||
static size_t gSmallBlockActualSizeCounter = 0;
|
||||
|
||||
static void
|
||||
|
@ -1091,17 +1140,18 @@ AllocCallback(void* aPtr, size_t aReqSize, Thread* aT)
|
|||
AutoBlockIntercepts block(aT);
|
||||
|
||||
size_t actualSize = gMallocTable->malloc_usable_size(aPtr);
|
||||
size_t sampleBelowSize = gOptions->SampleBelowSize();
|
||||
|
||||
if (actualSize < gSampleBelowSize) {
|
||||
if (actualSize < sampleBelowSize) {
|
||||
// If this allocation is smaller than the sample-below size, increment the
|
||||
// cumulative counter. Then, if that counter now exceeds the sample size,
|
||||
// blame this allocation for gSampleBelowSize bytes. This precludes the
|
||||
// blame this allocation for |sampleBelowSize| bytes. This precludes the
|
||||
// measurement of slop.
|
||||
gSmallBlockActualSizeCounter += actualSize;
|
||||
if (gSmallBlockActualSizeCounter >= gSampleBelowSize) {
|
||||
gSmallBlockActualSizeCounter -= gSampleBelowSize;
|
||||
if (gSmallBlockActualSizeCounter >= sampleBelowSize) {
|
||||
gSmallBlockActualSizeCounter -= sampleBelowSize;
|
||||
|
||||
Block b(aPtr, gSampleBelowSize, StackTrace::Get(aT), /* sampled */ true);
|
||||
Block b(aPtr, sampleBelowSize, StackTrace::Get(aT), /* sampled */ true);
|
||||
(void)gBlockTable->putNew(aPtr, b);
|
||||
}
|
||||
} else {
|
||||
|
@ -1555,19 +1605,14 @@ FrameRecord::Print(const Writer& aWriter, LocationService* aLocService,
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// DMD start-up
|
||||
// Options (Part 2)
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void RunTestMode(FILE* fp);
|
||||
static void RunStressMode(FILE* fp);
|
||||
|
||||
static const char* gDMDEnvVar = nullptr;
|
||||
|
||||
// Given an |aOptionName| like "foo", succeed if |aArg| has the form "foo=blah"
|
||||
// (where "blah" is non-empty) and return the pointer to "blah". |aArg| can
|
||||
// have leading space chars (but not other whitespace).
|
||||
static const char*
|
||||
OptionValueIfMatch(const char* aArg, const char* aOptionName)
|
||||
const char*
|
||||
Options::ValueIfMatch(const char* aArg, const char* aOptionName)
|
||||
{
|
||||
MOZ_ASSERT(!isspace(*aArg)); // any leading whitespace should not remain
|
||||
size_t optionLen = strlen(aOptionName);
|
||||
|
@ -1580,11 +1625,11 @@ OptionValueIfMatch(const char* aArg, const char* aOptionName)
|
|||
|
||||
// Extracts a |long| value for an option from an argument. It must be within
|
||||
// the range |aMin..aMax| (inclusive).
|
||||
static bool
|
||||
OptionLong(const char* aArg, const char* aOptionName, long aMin, long aMax,
|
||||
long* aN)
|
||||
bool
|
||||
Options::GetLong(const char* aArg, const char* aOptionName,
|
||||
long aMin, long aMax, long* aN)
|
||||
{
|
||||
if (const char* optionValue = OptionValueIfMatch(aArg, aOptionName)) {
|
||||
if (const char* optionValue = ValueIfMatch(aArg, aOptionName)) {
|
||||
char* endPtr;
|
||||
*aN = strtol(optionValue, &endPtr, /* base */ 10);
|
||||
if (!*endPtr && aMin <= *aN && *aN <= aMax &&
|
||||
|
@ -1595,95 +1640,22 @@ OptionLong(const char* aArg, const char* aOptionName, long aMin, long aMax,
|
|||
return false;
|
||||
}
|
||||
|
||||
static const size_t gMaxSampleBelowSize = 100 * 1000 * 1000; // bytes
|
||||
|
||||
// Default to sampling with a sample-below size that's a prime number close to
|
||||
// 4096.
|
||||
// The sample-below default is a prime number close to 4096.
|
||||
// - Why that size? Because it's *much* faster but only moderately less precise
|
||||
// than a size of 1.
|
||||
// - Why prime? Because it makes our sampling more random. If we used a size
|
||||
// of 4096, for example, then our alloc counter would only take on even
|
||||
// values, because jemalloc always rounds up requests sizes. In contrast, a
|
||||
// prime size will explore all possible values of the alloc counter.
|
||||
//
|
||||
// Using a sample-below size ~= 4096 is much faster than using a sample-below
|
||||
// size of 1, and it's not much less accurate in practice, so it's a reasonable
|
||||
// default.
|
||||
//
|
||||
// Using a prime sample-below size makes our sampling more random. If we used
|
||||
// instead a sample-below size of 4096, for example, then if all our allocation
|
||||
// sizes were even (which they likely are, due to how jemalloc rounds up), our
|
||||
// alloc counter would take on only even values.
|
||||
//
|
||||
// In contrast, using a prime sample-below size lets us explore all possible
|
||||
// values of the alloc counter.
|
||||
static const size_t gDefaultSampleBelowSize = 4093;
|
||||
|
||||
static void
|
||||
BadArg(const char* aArg)
|
||||
Options::Options(const char* aDMDEnvVar)
|
||||
: mDMDEnvVar(InfallibleAllocPolicy::strdup_(aDMDEnvVar)),
|
||||
mSampleBelowSize(4093, 100 * 100 * 1000),
|
||||
mMaxFrames(StackTrace::MaxFrames, StackTrace::MaxFrames),
|
||||
mMaxRecords(1000, 1000000),
|
||||
mMode(Normal)
|
||||
{
|
||||
StatusMsg("\n");
|
||||
StatusMsg("Bad entry in the $DMD environment variable: '%s'.\n", aArg);
|
||||
StatusMsg("\n");
|
||||
StatusMsg("Valid values of $DMD are:\n");
|
||||
StatusMsg("- undefined or \"\" or \"0\", which disables DMD, or\n");
|
||||
StatusMsg("- \"1\", which enables it with the default options, or\n");
|
||||
StatusMsg("- a whitespace-separated list of |--option=val| entries, which\n");
|
||||
StatusMsg(" enables it with non-default options.\n");
|
||||
StatusMsg("\n");
|
||||
StatusMsg("The following options are allowed; defaults are shown in [].\n");
|
||||
StatusMsg(" --sample-below=<1..%d> Sample blocks smaller than this [%d]\n"
|
||||
" (prime numbers recommended).\n",
|
||||
int(gMaxSampleBelowSize), int(gDefaultSampleBelowSize));
|
||||
StatusMsg(" --mode=<normal|test|stress> Which mode to run in? [normal]\n");
|
||||
StatusMsg("\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
static void
|
||||
NopStackWalkCallback(void* aPc, void* aSp, void* aClosure)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
// Note that fopen() can allocate.
|
||||
static FILE*
|
||||
OpenOutputFile(const char* aFilename)
|
||||
{
|
||||
FILE* fp = fopen(aFilename, "w");
|
||||
if (!fp) {
|
||||
StatusMsg("can't create %s file: %s\n", aFilename, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
// WARNING: this function runs *very* early -- before all static initializers
|
||||
// have run. For this reason, non-scalar globals such as gStateLock and
|
||||
// gStackTraceTable are allocated dynamically (so we can guarantee their
|
||||
// construction in this function) rather than statically.
|
||||
static void
|
||||
Init(const malloc_table_t* aMallocTable)
|
||||
{
|
||||
MOZ_ASSERT(!gIsDMDRunning);
|
||||
|
||||
gMallocTable = aMallocTable;
|
||||
|
||||
// Set defaults of things that can be affected by the $DMD env var.
|
||||
gMode = Normal;
|
||||
gSampleBelowSize = gDefaultSampleBelowSize;
|
||||
|
||||
// DMD is controlled by the |DMD| environment variable.
|
||||
// - If it's unset or empty or "0", DMD doesn't run.
|
||||
// - Otherwise, the contents dictate DMD's behaviour.
|
||||
|
||||
char* e = getenv("DMD");
|
||||
|
||||
StatusMsg("$DMD = '%s'\n", e);
|
||||
|
||||
if (!e || strcmp(e, "") == 0 || strcmp(e, "0") == 0) {
|
||||
StatusMsg("DMD is not enabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Save it so we can print it in Dump().
|
||||
gDMDEnvVar = e = InfallibleAllocPolicy::strdup_(e);
|
||||
|
||||
char* e = mDMDEnvVar;
|
||||
if (strcmp(e, "1") != 0) {
|
||||
bool isEnd = false;
|
||||
while (!isEnd) {
|
||||
|
@ -1706,15 +1678,21 @@ Init(const malloc_table_t* aMallocTable)
|
|||
|
||||
// Handle arg
|
||||
long myLong;
|
||||
if (OptionLong(arg, "--sample-below", 1, gMaxSampleBelowSize, &myLong)) {
|
||||
gSampleBelowSize = myLong;
|
||||
if (GetLong(arg, "--sample-below", 1, mSampleBelowSize.mMax, &myLong)) {
|
||||
mSampleBelowSize.mActual = myLong;
|
||||
|
||||
} else if (GetLong(arg, "--max-frames", 1, mMaxFrames.mMax, &myLong)) {
|
||||
mMaxFrames.mActual = myLong;
|
||||
|
||||
} else if (GetLong(arg, "--max-records", 1, mMaxRecords.mMax, &myLong)) {
|
||||
mMaxRecords.mActual = myLong;
|
||||
|
||||
} else if (strcmp(arg, "--mode=normal") == 0) {
|
||||
gMode = Normal;
|
||||
mMode = Options::Normal;
|
||||
} else if (strcmp(arg, "--mode=test") == 0) {
|
||||
gMode = Test;
|
||||
mMode = Options::Test;
|
||||
} else if (strcmp(arg, "--mode=stress") == 0) {
|
||||
gMode = Stress;
|
||||
mMode = Options::Stress;
|
||||
|
||||
} else if (strcmp(arg, "") == 0) {
|
||||
// This can only happen if there is trailing whitespace. Ignore.
|
||||
|
@ -1728,8 +1706,87 @@ Init(const malloc_table_t* aMallocTable)
|
|||
*e = replacedChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finished parsing $DMD.
|
||||
void
|
||||
Options::BadArg(const char* aArg)
|
||||
{
|
||||
StatusMsg("\n");
|
||||
StatusMsg("Bad entry in the $DMD environment variable: '%s'.\n", aArg);
|
||||
StatusMsg("\n");
|
||||
StatusMsg("Valid values of $DMD are:\n");
|
||||
StatusMsg("- undefined or \"\" or \"0\", which disables DMD, or\n");
|
||||
StatusMsg("- \"1\", which enables it with the default options, or\n");
|
||||
StatusMsg("- a whitespace-separated list of |--option=val| entries, which\n");
|
||||
StatusMsg(" enables it with non-default options.\n");
|
||||
StatusMsg("\n");
|
||||
StatusMsg("The following options are allowed; defaults are shown in [].\n");
|
||||
StatusMsg(" --sample-below=<1..%d> Sample blocks smaller than this [%d]\n",
|
||||
int(mSampleBelowSize.mMax),
|
||||
int(mSampleBelowSize.mDefault));
|
||||
StatusMsg(" (prime numbers are recommended)\n");
|
||||
StatusMsg(" --max-frames=<1..%d> Max. depth of stack traces [%d]\n",
|
||||
int(mMaxFrames.mMax),
|
||||
int(mMaxFrames.mDefault));
|
||||
StatusMsg(" --max-records=<1..%u> Max. number of records printed [%u]\n",
|
||||
mMaxRecords.mMax,
|
||||
mMaxRecords.mDefault);
|
||||
StatusMsg(" --mode=<normal|test|stress> Mode of operation [normal]\n");
|
||||
StatusMsg("\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// DMD start-up
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
static void
|
||||
NopStackWalkCallback(void* aPc, void* aSp, void* aClosure)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
// Note that fopen() can allocate.
|
||||
static FILE*
|
||||
OpenOutputFile(const char* aFilename)
|
||||
{
|
||||
FILE* fp = fopen(aFilename, "w");
|
||||
if (!fp) {
|
||||
StatusMsg("can't create %s file: %s\n", aFilename, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
static void RunTestMode(FILE* fp);
|
||||
static void RunStressMode(FILE* fp);
|
||||
|
||||
// WARNING: this function runs *very* early -- before all static initializers
|
||||
// have run. For this reason, non-scalar globals such as gStateLock and
|
||||
// gStackTraceTable are allocated dynamically (so we can guarantee their
|
||||
// construction in this function) rather than statically.
|
||||
static void
|
||||
Init(const malloc_table_t* aMallocTable)
|
||||
{
|
||||
MOZ_ASSERT(!gIsDMDRunning);
|
||||
|
||||
gMallocTable = aMallocTable;
|
||||
|
||||
// DMD is controlled by the |DMD| environment variable.
|
||||
// - If it's unset or empty or "0", DMD doesn't run.
|
||||
// - Otherwise, the contents dictate DMD's behaviour.
|
||||
|
||||
char* e = getenv("DMD");
|
||||
StatusMsg("$DMD = '%s'\n", e);
|
||||
|
||||
if (!e || strcmp(e, "") == 0 || strcmp(e, "0") == 0) {
|
||||
StatusMsg("DMD is not enabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse $DMD env var.
|
||||
gOptions = InfallibleAllocPolicy::new_<Options>(e);
|
||||
|
||||
StatusMsg("DMD is enabled\n");
|
||||
|
||||
|
@ -1756,7 +1813,7 @@ Init(const malloc_table_t* aMallocTable)
|
|||
gBlockTable = InfallibleAllocPolicy::new_<BlockTable>();
|
||||
gBlockTable->init(8192);
|
||||
|
||||
if (gMode == Test) {
|
||||
if (gOptions->IsTestMode()) {
|
||||
// OpenOutputFile() can allocate. So do this before setting
|
||||
// gIsDMDRunning so those allocations don't show up in our results. Once
|
||||
// gIsDMDRunning is set we are intercepting malloc et al. in earnest.
|
||||
|
@ -1770,7 +1827,7 @@ Init(const malloc_table_t* aMallocTable)
|
|||
exit(0);
|
||||
}
|
||||
|
||||
if (gMode == Stress) {
|
||||
if (gOptions->IsStressMode()) {
|
||||
FILE* fp = OpenOutputFile("stress.dmd");
|
||||
gIsDMDRunning = true;
|
||||
|
||||
|
@ -1857,23 +1914,23 @@ PrintSortedRecords(const Writer& aWriter, LocationService* aLocService,
|
|||
return;
|
||||
}
|
||||
|
||||
StatusMsg(" printing %s stack %s record array...\n", astr, kind);
|
||||
size_t cumulativeUsableSize = 0;
|
||||
|
||||
// Limit the number of records printed, because fix-linux-stack.pl is too
|
||||
// damn slow. Note that we don't break out of this loop because we need to
|
||||
// keep adding to |cumulativeUsableSize|.
|
||||
static const uint32_t MaxRecords = 1000;
|
||||
uint32_t numRecords = recordArray.length();
|
||||
|
||||
StatusMsg(" printing %s stack %s record array...\n", astr, kind);
|
||||
size_t cumulativeUsableSize = 0;
|
||||
uint32_t maxRecords = gOptions->MaxRecords();
|
||||
for (uint32_t i = 0; i < numRecords; i++) {
|
||||
const Record* r = recordArray[i];
|
||||
cumulativeUsableSize += r->GetRecordSize().Usable();
|
||||
if (i < MaxRecords) {
|
||||
if (i < maxRecords) {
|
||||
r->Print(aWriter, aLocService, i+1, numRecords, aStr, astr,
|
||||
aCategoryUsableSize, cumulativeUsableSize, aTotalUsableSize);
|
||||
} else if (i == MaxRecords) {
|
||||
} else if (i == maxRecords) {
|
||||
W("%s: stopping after %s stack %s records\n\n", aStr,
|
||||
Show(MaxRecords, gBuf1, kBufLen), kind);
|
||||
Show(maxRecords, gBuf1, kBufLen), kind);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2060,8 +2117,9 @@ Dump(Writer aWriter)
|
|||
unreportedNumBlocks + onceReportedNumBlocks + twiceReportedNumBlocks;
|
||||
|
||||
WriteTitle("Invocation\n");
|
||||
W("$DMD = '%s'\n", gDMDEnvVar);
|
||||
W("Sample-below size = %lld\n\n", (long long)(gSampleBelowSize));
|
||||
W("$DMD = '%s'\n", gOptions->DMDEnvVar());
|
||||
W("Sample-below size = %lld\n\n",
|
||||
(long long)(gOptions->SampleBelowSize()));
|
||||
|
||||
// Allocate this on the heap instead of the stack because it's fairly large.
|
||||
LocationService* locService = InfallibleAllocPolicy::new_<LocationService>();
|
||||
|
@ -2110,7 +2168,7 @@ Dump(Writer aWriter)
|
|||
W("\n");
|
||||
|
||||
// Stats are non-deterministic, so don't show them in test mode.
|
||||
if (gMode != Test) {
|
||||
if (!gOptions->IsTestMode()) {
|
||||
Sizes sizes;
|
||||
SizeOfInternal(&sizes);
|
||||
|
||||
|
@ -2221,7 +2279,7 @@ RunTestMode(FILE* fp)
|
|||
Writer writer(FpWrite, fp);
|
||||
|
||||
// The first part of this test requires sampling to be disabled.
|
||||
gSampleBelowSize = 1;
|
||||
gOptions->SetSampleBelowSize(1);
|
||||
|
||||
// 0th Dump. Zero for everything.
|
||||
Dump(writer);
|
||||
|
@ -2359,10 +2417,7 @@ RunTestMode(FILE* fp)
|
|||
// Clear all knowledge of existing blocks to give us a clean slate.
|
||||
gBlockTable->clear();
|
||||
|
||||
// Reset the counter just in case |sample-size| was specified in $DMD.
|
||||
// Otherwise the assertions fail.
|
||||
gSmallBlockActualSizeCounter = 0;
|
||||
gSampleBelowSize = 128;
|
||||
gOptions->SetSampleBelowSize(128);
|
||||
|
||||
char* s;
|
||||
|
||||
|
@ -2480,7 +2535,7 @@ RunStressMode(FILE* fp)
|
|||
Writer writer(FpWrite, fp);
|
||||
|
||||
// Disable sampling for maximum stress.
|
||||
gSampleBelowSize = 1;
|
||||
gOptions->SetSampleBelowSize(1);
|
||||
|
||||
stress1(); stress1(); stress1(); stress1(); stress1();
|
||||
stress1(); stress1(); stress1(); stress1(); stress1();
|
||||
|
|
Загрузка…
Ссылка в новой задаче