Skip to content

Commit 2ac91a4

Browse files
dl2nFengLiMSFeng LiDan Lovinger
authored
DISKSPD 2.2 (#209)
* add sorted data to Historgram (#197) Co-authored-by: Feng Li <[email protected]> * multiple updates from msft internal 2.1.2 prerelease flush stdout to force XML/text results through prior to process exit fix issues identified by vs2019 build loop - 64->32 downcast, minor printf issues, _snprintf -> _snprintf_s timestamp prefixes for all verbose output dump specific time intervals for warmup/measured/cooldown to validate v. expected @ actual time of use/measurement only emit warmup/cooldown verbose output notes if there is nonzero warmup/cooldown specified in the profile minor cleanup of load thread verbose output so that everything has a consistent thread N: prefix histogram processing speedups, about 60% for XML (all percentiles) implicitly seal/sort histogram on first read operation, reset on subsequent inserts; save repeated re-sorting save histogram percentile iterator so that asecending percentile queries do not restart from lowest sample min/max in terms of begin/rbegin iterator show latency histogram bucket counts in XML results; potential work to moderate histogram size unit test coverage * DISKSPD 2.2 --------- Co-authored-by: FengLiMS <[email protected]> Co-authored-by: Feng Li <[email protected]> Co-authored-by: Dan Lovinger <[email protected]>
1 parent 206bae5 commit 2ac91a4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+13862
-12590
lines changed

CmdLineParser/CmdLineParser.cpp

Lines changed: 2070 additions & 1959 deletions
Large diffs are not rendered by default.

CmdRequestCreator/diskspd.rc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include <windows.h>
2-
#include "Common.h"
2+
#include "Version.h"
33

44
DISKSPD.XSD HTML "..\\XmlProfileParser\\diskspd.xsd"
55

Common/Common.cpp

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ TRACELOGGING_DEFINE_PROVIDER(g_hEtwProvider,
3434
(0xca13db84, 0xd0a9, 0x5145, 0xfc, 0xa4, 0x46, 0x8d, 0xa9, 0x2f, 0xdc, 0x2d));
3535

3636
SystemInformation g_SystemInformation;
37+
ULONG g_ExperimentFlags;
3738

3839
UINT64 PerfTimer::GetTime()
3940
{
@@ -99,12 +100,12 @@ UINT64 PerfTimer::SecondsToPerfTime(const double seconds)
99100
Random::Random(UINT64 ulSeed)
100101
{
101102
UINT32 i;
102-
103+
103104
_ulState[0] = 0xf1ea5eed;
104105
_ulState[1] = ulSeed;
105106
_ulState[2] = ulSeed;
106107
_ulState[3] = ulSeed;
107-
108+
108109
for (i = 0; i < 20; i++) {
109110
Rand64();
110111
}
@@ -138,10 +139,10 @@ void Random::RandBuffer(BYTE *pBuffer, UINT32 ulLength, bool fPseudoRandomOkay)
138139
pBuffer += Remaining * 8;
139140

140141
if (fPseudoRandomOkay) {
141-
142+
142143
//
143144
// Generate 5 random numbers and then mix them to produce
144-
// 16 random (but correlated) numbers. We want to do 16
145+
// 16 random (but correlated) numbers. We want to do 16
145146
// numbers at a time for optimal cache line alignment.
146147
// Only do this if the caller is okay with numbers that
147148
// aren't independent. A detailed analysis of the data
@@ -150,7 +151,7 @@ void Random::RandBuffer(BYTE *pBuffer, UINT32 ulLength, bool fPseudoRandomOkay)
150151
// instance it's unlikely compression algorithms will be
151152
// able to detect this and utilize it).
152153
//
153-
154+
154155
while (Remaining > 16) {
155156
r1 = Rand64();
156157
r2 = Rand64();
@@ -195,7 +196,7 @@ void Random::RandBuffer(BYTE *pBuffer, UINT32 ulLength, bool fPseudoRandomOkay)
195196
//
196197
// Fill in the tail of the buffer
197198
//
198-
199+
199200
while (Remaining >= 4) {
200201
r1 = Rand64();
201202
r2 = Rand64();
@@ -241,7 +242,7 @@ string ThreadTarget::GetXml(UINT32 indent) const
241242
{
242243
char buffer[4096];
243244
string sXml;
244-
245+
245246
AddXmlInc(sXml, "<ThreadTarget>\n");
246247

247248
sprintf_s(buffer, _countof(buffer), "<Thread>%u</Thread>\n", _ulThread);
@@ -262,7 +263,7 @@ string Target::GetXml(UINT32 indent) const
262263
{
263264
char buffer[4096];
264265
string sXml;
265-
266+
266267
AddXmlInc(sXml, "<Target>\n");
267268
AddXml(sXml, "<Path>" + _sPath + "</Path>\n");
268269

@@ -295,7 +296,7 @@ string Target::GetXml(UINT32 indent) const
295296
AddXml(sXml, "<WriteThrough>true</WriteThrough>\n");
296297
break;
297298
}
298-
299+
299300
// MemoryMappedIoMode::Off is implied default
300301
switch (_memoryMappedIoMode)
301302
{
@@ -416,7 +417,7 @@ string Target::GetXml(UINT32 indent) const
416417
{
417418
sprintf_s(buffer, _countof(buffer), "<StrideSize>%I64u</StrideSize>\n", GetBlockAlignmentInBytes());
418419
AddXml(sXml, buffer);
419-
420+
420421
AddXml(sXml, _fInterlockedSequential ?
421422
"<InterlockedSequential>true</InterlockedSequential>\n" :
422423
"<InterlockedSequential>false</InterlockedSequential>\n");
@@ -672,6 +673,13 @@ string Profile::GetXml(UINT32 indent) const
672673
sprintf_s(buffer, _countof(buffer), "<Progress>%u</Progress>\n", _dwProgress);
673674
AddXml(sXml, buffer);
674675

676+
if (g_ExperimentFlags)
677+
{
678+
// only output if on so that downlevel doesn't get (and fail: not in downlevel xsd) unless actually specified
679+
sprintf_s(buffer, _countof(buffer), "<ExperimentFlags>%u</ExperimentFlags>\n", g_ExperimentFlags);
680+
AddXml(sXml, buffer);
681+
}
682+
675683
if (_resultsFormat == ResultsFormat::Text)
676684
{
677685
AddXml(sXml, "<ResultFormat>text</ResultFormat>\n");
@@ -686,6 +694,12 @@ string Profile::GetXml(UINT32 indent) const
686694
}
687695

688696
AddXml(sXml, _fVerbose ? "<Verbose>true</Verbose>\n" : "<Verbose>false</Verbose>\n");
697+
if (_fVerboseStats)
698+
{
699+
// only output if on so that downlevel doesn't get (and fail: not in downlevel xsd) unless actually specified
700+
AddXml(sXml, "<VerboseStats>true</VerboseStats>\n");
701+
}
702+
689703
if (_precreateFiles == PrecreateFiles::UseMaxSize)
690704
{
691705
AddXml(sXml, "<PrecreateFiles>UseMaxSize</PrecreateFiles>\n");
@@ -763,7 +777,7 @@ bool Profile::Validate(bool fSingleSpec, SystemInformation *pSystem) const
763777
}
764778
if (fOk && !pSystem->processorTopology._vProcessorGroupInformation[Affinity.wGroup].IsProcessorValid(Affinity.bProc))
765779
{
766-
fprintf(stderr, "ERROR: affinity assignment to group %u core %u not possible; group only has %u cores\n",
780+
fprintf(stderr, "ERROR: affinity assignment to group %u cpu %u not possible; group has a max of %u cpus\n",
767781
Affinity.wGroup,
768782
Affinity.bProc,
769783
pSystem->processorTopology._vProcessorGroupInformation[Affinity.wGroup]._maximumProcessorCount);
@@ -773,22 +787,27 @@ bool Profile::Validate(bool fSingleSpec, SystemInformation *pSystem) const
773787

774788
if (fOk && !pSystem->processorTopology._vProcessorGroupInformation[Affinity.wGroup].IsProcessorActive(Affinity.bProc))
775789
{
776-
fprintf(stderr, "ERROR: affinity assignment to group %u core %u not possible; core is not active (current mask 0x%Ix)\n",
790+
fprintf(stderr, "ERROR: affinity assignment to group %u cpu %u not possible; cpu is not active (current mask 0x%p)\n",
777791
Affinity.wGroup,
778792
Affinity.bProc,
779-
pSystem->processorTopology._vProcessorGroupInformation[Affinity.wGroup]._activeProcessorMask);
793+
(void *) pSystem->processorTopology._vProcessorGroupInformation[Affinity.wGroup]._activeProcessorMask);
780794

781795
fOk = false;
782796
}
783797
}
784798
}
785799

800+
// ISSUE: many of the following validation errors are stated in cmdline terms, which is not helpful for XML
801+
786802
if (timeSpan.GetDisableAffinity() && timeSpan.GetAffinityAssignments().size() > 0)
787803
{
788804
fprintf(stderr, "ERROR: -n and -a parameters cannot be used together\n");
789805
fOk = false;
790806
}
791807

808+
// ISSUE: with XML and the following the target specification validation it would be useful to say what
809+
// target they're for
810+
792811
for (const auto& target : timeSpan.GetTargets())
793812
{
794813
const bool targetHasMultipleThreads = (timeSpan.GetThreadCount() > 1) || (target.GetThreadsPerFile() > 1);
@@ -881,7 +900,7 @@ bool Profile::Validate(bool fSingleSpec, SystemInformation *pSystem) const
881900
fprintf(stderr, "ERROR: random distribution ranges (-rd) do not apply to sequential-only IO patterns\n");
882901
fOk = false;
883902
}
884-
903+
885904
if (target.GetUseParallelAsyncIO() && target.GetRequestCount() == 1)
886905
{
887906
fprintf(stderr, "WARNING: -p does not have effect unless outstanding I/O count (-o) is > 1\n");
@@ -958,7 +977,7 @@ bool Profile::Validate(bool fSingleSpec, SystemInformation *pSystem) const
958977
// Note that absolute range needs no additional validation - known nonzero/large enough for IO
959978
if (target.GetDistributionType() == DistributionType::Percent)
960979
{
961-
if (targetAcc + r._dst.second > 100)
980+
if (targetAcc + r._dst.second > 100)
962981
{
963982
fprintf(stderr, "ERROR: invalid random distribution Target%% %I64u: can be at most %I64u - total must be <= 100%%\n", r._dst.second, 100 - targetAcc);
964983
fOk = false;
@@ -1036,10 +1055,20 @@ bool Profile::Validate(bool fSingleSpec, SystemInformation *pSystem) const
10361055
}
10371056
}
10381057

1039-
// in the cases where there is only a single configuration specified for each target (e.g., cmdline),
1040-
// currently there are no validations specific to individual targets (e.g., pre-existing files)
1041-
// so we can stop validation now. this allows us to only warn/error once, as opposed to repeating
1042-
// it for each target.
1058+
// Note that this error is only possible with -f or XML. The -Bbase:length form is immune.
1059+
if (target.GetMaxFileSize() && target.GetMaxFileSize() <= target.GetBaseFileOffsetInBytes())
1060+
{
1061+
fprintf(stderr, "ERROR: maximum (-f) target offset must be greater than base (-B)\n");
1062+
fOk = false;
1063+
}
1064+
1065+
// If we know there is only a single target specification (the parameters which apply to targets) shared
1066+
// across the one or more targets, we can stop. In practical terms this is the command line case - for
1067+
// XML we don't know, and do need to keep going. This early exit lets us avoid repeating the same sets
1068+
// of error messages per each target we would otherwise loop over.
1069+
//
1070+
// If we ever did target property validation (say, v. its size) we'd want to divide out the validations
1071+
// into parameter-only v. parameter/property cases for similar reasons.
10431072
if (fSingleSpec)
10441073
{
10451074
break;
@@ -1113,7 +1142,7 @@ BYTE* ThreadParameters::GetReadBuffer(size_t iTarget, size_t iRequest)
11131142
BYTE* ThreadParameters::GetWriteBuffer(size_t iTarget, size_t iRequest)
11141143
{
11151144
BYTE *pBuffer = nullptr;
1116-
1145+
11171146
Target& target(vTargets[iTarget]);
11181147
size_t cb = static_cast<size_t>(target.GetRandomDataWriteBufferSize());
11191148
if (cb == 0)

0 commit comments

Comments
 (0)