@@ -34,6 +34,7 @@ TRACELOGGING_DEFINE_PROVIDER(g_hEtwProvider,
34
34
(0xca13db84 , 0xd0a9 , 0x5145 , 0xfc , 0xa4 , 0x46 , 0x8d , 0xa9 , 0x2f , 0xdc , 0x2d ));
35
35
36
36
SystemInformation g_SystemInformation;
37
+ ULONG g_ExperimentFlags;
37
38
38
39
UINT64 PerfTimer::GetTime ()
39
40
{
@@ -99,12 +100,12 @@ UINT64 PerfTimer::SecondsToPerfTime(const double seconds)
99
100
Random::Random (UINT64 ulSeed)
100
101
{
101
102
UINT32 i;
102
-
103
+
103
104
_ulState[0 ] = 0xf1ea5eed ;
104
105
_ulState[1 ] = ulSeed;
105
106
_ulState[2 ] = ulSeed;
106
107
_ulState[3 ] = ulSeed;
107
-
108
+
108
109
for (i = 0 ; i < 20 ; i++) {
109
110
Rand64 ();
110
111
}
@@ -138,10 +139,10 @@ void Random::RandBuffer(BYTE *pBuffer, UINT32 ulLength, bool fPseudoRandomOkay)
138
139
pBuffer += Remaining * 8 ;
139
140
140
141
if (fPseudoRandomOkay ) {
141
-
142
+
142
143
//
143
144
// 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
145
146
// numbers at a time for optimal cache line alignment.
146
147
// Only do this if the caller is okay with numbers that
147
148
// aren't independent. A detailed analysis of the data
@@ -150,7 +151,7 @@ void Random::RandBuffer(BYTE *pBuffer, UINT32 ulLength, bool fPseudoRandomOkay)
150
151
// instance it's unlikely compression algorithms will be
151
152
// able to detect this and utilize it).
152
153
//
153
-
154
+
154
155
while (Remaining > 16 ) {
155
156
r1 = Rand64 ();
156
157
r2 = Rand64 ();
@@ -195,7 +196,7 @@ void Random::RandBuffer(BYTE *pBuffer, UINT32 ulLength, bool fPseudoRandomOkay)
195
196
//
196
197
// Fill in the tail of the buffer
197
198
//
198
-
199
+
199
200
while (Remaining >= 4 ) {
200
201
r1 = Rand64 ();
201
202
r2 = Rand64 ();
@@ -241,7 +242,7 @@ string ThreadTarget::GetXml(UINT32 indent) const
241
242
{
242
243
char buffer[4096 ];
243
244
string sXml ;
244
-
245
+
245
246
AddXmlInc (sXml , " <ThreadTarget>\n " );
246
247
247
248
sprintf_s (buffer, _countof (buffer), " <Thread>%u</Thread>\n " , _ulThread);
@@ -262,7 +263,7 @@ string Target::GetXml(UINT32 indent) const
262
263
{
263
264
char buffer[4096 ];
264
265
string sXml ;
265
-
266
+
266
267
AddXmlInc (sXml , " <Target>\n " );
267
268
AddXml (sXml , " <Path>" + _sPath + " </Path>\n " );
268
269
@@ -295,7 +296,7 @@ string Target::GetXml(UINT32 indent) const
295
296
AddXml (sXml , " <WriteThrough>true</WriteThrough>\n " );
296
297
break ;
297
298
}
298
-
299
+
299
300
// MemoryMappedIoMode::Off is implied default
300
301
switch (_memoryMappedIoMode)
301
302
{
@@ -416,7 +417,7 @@ string Target::GetXml(UINT32 indent) const
416
417
{
417
418
sprintf_s (buffer, _countof (buffer), " <StrideSize>%I64u</StrideSize>\n " , GetBlockAlignmentInBytes ());
418
419
AddXml (sXml , buffer);
419
-
420
+
420
421
AddXml (sXml , _fInterlockedSequential ?
421
422
" <InterlockedSequential>true</InterlockedSequential>\n " :
422
423
" <InterlockedSequential>false</InterlockedSequential>\n " );
@@ -672,6 +673,13 @@ string Profile::GetXml(UINT32 indent) const
672
673
sprintf_s (buffer, _countof (buffer), " <Progress>%u</Progress>\n " , _dwProgress);
673
674
AddXml (sXml , buffer);
674
675
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
+
675
683
if (_resultsFormat == ResultsFormat::Text)
676
684
{
677
685
AddXml (sXml , " <ResultFormat>text</ResultFormat>\n " );
@@ -686,6 +694,12 @@ string Profile::GetXml(UINT32 indent) const
686
694
}
687
695
688
696
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
+
689
703
if (_precreateFiles == PrecreateFiles::UseMaxSize)
690
704
{
691
705
AddXml (sXml , " <PrecreateFiles>UseMaxSize</PrecreateFiles>\n " );
@@ -763,7 +777,7 @@ bool Profile::Validate(bool fSingleSpec, SystemInformation *pSystem) const
763
777
}
764
778
if (fOk && !pSystem->processorTopology ._vProcessorGroupInformation [Affinity.wGroup ].IsProcessorValid (Affinity.bProc ))
765
779
{
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 " ,
767
781
Affinity.wGroup ,
768
782
Affinity.bProc ,
769
783
pSystem->processorTopology ._vProcessorGroupInformation [Affinity.wGroup ]._maximumProcessorCount );
@@ -773,22 +787,27 @@ bool Profile::Validate(bool fSingleSpec, SystemInformation *pSystem) const
773
787
774
788
if (fOk && !pSystem->processorTopology ._vProcessorGroupInformation [Affinity.wGroup ].IsProcessorActive (Affinity.bProc ))
775
789
{
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 " ,
777
791
Affinity.wGroup ,
778
792
Affinity.bProc ,
779
- pSystem->processorTopology ._vProcessorGroupInformation [Affinity.wGroup ]._activeProcessorMask );
793
+ ( void *) pSystem->processorTopology ._vProcessorGroupInformation [Affinity.wGroup ]._activeProcessorMask );
780
794
781
795
fOk = false ;
782
796
}
783
797
}
784
798
}
785
799
800
+ // ISSUE: many of the following validation errors are stated in cmdline terms, which is not helpful for XML
801
+
786
802
if (timeSpan.GetDisableAffinity () && timeSpan.GetAffinityAssignments ().size () > 0 )
787
803
{
788
804
fprintf (stderr, " ERROR: -n and -a parameters cannot be used together\n " );
789
805
fOk = false ;
790
806
}
791
807
808
+ // ISSUE: with XML and the following the target specification validation it would be useful to say what
809
+ // target they're for
810
+
792
811
for (const auto & target : timeSpan.GetTargets ())
793
812
{
794
813
const bool targetHasMultipleThreads = (timeSpan.GetThreadCount () > 1 ) || (target.GetThreadsPerFile () > 1 );
@@ -881,7 +900,7 @@ bool Profile::Validate(bool fSingleSpec, SystemInformation *pSystem) const
881
900
fprintf (stderr, " ERROR: random distribution ranges (-rd) do not apply to sequential-only IO patterns\n " );
882
901
fOk = false ;
883
902
}
884
-
903
+
885
904
if (target.GetUseParallelAsyncIO () && target.GetRequestCount () == 1 )
886
905
{
887
906
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
958
977
// Note that absolute range needs no additional validation - known nonzero/large enough for IO
959
978
if (target.GetDistributionType () == DistributionType::Percent)
960
979
{
961
- if (targetAcc + r._dst .second > 100 )
980
+ if (targetAcc + r._dst .second > 100 )
962
981
{
963
982
fprintf (stderr, " ERROR: invalid random distribution Target%% %I64u: can be at most %I64u - total must be <= 100%%\n " , r._dst .second , 100 - targetAcc);
964
983
fOk = false ;
@@ -1036,10 +1055,20 @@ bool Profile::Validate(bool fSingleSpec, SystemInformation *pSystem) const
1036
1055
}
1037
1056
}
1038
1057
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.
1043
1072
if (fSingleSpec )
1044
1073
{
1045
1074
break ;
@@ -1113,7 +1142,7 @@ BYTE* ThreadParameters::GetReadBuffer(size_t iTarget, size_t iRequest)
1113
1142
BYTE* ThreadParameters::GetWriteBuffer (size_t iTarget, size_t iRequest)
1114
1143
{
1115
1144
BYTE *pBuffer = nullptr ;
1116
-
1145
+
1117
1146
Target& target (vTargets[iTarget]);
1118
1147
size_t cb = static_cast <size_t >(target.GetRandomDataWriteBufferSize ());
1119
1148
if (cb == 0 )
0 commit comments