Добавлена папка source в CristalDiskMark
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "Common.h"
|
||||
|
||||
namespace UnitTests { class CmdLineParserUnitTests; }
|
||||
|
||||
class CmdLineParser
|
||||
{
|
||||
public:
|
||||
CmdLineParser();
|
||||
~CmdLineParser();
|
||||
|
||||
bool ParseCmdLine(const int argc, const char *argv[], Profile *pProfile, struct Synchronization *synch);
|
||||
|
||||
private:
|
||||
bool _ReadParametersFromCmdLine(const int argc, const char *argv[], Profile *pProfile, struct Synchronization *synch);
|
||||
bool _ReadParametersFromXmlFile(const char *pszPath, Profile *pProfile);
|
||||
|
||||
bool _ParseETWParameter(const char *arg, Profile *pProfile);
|
||||
bool _ParseAffinity(const char *arg, TimeSpan *pTimeSpan);
|
||||
|
||||
void _DisplayUsageInfo(const char *pszFilename) const;
|
||||
bool _GetSizeInBytes(const char *pszSize, UINT64& ullSize) const;
|
||||
bool _GetRandomDataWriteBufferData(const string& sArg, UINT64& cb, string& sPath);
|
||||
|
||||
// variables that used to be global
|
||||
DWORD _dwBlockSize; // block size; other parameters may be stated in blocks
|
||||
// so the block size is needed to process them
|
||||
|
||||
UINT32 _ulWriteRatio; // default percentage of write requests
|
||||
|
||||
HANDLE _hEventStarted; // event signalled to notify that the actual (measured) test is to be started
|
||||
HANDLE _hEventFinished; // event signalled to notify that the actual test has finished
|
||||
|
||||
friend class UnitTests::CmdLineParserUnitTests;
|
||||
};
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// CmdRequestCreator.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
|
||||
#include "CmdRequestCreator.h"
|
||||
#include <windows.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "common.h"
|
||||
#include "errors.h"
|
||||
#include "..\CmdLineParser\CmdLineParser.h"
|
||||
#include "..\XmlProfileParser\XmlProfileParser.h"
|
||||
#include "..\IORequestGenerator\IORequestGenerator.h"
|
||||
#include "..\ResultParser\ResultParser.h"
|
||||
#include "..\XmlResultParser\XmlResultParser.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
// global variables
|
||||
static HANDLE g_hAbortEvent = NULL; // handle to the 'abort' event
|
||||
// it allows stopping I/O Request Generator in the middle of its work
|
||||
// the results of its work will be passed to the Results Parser
|
||||
static HANDLE g_hEventStarted = NULL; // event signalled to notify that the actual (measured) test is to be started
|
||||
static HANDLE g_hEventFinished = NULL; // event signalled to notify that the actual test has finished
|
||||
|
||||
/*****************************************************************************/
|
||||
// wrapper for printf. printf cannot be used directly, because IORequestGenerator.dll
|
||||
// may be consumed by gui app which doesn't have stdout
|
||||
void WINAPI PrintOut(const char *format, va_list args)
|
||||
{
|
||||
vprintf(format, args);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// wrapper for fprintf. fprintf cannot be used directly, because IORequestGenerator.dll
|
||||
// may be consumed by gui app which doesn't have stdout
|
||||
void WINAPI PrintError(const char *format, va_list args)
|
||||
{
|
||||
vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
BOOL WINAPI ctrlCRoutine(DWORD dwCtrlType)
|
||||
{
|
||||
if( CTRL_C_EVENT == dwCtrlType )
|
||||
{
|
||||
printf("\n*** Interrupted by Ctrl-C. Stopping I/O Request Generator. ***\n");
|
||||
if( !SetEvent(g_hAbortEvent) )
|
||||
{
|
||||
fprintf(stderr, "Warning: Setting abort event failed (error code: %u)\n", GetLastError());
|
||||
}
|
||||
SetConsoleCtrlHandler(ctrlCRoutine, FALSE);
|
||||
|
||||
//indicate that the signal has been handled
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void TestStarted()
|
||||
{
|
||||
if( (NULL != g_hEventStarted) && !SetEvent(g_hEventStarted) )
|
||||
{
|
||||
fprintf(stderr, "Warning: Setting test start notification event failed (error code: %u)\n", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void TestFinished()
|
||||
{
|
||||
if( (NULL != g_hEventFinished) && !SetEvent(g_hEventFinished) )
|
||||
{
|
||||
fprintf(stderr, "Warning: Setting test finish notification event failed (error code: %u)\n", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
DWORD pid = 0;
|
||||
|
||||
/*****************************************************************************/
|
||||
int __cdecl main(int argc, const char* argv[])
|
||||
{
|
||||
/// for CrystalDiskMark
|
||||
int totalScore = 0;
|
||||
double averageLatency = 0.0;
|
||||
|
||||
//
|
||||
// parse cmd line parameters
|
||||
//
|
||||
struct Synchronization synch; //sychronization structure
|
||||
synch.ulStructSize = sizeof(synch);
|
||||
synch.hStopEvent = NULL;
|
||||
synch.hStartEvent = NULL;
|
||||
|
||||
CmdLineParser cmdLineParser;
|
||||
Profile profile;
|
||||
if (!cmdLineParser.ParseCmdLine(argc, argv, &profile, &synch))
|
||||
{
|
||||
return ERROR_PARSE_CMD_LINE;
|
||||
}
|
||||
|
||||
synch.pfnCallbackTestStarted = TestStarted;
|
||||
synch.pfnCallbackTestFinished = TestFinished;
|
||||
|
||||
//
|
||||
// create abort event if stop event is not explicitly provided by the user (otherwise use the stop event)
|
||||
//
|
||||
|
||||
if (NULL == synch.hStopEvent)
|
||||
{
|
||||
synch.hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if( NULL == synch.hStopEvent )
|
||||
{
|
||||
fprintf(stderr, "Unable to create an abort event for CTRL+C\n");
|
||||
//FUTURE EXTENSION: change error code
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
g_hAbortEvent = synch.hStopEvent; // set abort event to either stop event provided by user or the just created event
|
||||
|
||||
//
|
||||
// capture ctrl+c
|
||||
//
|
||||
if( !SetConsoleCtrlHandler(ctrlCRoutine, TRUE) )
|
||||
{
|
||||
fprintf(stderr, "Unable to set CTRL+C routine\n");
|
||||
//FUTURE EXTENSION: change error code
|
||||
return 6;
|
||||
}
|
||||
|
||||
//
|
||||
// call IO request generator
|
||||
//
|
||||
ResultParser resultParser;
|
||||
XmlResultParser xmlResultParser;
|
||||
IResultParser *pResultParser = nullptr;
|
||||
if (profile.GetResultsFormat() == ResultsFormat::Xml)
|
||||
{
|
||||
pResultParser = &xmlResultParser;
|
||||
}
|
||||
else
|
||||
{
|
||||
pResultParser = &resultParser;
|
||||
}
|
||||
|
||||
IORequestGenerator ioGenerator;
|
||||
if (!ioGenerator.GenerateRequests(profile, *pResultParser, (PRINTF)PrintOut, (PRINTF)PrintError, (PRINTF)PrintOut, &synch, &totalScore, &averageLatency))
|
||||
{
|
||||
fprintf(stderr, "Error generating I/O requests\n");
|
||||
return 7;
|
||||
}
|
||||
|
||||
if( NULL != synch.hStartEvent )
|
||||
{
|
||||
CloseHandle(synch.hStartEvent);
|
||||
}
|
||||
if( NULL != synch.hStopEvent )
|
||||
{
|
||||
CloseHandle(synch.hStopEvent);
|
||||
}
|
||||
if( g_hEventStarted )
|
||||
{
|
||||
CloseHandle(g_hEventStarted);
|
||||
}
|
||||
if( NULL != g_hEventFinished )
|
||||
{
|
||||
CloseHandle(g_hEventFinished);
|
||||
}
|
||||
|
||||
/// for CrystalDiskMark
|
||||
CHAR name[32];
|
||||
snprintf(name, 32, "CrystalDiskMark%08X", pid);
|
||||
auto size = 8;
|
||||
|
||||
HANDLE hSharedMemory = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, NULL, size, name);
|
||||
if (hSharedMemory != NULL)
|
||||
{
|
||||
auto pMemory = (double*)MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, NULL, NULL, size);
|
||||
if (pMemory != NULL)
|
||||
{
|
||||
*pMemory = averageLatency;
|
||||
UnmapViewOfFile(pMemory);
|
||||
CloseHandle(hSharedMemory);
|
||||
}
|
||||
}
|
||||
// fprintf(stderr, "%f", averageLatency);
|
||||
|
||||
return totalScore;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently, but
|
||||
// are changed infrequently
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __DISKSPD_ERRORS_H
|
||||
#define __DISKSPD_ERRORS_H
|
||||
|
||||
#define ERROR_LOAD_LIBRARY 1 //error during LoadLibrary call
|
||||
#define ERROR_GET_PROC_ADDRESS 2 //error during GetProcAddress
|
||||
#define ERROR_PARSE_CMD_LINE 3 //error parsing cmd line parameters
|
||||
#define ERROR_WAIT_FOR_START_SIGNAL 4 //error waiting for a signal to start work
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,685 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
UINT64 PerfTimer::GetTime()
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
QueryPerformanceCounter(&li);
|
||||
return li.QuadPart;
|
||||
}
|
||||
|
||||
UINT64 PerfTimer::_GetPerfTimerFreq()
|
||||
{
|
||||
LARGE_INTEGER li;
|
||||
QueryPerformanceFrequency(&li);
|
||||
return li.QuadPart;
|
||||
}
|
||||
|
||||
const UINT64 PerfTimer::TIMER_FREQ = _GetPerfTimerFreq();
|
||||
|
||||
double PerfTimer::PerfTimeToMicroseconds(const double perfTime)
|
||||
{
|
||||
return perfTime / (TIMER_FREQ / 1000000.0);
|
||||
}
|
||||
|
||||
double PerfTimer::PerfTimeToMilliseconds(const double perfTime)
|
||||
{
|
||||
return PerfTimeToMicroseconds(perfTime) / 1000;
|
||||
}
|
||||
|
||||
double PerfTimer::PerfTimeToSeconds(const double perfTime)
|
||||
{
|
||||
return PerfTimeToMilliseconds(perfTime) / 1000;
|
||||
}
|
||||
|
||||
double PerfTimer::PerfTimeToMicroseconds(const UINT64 perfTime)
|
||||
{
|
||||
return PerfTimeToMicroseconds(static_cast<double>(perfTime));
|
||||
}
|
||||
|
||||
double PerfTimer::PerfTimeToMilliseconds(const UINT64 perfTime)
|
||||
{
|
||||
return PerfTimeToMilliseconds(static_cast<double>(perfTime));
|
||||
}
|
||||
|
||||
double PerfTimer::PerfTimeToSeconds(const UINT64 perfTime)
|
||||
{
|
||||
return PerfTimeToSeconds(static_cast<double>(perfTime));
|
||||
}
|
||||
|
||||
UINT64 PerfTimer::MicrosecondsToPerfTime(const double microseconds)
|
||||
{
|
||||
return static_cast<UINT64>(TIMER_FREQ * (microseconds / 1000000.0));
|
||||
}
|
||||
|
||||
UINT64 PerfTimer::MillisecondsToPerfTime(const double milliseconds)
|
||||
{
|
||||
return static_cast<UINT64>(TIMER_FREQ * (milliseconds / 1000.0));
|
||||
}
|
||||
|
||||
UINT64 PerfTimer::SecondsToPerfTime(const double seconds)
|
||||
{
|
||||
return static_cast<UINT64>(TIMER_FREQ * seconds);
|
||||
}
|
||||
|
||||
string Util::DoubleToStringHelper(const double d)
|
||||
{
|
||||
char szFloatBuffer[100];
|
||||
sprintf_s(szFloatBuffer, _countof(szFloatBuffer), "%10.3lf", d);
|
||||
|
||||
return string(szFloatBuffer);
|
||||
}
|
||||
|
||||
string Target::GetXml() const
|
||||
{
|
||||
char buffer[4096];
|
||||
string sXml("<Target>\n");
|
||||
sXml += "<Path>" + _sPath + "</Path>\n";
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<BlockSize>%u</BlockSize>\n", _dwBlockSize);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<BaseFileOffset>%I64u</BaseFileOffset>\n", _ullBaseFileOffset);
|
||||
sXml += buffer;
|
||||
|
||||
sXml += _fSequentialScanHint ? "<SequentialScan>true</SequentialScan>\n" : "<SequentialScan>false</SequentialScan>\n";
|
||||
sXml += _fRandomAccessHint ? "<RandomAccess>true</RandomAccess>\n" : "<RandomAccess>false</RandomAccess>\n";
|
||||
sXml += _fUseLargePages ? "<UseLargePages>true</UseLargePages>\n" : "<UseLargePages>false</UseLargePages>\n";
|
||||
sXml += _fDisableAllCache ? "<DisableAllCache>true</DisableAllCache>\n" : "<DisableAllCache>false</DisableAllCache>\n";
|
||||
// normalize cache controls - disabling the OS cache is included if all caches are disabled,
|
||||
// so specifying it twice is not neccesary (this generates a warning on the cmdline)
|
||||
if (!_fDisableAllCache)
|
||||
{
|
||||
sXml += _fDisableOSCache ? "<DisableOSCache>true</DisableOSCache>\n" : "<DisableOSCache>false</DisableOSCache>\n";
|
||||
}
|
||||
|
||||
sXml += "<WriteBufferContent>\n";
|
||||
if (_fZeroWriteBuffers)
|
||||
{
|
||||
sXml += "<Pattern>zero</Pattern>\n";
|
||||
}
|
||||
else if (_cbRandomDataWriteBuffer == 0)
|
||||
{
|
||||
sXml += "<Pattern>sequential</Pattern>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
sXml += "<Pattern>random</Pattern>\n";
|
||||
sXml += "<RandomDataSource>\n";
|
||||
sprintf_s(buffer, _countof(buffer), "<SizeInBytes>%I64u</SizeInBytes>\n", _cbRandomDataWriteBuffer);
|
||||
sXml += buffer;
|
||||
if (_sRandomDataWriteBufferSourcePath != "")
|
||||
{
|
||||
sXml += "<FilePath>" + _sRandomDataWriteBufferSourcePath + "</FilePath>\n";
|
||||
}
|
||||
sXml += "</RandomDataSource>\n";
|
||||
}
|
||||
sXml += "</WriteBufferContent>\n";
|
||||
|
||||
sXml += _fParallelAsyncIO ? "<ParallelAsyncIO>true</ParallelAsyncIO>\n" : "<ParallelAsyncIO>false</ParallelAsyncIO>\n";
|
||||
|
||||
if (_fUseBurstSize)
|
||||
{
|
||||
sprintf_s(buffer, _countof(buffer), "<BurstSize>%u</BurstSize>\n", _dwBurstSize);
|
||||
sXml += buffer;
|
||||
}
|
||||
|
||||
if (_fThinkTime)
|
||||
{
|
||||
sprintf_s(buffer, _countof(buffer), "<ThinkTime>%u</ThinkTime>\n", _dwThinkTime);
|
||||
sXml += buffer;
|
||||
}
|
||||
|
||||
if (_fCreateFile)
|
||||
{
|
||||
sprintf_s(buffer, _countof(buffer), "<FileSize>%I64u</FileSize>\n", _ullFileSize);
|
||||
sXml += buffer;
|
||||
}
|
||||
|
||||
// If XML contains <Random>, <StrideSize> is ignored
|
||||
if (_fUseRandomAccessPattern)
|
||||
{
|
||||
sprintf_s(buffer, _countof(buffer), "<Random>%I64u</Random>\n", GetBlockAlignmentInBytes());
|
||||
sXml += buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf_s(buffer, _countof(buffer), "<StrideSize>%I64u</StrideSize>\n", GetBlockAlignmentInBytes());
|
||||
sXml += buffer;
|
||||
|
||||
sXml += _fInterlockedSequential ?
|
||||
"<InterlockedSequential>true</InterlockedSequential>\n" :
|
||||
"<InterlockedSequential>false</InterlockedSequential>\n";
|
||||
}
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<ThreadStride>%I64u</ThreadStride>\n", _ullThreadStride);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<MaxFileSize>%I64u</MaxFileSize>\n", _ullMaxFileSize);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<RequestCount>%u</RequestCount>\n", _dwRequestCount);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<WriteRatio>%u</WriteRatio>\n", _ulWriteRatio);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<Throughput>%u</Throughput>\n", _dwThroughputBytesPerMillisecond);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<ThreadsPerFile>%u</ThreadsPerFile>\n", _dwThreadsPerFile);
|
||||
sXml += buffer;
|
||||
|
||||
if (_ioPriorityHint == IoPriorityHintVeryLow)
|
||||
{
|
||||
sXml += "<IOPriority>1</IOPriority>\n";
|
||||
}
|
||||
else if (_ioPriorityHint == IoPriorityHintLow)
|
||||
{
|
||||
sXml += "<IOPriority>2</IOPriority>\n";
|
||||
}
|
||||
else if (_ioPriorityHint == IoPriorityHintNormal)
|
||||
{
|
||||
sXml += "<IOPriority>3</IOPriority>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
sXml += "<IOPriority>* UNSUPPORTED *</IOPriority>\n";
|
||||
}
|
||||
|
||||
sXml += "</Target>\n";
|
||||
|
||||
|
||||
return sXml;
|
||||
}
|
||||
|
||||
bool Target::_FillRandomDataWriteBuffer()
|
||||
{
|
||||
assert(_pRandomDataWriteBuffer != nullptr);
|
||||
bool fOk = true;
|
||||
size_t cb = static_cast<size_t>(GetRandomDataWriteBufferSize());
|
||||
if (GetRandomDataWriteBufferSourcePath() == "")
|
||||
{
|
||||
// fill buffer with random data
|
||||
for (size_t i = 0; i < cb; i++)
|
||||
{
|
||||
_pRandomDataWriteBuffer[i] = (rand() % 256);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// fill buffer from file
|
||||
HANDLE hFile = CreateFile(GetRandomDataWriteBufferSourcePath().c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
UINT64 cbLeftToRead = GetRandomDataWriteBufferSize();
|
||||
BYTE *pBuffer = _pRandomDataWriteBuffer;
|
||||
bool fReadSuccess = true;
|
||||
while (fReadSuccess && cbLeftToRead > 0)
|
||||
{
|
||||
DWORD cbToRead = static_cast<DWORD>(min(64 * 1024, cbLeftToRead));
|
||||
DWORD cbRead;
|
||||
fReadSuccess = ((ReadFile(hFile, pBuffer, cbToRead, &cbRead, nullptr) == TRUE) && (cbRead > 0));
|
||||
pBuffer += cbRead;
|
||||
}
|
||||
|
||||
// if the file is smaller than the buffer, repeat its content
|
||||
BYTE *pSource = _pRandomDataWriteBuffer;
|
||||
const BYTE *pPastEnd = pSource + GetRandomDataWriteBufferSize();
|
||||
while (pBuffer < pPastEnd)
|
||||
{
|
||||
*pBuffer++ = *pSource++;
|
||||
}
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
fOk = false;
|
||||
// TODO: print error message?
|
||||
}
|
||||
}
|
||||
return fOk;
|
||||
}
|
||||
|
||||
bool Target::AllocateAndFillRandomDataWriteBuffer()
|
||||
{
|
||||
assert(_pRandomDataWriteBuffer == nullptr);
|
||||
bool fOk = true;
|
||||
size_t cb = static_cast<size_t>(GetRandomDataWriteBufferSize());
|
||||
assert(cb > 0);
|
||||
|
||||
// TODO: make sure the size if <= max value for size_t
|
||||
/// CrystalDiskMark 4 does not support Large Page
|
||||
if (false && GetUseLargePages())
|
||||
{
|
||||
/// size_t cbMinLargePage = GetLargePageMinimum();
|
||||
/// size_t cbRoundedSize = (cb + cbMinLargePage - 1) & ~(cbMinLargePage - 1);
|
||||
/// _pRandomDataWriteBuffer = (BYTE *)VirtualAlloc(nullptr, cbRoundedSize, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pRandomDataWriteBuffer = (BYTE *)VirtualAlloc(nullptr, cb, MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
fOk = (_pRandomDataWriteBuffer != nullptr);
|
||||
if (fOk)
|
||||
{
|
||||
fOk = _FillRandomDataWriteBuffer();
|
||||
}
|
||||
return fOk;
|
||||
}
|
||||
|
||||
void Target::FreeRandomDataWriteBuffer()
|
||||
{
|
||||
if (nullptr != _pRandomDataWriteBuffer)
|
||||
{
|
||||
VirtualFree(_pRandomDataWriteBuffer, 0, MEM_RELEASE);
|
||||
_pRandomDataWriteBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
BYTE* Target::GetRandomDataWriteBuffer()
|
||||
{
|
||||
size_t cbBuffer = static_cast<size_t>(GetRandomDataWriteBufferSize());
|
||||
size_t cbBlock = GetBlockSizeInBytes();
|
||||
|
||||
// leave enough bytes in the buffer for one block
|
||||
size_t randomOffset = rand() % (cbBuffer - (cbBlock - 1));
|
||||
|
||||
bool fUnbufferedIO = (GetDisableOSCache() || GetDisableAllCache());
|
||||
if (fUnbufferedIO)
|
||||
{
|
||||
// for unbuffered IO, offset in the buffer needs to be DWORD-aligned
|
||||
const size_t cbAlignment = 4;
|
||||
randomOffset -= (randomOffset % cbAlignment);
|
||||
}
|
||||
|
||||
BYTE *pBuffer = reinterpret_cast<BYTE*>(reinterpret_cast<ULONG_PTR>(_pRandomDataWriteBuffer)+randomOffset);
|
||||
|
||||
// unbuffered IO needs aligned addresses
|
||||
assert(!fUnbufferedIO || (reinterpret_cast<ULONG_PTR>(pBuffer) % 4 == 0));
|
||||
|
||||
assert(pBuffer >= _pRandomDataWriteBuffer);
|
||||
assert(pBuffer <= _pRandomDataWriteBuffer + GetRandomDataWriteBufferSize() - GetBlockSizeInBytes());
|
||||
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
string TimeSpan::GetXml() const
|
||||
{
|
||||
string sXml("<TimeSpan>\n");
|
||||
char buffer[4096];
|
||||
|
||||
sXml += _fCompletionRoutines ? "<CompletionRoutines>true</CompletionRoutines>\n" : "<CompletionRoutines>false</CompletionRoutines>\n";
|
||||
sXml += _fMeasureLatency ? "<MeasureLatency>true</MeasureLatency>\n" : "<MeasureLatency>false</MeasureLatency>\n";
|
||||
sXml += _fCalculateIopsStdDev ? "<CalculateIopsStdDev>true</CalculateIopsStdDev>\n" : "<CalculateIopsStdDev>false</CalculateIopsStdDev>\n";
|
||||
sXml += _fDisableAffinity ? "<DisableAffinity>true</DisableAffinity>\n" : "<DisableAffinity>false</DisableAffinity>\n";
|
||||
sXml += _fGroupAffinity ? "<GroupAffinity>true</GroupAffinity>\n" : "<GroupAffinity>false</GroupAffinity>\n";
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<Duration>%u</Duration>\n", _ulDuration);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<Warmup>%u</Warmup>\n", _ulWarmUp);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<Cooldown>%u</Cooldown>\n", _ulCoolDown);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<ThreadCount>%u</ThreadCount>\n", _dwThreadCount);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<IoBucketDuration>%u</IoBucketDuration>\n", _ulIoBucketDurationInMilliseconds);
|
||||
sXml += buffer;
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<RandSeed>%u</RandSeed>\n", _ulRandSeed);
|
||||
sXml += buffer;
|
||||
|
||||
if (_vAffinity.size() > 0)
|
||||
{
|
||||
sXml += "<Affinity>\n";
|
||||
for (auto a : _vAffinity)
|
||||
{
|
||||
sprintf_s(buffer, _countof(buffer), "<AffinityAssignment>%u</AffinityAssignment>\n", a);
|
||||
sXml += buffer;
|
||||
}
|
||||
sXml += "</Affinity>\n";
|
||||
}
|
||||
|
||||
sXml += "<Targets>\n";
|
||||
for (const auto& target : _vTargets)
|
||||
{
|
||||
sXml += target.GetXml();
|
||||
}
|
||||
sXml += "</Targets>\n";
|
||||
sXml += "</TimeSpan>\n";
|
||||
return sXml;
|
||||
}
|
||||
|
||||
void TimeSpan::MarkFilesAsPrecreated(const vector<string> vFiles)
|
||||
{
|
||||
for (auto sFile : vFiles)
|
||||
{
|
||||
for (auto pTarget = _vTargets.begin(); pTarget != _vTargets.end(); pTarget++)
|
||||
{
|
||||
if (sFile == pTarget->GetPath())
|
||||
{
|
||||
pTarget->SetPrecreated(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string Profile::GetXml() const
|
||||
{
|
||||
string sXml("<Profile>\n");
|
||||
char buffer[4096];
|
||||
|
||||
sprintf_s(buffer, _countof(buffer), "<Progress>%u</Progress>\n", _dwProgress);
|
||||
sXml += buffer;
|
||||
|
||||
if (_resultsFormat == ResultsFormat::Text)
|
||||
{
|
||||
sXml += "<ResultFormat>text</ResultFormat>\n";
|
||||
}
|
||||
else if (_resultsFormat == ResultsFormat::Xml)
|
||||
{
|
||||
sXml += "<ResultFormat>xml</ResultFormat>\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
sXml += "<ResultFormat>* UNSUPPORTED *</ResultFormat>\n";
|
||||
}
|
||||
|
||||
sXml += _fVerbose ? "<Verbose>true</Verbose>\n" : "<Verbose>false</Verbose>\n";
|
||||
if (_precreateFiles == PrecreateFiles::UseMaxSize)
|
||||
{
|
||||
sXml += "<PrecreateFiles>UseMaxSize</PrecreateFiles>\n";
|
||||
}
|
||||
else if (_precreateFiles == PrecreateFiles::OnlyFilesWithConstantSizes)
|
||||
{
|
||||
sXml += "<PrecreateFiles>CreateOnlyFilesWithConstantSizes</PrecreateFiles>\n";
|
||||
}
|
||||
else if (_precreateFiles == PrecreateFiles::OnlyFilesWithConstantOrZeroSizes)
|
||||
{
|
||||
sXml += "<PrecreateFiles>CreateOnlyFilesWithConstantOrZeroSizes</PrecreateFiles>\n";
|
||||
}
|
||||
|
||||
if (_fEtwEnabled)
|
||||
{
|
||||
sXml += _fEtwProcess ? "<Process>true</Process>\n" : "<Process>false</Process>\n";
|
||||
sXml += _fEtwThread ? "<Thread>true</Thread>\n" : "<Thread>false</Thread>\n";
|
||||
sXml += _fEtwImageLoad ? "<ImageLoad>true</ImageLoad>\n" : "<ImageLoad>false</ImageLoad>\n";
|
||||
sXml += _fEtwDiskIO ? "<DiskIO>true</DiskIO>\n" : "<DiskIO>false</DiskIO>\n";
|
||||
sXml += _fEtwMemoryPageFaults ? "<MemoryPageFaults>true</MemoryPageFaults>\n" : "<MemoryPageFaults>false</MemoryPageFaults>\n";
|
||||
sXml += _fEtwMemoryHardFaults ? "<MemoryHardFaults>true</MemoryHardFaults>\n" : "<MemoryHardFaults>false</MemoryHardFaults>\n";
|
||||
sXml += _fEtwNetwork ? "<Network>true</Network>\n" : "<Network>false</Network>\n";
|
||||
sXml += _fEtwRegistry ? "<Registry>true</Registry>\n" : "<Registry>false</Registry>\n";
|
||||
sXml += _fEtwUsePagedMemory ? "<UsePagedMemory>true</UsePagedMemory>\n" : "<UsePagedMemory>false</UsePagedMemory>\n";
|
||||
sXml += _fEtwUsePerfTimer ? "<UsePerfTimer>true</UsePerfTimer>\n" : "<UsePerfTimer>false</UsePerfTimer>\n";
|
||||
sXml += _fEtwUseSystemTimer ? "<UseSystemTimer>true</UseSystemTimer>\n" : "<UseSystemTimer>false</UseSystemTimer>\n";
|
||||
sXml += _fEtwUseCyclesCounter ? "<UseCyclesCounter>true</UseCyclesCounter>\n" : "<UseCyclesCounter>false</UseCyclesCounter>\n";
|
||||
}
|
||||
|
||||
sXml += "<TimeSpans>\n";
|
||||
for (const auto& timespan : _vTimeSpans)
|
||||
{
|
||||
sXml += timespan.GetXml();
|
||||
}
|
||||
sXml += "</TimeSpans>\n";
|
||||
sXml += "</Profile>\n";
|
||||
return sXml;
|
||||
}
|
||||
|
||||
void Profile::MarkFilesAsPrecreated(const vector<string> vFiles)
|
||||
{
|
||||
for (auto pTimeSpan = _vTimeSpans.begin(); pTimeSpan != _vTimeSpans.end(); pTimeSpan++)
|
||||
{
|
||||
pTimeSpan->MarkFilesAsPrecreated(vFiles);
|
||||
}
|
||||
}
|
||||
|
||||
bool Profile::Validate(bool fSingleSpec) const
|
||||
{
|
||||
bool fOk = true;
|
||||
for (const auto& timeSpan : GetTimeSpans())
|
||||
{
|
||||
if (timeSpan.GetDisableAffinity() && timeSpan.GetAffinityAssignments().size() > 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: -n and -a parameters cannot be used together\n");
|
||||
fOk = false;
|
||||
}
|
||||
|
||||
for (const auto& target : timeSpan.GetTargets())
|
||||
{
|
||||
const bool targetHasMultipleThreads = (timeSpan.GetThreadCount() > 1) || (target.GetThreadsPerFile() > 1);
|
||||
|
||||
if (timeSpan.GetThreadCount() > 0 && target.GetThreadsPerFile() > 1)
|
||||
{
|
||||
fprintf(stderr, "ERROR: -F and -t parameters cannot be used together\n");
|
||||
fOk = false;
|
||||
}
|
||||
|
||||
if (target.GetDisableAllCache() && target.GetDisableOSCache())
|
||||
{
|
||||
fprintf(stderr, "WARNING: -S is included in the effect of -h, specifying both is not required\n");
|
||||
}
|
||||
|
||||
if (target.GetThroughputInBytesPerMillisecond() > 0 && timeSpan.GetCompletionRoutines())
|
||||
{
|
||||
fprintf(stderr, "ERROR: -g throughput control cannot be used with -x completion routines\n");
|
||||
fOk = false;
|
||||
}
|
||||
|
||||
// If burst size is specified think time must be specified and If think time is specified burst size should be non zero
|
||||
if ((target.GetThinkTime() == 0 && target.GetBurstSize() > 0) || (target.GetThinkTime() > 0 && target.GetBurstSize() == 0))
|
||||
{
|
||||
fprintf(stderr, "ERROR: need to specify -j<think time> with -i<burst size>\n");
|
||||
fOk = false;
|
||||
}
|
||||
|
||||
// FIXME: we can no longer do this check, because the target no longer
|
||||
// contains a property that uniquely identifies the case where "-s" or <StrideSize>
|
||||
// was passed.
|
||||
#if 0
|
||||
if (target.GetUseRandomAccessPattern() && target.GetEnableCustomStrideSize())
|
||||
{
|
||||
fprintf(stderr, "WARNING: -s is ignored if -r is provided\n");
|
||||
}
|
||||
#endif
|
||||
if (target.GetUseRandomAccessPattern())
|
||||
{
|
||||
if (target.GetThreadStrideInBytes() > 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: -T conflicts with -r\n");
|
||||
fOk = false;
|
||||
// although ullThreadStride==0 is a valid value, it's interpreted as "not provided" for this warning
|
||||
}
|
||||
|
||||
if (target.GetUseInterlockedSequential())
|
||||
{
|
||||
fprintf(stderr, "ERROR: -si conflicts with -r\n");
|
||||
fOk = false;
|
||||
}
|
||||
|
||||
if (target.GetUseParallelAsyncIO())
|
||||
{
|
||||
fprintf(stderr, "ERROR: -p conflicts with -r\n");
|
||||
fOk = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target.GetUseParallelAsyncIO() && target.GetRequestCount() == 1)
|
||||
{
|
||||
fprintf(stderr, "WARNING: -p does not have effect unless outstanding I/O count (-o) is > 1\n");
|
||||
}
|
||||
|
||||
if (timeSpan.GetRandSeed() > 0)
|
||||
{
|
||||
fprintf(stderr, "WARNING: -z is ignored if -r is not provided\n");
|
||||
// although ulRandSeed==0 is a valid value, it's interpreted as "not provided" for this warning
|
||||
}
|
||||
|
||||
if (target.GetUseInterlockedSequential())
|
||||
{
|
||||
if (target.GetThreadStrideInBytes() > 0)
|
||||
{
|
||||
fprintf(stderr, "ERROR: -si conflicts with -T\n");
|
||||
fOk = false;
|
||||
}
|
||||
|
||||
if (target.GetUseParallelAsyncIO())
|
||||
{
|
||||
fprintf(stderr, "ERROR: -si conflicts with -p\n");
|
||||
fOk = false;
|
||||
}
|
||||
|
||||
if (!targetHasMultipleThreads)
|
||||
{
|
||||
fprintf(stderr, "WARNING: single-threaded test, -si ignored\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (targetHasMultipleThreads && !target.GetThreadStrideInBytes())
|
||||
{
|
||||
fprintf(stderr, "WARNING: target access pattern will not be sequential, consider -si\n");
|
||||
}
|
||||
|
||||
if (!targetHasMultipleThreads && target.GetThreadStrideInBytes())
|
||||
{
|
||||
fprintf(stderr, "ERROR: -T has no effect unless multiple threads per target are used\n");
|
||||
fOk = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target.GetRandomDataWriteBufferSize() > 0)
|
||||
{
|
||||
if (target.GetRandomDataWriteBufferSize() < target.GetBlockSizeInBytes())
|
||||
{
|
||||
fprintf(stderr, "ERROR: custom write buffer (-Z) is smaller than the block size. Write buffer size: %I64u block size: %u\n",
|
||||
target.GetRandomDataWriteBufferSize(),
|
||||
target.GetBlockSizeInBytes());
|
||||
fOk = false;
|
||||
}
|
||||
}
|
||||
|
||||
// in the cases where there is only a single configuration specified for each target (e.g., cmdline),
|
||||
// currently there are no validations specific to individual targets (e.g., pre-existing files)
|
||||
// so we can stop validation now. this allows us to only warn/error once, as opposed to repeating
|
||||
// it for each target.
|
||||
if (fSingleSpec)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fOk;
|
||||
}
|
||||
|
||||
bool ThreadParameters::AllocateAndFillBufferForTarget(const Target& target)
|
||||
{
|
||||
bool fOk = true;
|
||||
BYTE *pDataBuffer = nullptr;
|
||||
size_t cbDataBuffer = target.GetBlockSizeInBytes() * target.GetRequestCount();
|
||||
|
||||
/// CrystalDiskMark 4 does not support Large Page
|
||||
if (false && target.GetUseLargePages())
|
||||
{
|
||||
/// size_t cbMinLargePage = GetLargePageMinimum();
|
||||
/// size_t cbRoundedSize = (cbDataBuffer + cbMinLargePage - 1) & ~(cbMinLargePage - 1);
|
||||
/// pDataBuffer = (BYTE *)VirtualAlloc(nullptr, cbRoundedSize, MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, PAGE_EXECUTE_READWRITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pDataBuffer = (BYTE *)VirtualAlloc(nullptr, cbDataBuffer, MEM_COMMIT, PAGE_READWRITE);
|
||||
}
|
||||
|
||||
fOk = (pDataBuffer != nullptr);
|
||||
|
||||
//fill buffer (useful only for write tests)
|
||||
if (fOk && target.GetWriteRatio() > 0)
|
||||
{
|
||||
if (target.GetZeroWriteBuffers())
|
||||
{
|
||||
memset(pDataBuffer, 0, cbDataBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < cbDataBuffer; i++)
|
||||
{
|
||||
pDataBuffer[i] = (BYTE)(i % 256);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fOk)
|
||||
{
|
||||
vpDataBuffers.push_back(pDataBuffer);
|
||||
}
|
||||
|
||||
return fOk;
|
||||
}
|
||||
|
||||
BYTE* ThreadParameters::GetReadBuffer(size_t iTarget, size_t iRequest)
|
||||
{
|
||||
return vpDataBuffers[iTarget] + (iRequest * vTargets[iTarget].GetBlockSizeInBytes());
|
||||
}
|
||||
|
||||
BYTE* ThreadParameters::GetWriteBuffer(size_t iTarget, size_t iRequest)
|
||||
{
|
||||
BYTE *pBuffer = nullptr;
|
||||
|
||||
Target& target(vTargets[iTarget]);
|
||||
size_t cb = static_cast<size_t>(target.GetRandomDataWriteBufferSize());
|
||||
if (cb == 0)
|
||||
{
|
||||
pBuffer = vpDataBuffers[iTarget] + (iRequest * vTargets[iTarget].GetBlockSizeInBytes());
|
||||
}
|
||||
else
|
||||
{
|
||||
pBuffer = target.GetRandomDataWriteBuffer();
|
||||
}
|
||||
return pBuffer;
|
||||
}
|
||||
|
||||
DWORD ThreadParameters::GetTotalRequestCount() const
|
||||
{
|
||||
DWORD cRequests = 0;
|
||||
|
||||
for (const auto& t : vTargets)
|
||||
{
|
||||
cRequests += t.GetRequestCount();
|
||||
}
|
||||
|
||||
return cRequests;
|
||||
}
|
||||
@@ -0,0 +1,814 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#include <Winternl.h> //ntdll.dll
|
||||
#include <assert.h>
|
||||
#include "Histogram.h"
|
||||
#include "IoBucketizer.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/// structures used for passing the input parameters
|
||||
|
||||
// versioning material. for simplicity in consumption, please ensure that the date string
|
||||
// parses via the System.Datetime constructor as follows (in Powershell):
|
||||
//
|
||||
// [datetime] "string"
|
||||
//
|
||||
// this should result in a valid System.Datetime object, rendered like:
|
||||
//
|
||||
// Monday, June 16, 2014 12:00:00 AM
|
||||
|
||||
#define DISKSPD_RELEASE_TAG ""
|
||||
#define DISKSPD_NUMERIC_VERSION_STRING "2.0.15" DISKSPD_RELEASE_TAG
|
||||
#define DISKSPD_DATE_VERSION_STRING "2015/01/09"
|
||||
|
||||
typedef void (WINAPI *PRINTF)(const char*, va_list); //function used for displaying formatted data (printf style)
|
||||
|
||||
struct ETWEventCounters
|
||||
{
|
||||
UINT64 ullIORead; // Read
|
||||
UINT64 ullIOWrite; // Write
|
||||
UINT64 ullMMTransitionFault; // Transition fault
|
||||
UINT64 ullMMDemandZeroFault; // Demand Zero fault
|
||||
UINT64 ullMMCopyOnWrite; // Copy on Write
|
||||
UINT64 ullMMGuardPageFault; // Guard Page fault
|
||||
UINT64 ullMMHardPageFault; // Hard page fault
|
||||
UINT64 ullNetTcpSend; // Send
|
||||
UINT64 ullNetTcpReceive; // Receive
|
||||
UINT64 ullNetUdpSend; // Send
|
||||
UINT64 ullNetUdpReceive; // Receive
|
||||
UINT64 ullNetConnect; // Connect
|
||||
UINT64 ullNetDisconnect; // Disconnect
|
||||
UINT64 ullNetRetransmit; // ReTransmit
|
||||
UINT64 ullNetAccept; // Accept
|
||||
UINT64 ullNetReconnect; // ReConnect
|
||||
UINT64 ullRegCreate; // NtCreateKey
|
||||
UINT64 ullRegOpen; // NtOpenKey
|
||||
UINT64 ullRegDelete; // NtDeleteKey
|
||||
UINT64 ullRegQuery; // NtQueryKey
|
||||
UINT64 ullRegSetValue; // NtSetValueKey
|
||||
UINT64 ullRegDeleteValue; // NtDeleteValueKey
|
||||
UINT64 ullRegQueryValue; // NtQueryValueKey
|
||||
UINT64 ullRegEnumerateKey; // NtEnumerateKey
|
||||
UINT64 ullRegEnumerateValueKey; // NtEnumerateValueKey
|
||||
UINT64 ullRegQueryMultipleValue; // NtQueryMultipleValueKey
|
||||
UINT64 ullRegSetInformation; // NtSetInformationKey
|
||||
UINT64 ullRegFlush; // NtFlushKey
|
||||
UINT64 ullRegKcbDmp; // KcbDump/create
|
||||
UINT64 ullThreadStart;
|
||||
UINT64 ullThreadEnd;
|
||||
UINT64 ullProcessStart;
|
||||
UINT64 ullProcessEnd;
|
||||
UINT64 ullImageLoad;
|
||||
};
|
||||
|
||||
|
||||
// structure containing informations about ETW session
|
||||
struct ETWSessionInfo
|
||||
{
|
||||
ULONG ulBufferSize;
|
||||
ULONG ulMinimumBuffers;
|
||||
ULONG ulMaximumBuffers;
|
||||
ULONG ulFreeBuffers;
|
||||
ULONG ulBuffersWritten;
|
||||
ULONG ulFlushTimer;
|
||||
LONG lAgeLimit;
|
||||
ULONG ulNumberOfBuffers;
|
||||
ULONG ulEventsLost;
|
||||
ULONG ulLogBuffersLost;
|
||||
ULONG ulRealTimeBuffersLost;
|
||||
};
|
||||
|
||||
// structure containing parameters concerning ETW session provided by user
|
||||
struct ETWMask
|
||||
{
|
||||
BOOL bProcess;
|
||||
BOOL bThread;
|
||||
BOOL bImageLoad;
|
||||
BOOL bDiskIO;
|
||||
BOOL bMemoryPageFaults;
|
||||
BOOL bMemoryHardFaults;
|
||||
BOOL bNetwork;
|
||||
BOOL bRegistry;
|
||||
BOOL bUsePagedMemory;
|
||||
BOOL bUsePerfTimer;
|
||||
BOOL bUseSystemTimer;
|
||||
BOOL bUseCyclesCounter;
|
||||
};
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
class PerfTimerUnitTests;
|
||||
class ProfileUnitTests;
|
||||
class TargetUnitTests;
|
||||
}
|
||||
|
||||
class PerfTimer
|
||||
{
|
||||
public:
|
||||
|
||||
static UINT64 GetTime();
|
||||
|
||||
static double PerfTimeToMicroseconds(const double);
|
||||
static double PerfTimeToMilliseconds(const double);
|
||||
static double PerfTimeToSeconds(const double);
|
||||
static double PerfTimeToMicroseconds(const UINT64);
|
||||
static double PerfTimeToMilliseconds(const UINT64);
|
||||
static double PerfTimeToSeconds(const UINT64);
|
||||
|
||||
static UINT64 MicrosecondsToPerfTime(const double);
|
||||
static UINT64 MillisecondsToPerfTime(const double);
|
||||
static UINT64 SecondsToPerfTime(const double);
|
||||
|
||||
private:
|
||||
|
||||
static const UINT64 TIMER_FREQ;
|
||||
static UINT64 _GetPerfTimerFreq();
|
||||
|
||||
friend class UnitTests::PerfTimerUnitTests;
|
||||
};
|
||||
|
||||
struct PercentileDescriptor
|
||||
{
|
||||
double Percentile;
|
||||
string Name;
|
||||
};
|
||||
|
||||
class Util
|
||||
{
|
||||
public:
|
||||
static string DoubleToStringHelper(const double);
|
||||
template<typename T> static T QuotientCeiling(T dividend, T divisor)
|
||||
{
|
||||
return (dividend + divisor - 1) / divisor;
|
||||
}
|
||||
};
|
||||
|
||||
// To keep track of which type of IO was issued
|
||||
enum class IOOperation
|
||||
{
|
||||
ReadIO = 1,
|
||||
WriteIO
|
||||
};
|
||||
|
||||
class TargetResults
|
||||
{
|
||||
public:
|
||||
TargetResults() :
|
||||
ullFileSize(0),
|
||||
ullBytesCount(0),
|
||||
ullIOCount(0),
|
||||
ullReadBytesCount(0),
|
||||
ullReadIOCount(0),
|
||||
ullWriteBytesCount(0),
|
||||
ullWriteIOCount(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Add(DWORD dwBytesTransferred,
|
||||
IOOperation type,
|
||||
PUINT64 pullIoStartTime,
|
||||
PUINT64 pullSpanStartTime,
|
||||
bool fMeasureLatency,
|
||||
bool fCalculateIopsStdDev
|
||||
)
|
||||
{
|
||||
float fDurationMsec = 0;
|
||||
UINT64 ullEndTime = 0;
|
||||
// assume it is worthwhile to stay off of the time query path unless needed (micro-overhead)
|
||||
if (fMeasureLatency || fCalculateIopsStdDev)
|
||||
{
|
||||
ullEndTime = PerfTimer::GetTime();
|
||||
}
|
||||
|
||||
if (fMeasureLatency)
|
||||
{
|
||||
UINT64 ullDuration = ullEndTime - *pullIoStartTime;
|
||||
fDurationMsec = static_cast<float>(PerfTimer::PerfTimeToMicroseconds(ullDuration));
|
||||
|
||||
if (type == IOOperation::ReadIO)
|
||||
{
|
||||
readLatencyHistogram.Add(fDurationMsec);
|
||||
}
|
||||
else
|
||||
{
|
||||
writeLatencyHistogram.Add(fDurationMsec);
|
||||
}
|
||||
}
|
||||
|
||||
UINT64 ullRelativeCompletionTime = 0;
|
||||
if (fCalculateIopsStdDev)
|
||||
{
|
||||
ullRelativeCompletionTime = ullEndTime - *pullSpanStartTime;
|
||||
|
||||
if (type == IOOperation::ReadIO)
|
||||
{
|
||||
readBucketizer.Add(ullRelativeCompletionTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
writeBucketizer.Add(ullRelativeCompletionTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (type == IOOperation::ReadIO)
|
||||
{
|
||||
ullReadBytesCount += dwBytesTransferred; // update read bytes counter
|
||||
ullReadIOCount++; // update completed read I/O operations counter
|
||||
}
|
||||
else
|
||||
{
|
||||
ullWriteBytesCount += dwBytesTransferred; // update write bytes counter
|
||||
ullWriteIOCount++; // update completed write I/O operations counter
|
||||
}
|
||||
|
||||
ullBytesCount += dwBytesTransferred; // update bytes counter
|
||||
ullIOCount++; // update completed I/O operations counter
|
||||
}
|
||||
|
||||
string sPath;
|
||||
UINT64 ullFileSize; //size of the file
|
||||
UINT64 ullBytesCount; //number of accessed bytes
|
||||
UINT64 ullIOCount; //number of performed I/O operations
|
||||
UINT64 ullReadBytesCount; //number of bytes read
|
||||
UINT64 ullReadIOCount; //number of performed Read I/O operations
|
||||
UINT64 ullWriteBytesCount; //number of bytes written
|
||||
UINT64 ullWriteIOCount; //number of performed Write I/O operations
|
||||
|
||||
Histogram<float> readLatencyHistogram;
|
||||
Histogram<float> writeLatencyHistogram;
|
||||
|
||||
IoBucketizer readBucketizer;
|
||||
IoBucketizer writeBucketizer;
|
||||
};
|
||||
|
||||
class ThreadResults
|
||||
{
|
||||
public:
|
||||
vector<TargetResults> vTargetResults;
|
||||
};
|
||||
|
||||
class Results
|
||||
{
|
||||
public:
|
||||
bool fUseETW;
|
||||
struct ETWEventCounters EtwEventCounters;
|
||||
struct ETWMask EtwMask;
|
||||
struct ETWSessionInfo EtwSessionInfo;
|
||||
vector<ThreadResults> vThreadResults;
|
||||
UINT64 ullTimeCount;
|
||||
vector<SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION> vSystemProcessorPerfInfo;
|
||||
};
|
||||
|
||||
typedef void (*CALLBACK_TEST_STARTED)(); //callback function to notify that the measured test is about to start
|
||||
typedef void (*CALLBACK_TEST_FINISHED)(); //callback function to notify that the measured test has just finished
|
||||
|
||||
class SystemInformation
|
||||
{
|
||||
public:
|
||||
string sComputerName;
|
||||
|
||||
SystemInformation()
|
||||
{
|
||||
char buffer[64];
|
||||
DWORD cb = _countof(buffer);
|
||||
BOOL fResult;
|
||||
|
||||
#pragma prefast(suppress:38020, "Yes, we're aware this is an ANSI API in a UNICODE project")
|
||||
fResult = GetComputerNameExA(ComputerNamePhysicalDnsHostname, buffer, &cb);
|
||||
if (fResult)
|
||||
{
|
||||
sComputerName = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
string SystemInformation::GetXml() const
|
||||
{
|
||||
string sXml("<System>\n");
|
||||
|
||||
// identify computer which ran the test
|
||||
sXml += "<ComputerName>";
|
||||
sXml += sComputerName;
|
||||
sXml += "</ComputerName>\n";
|
||||
|
||||
// identify tool version which performed the test
|
||||
sXml += "<Tool>\n";
|
||||
sXml += "<Version>" DISKSPD_NUMERIC_VERSION_STRING "</Version>\n";
|
||||
sXml += "<VersionDate>" DISKSPD_DATE_VERSION_STRING "</VersionDate>\n";
|
||||
sXml += "</Tool>\n";
|
||||
|
||||
sXml += "</System>\n";
|
||||
|
||||
return sXml;
|
||||
}
|
||||
};
|
||||
|
||||
struct Synchronization
|
||||
{
|
||||
ULONG ulStructSize; //size of the structure that the caller is aware of (to easier achieve backward compatibility in a future)
|
||||
HANDLE hStopEvent; //an event to be signalled if the scenario is to be stop before time ellapses
|
||||
HANDLE hStartEvent; //an event for signalling start
|
||||
CALLBACK_TEST_STARTED pfnCallbackTestStarted; //a function to be called if the measured test is about to start
|
||||
CALLBACK_TEST_FINISHED pfnCallbackTestFinished; //a function to be called as soon as the measrued test finishes
|
||||
};
|
||||
|
||||
#define STRUCT_SYNCHRONIZATION_SUPPORTS(pSynch, Field) ( \
|
||||
(NULL != (pSynch)) && \
|
||||
((pSynch)->ulStructSize >= offsetof(struct Synchronization, Field) + sizeof((pSynch)->Field)) \
|
||||
)
|
||||
|
||||
class Target
|
||||
{
|
||||
public:
|
||||
|
||||
Target() :
|
||||
_dwBlockSize(64 * 1024),
|
||||
_dwRequestCount(2),
|
||||
_ullBlockAlignment(64 * 1024),
|
||||
_fBlockAlignmentValid(false),
|
||||
_fUseRandomAccessPattern(false),
|
||||
_ullBaseFileOffset(0),
|
||||
_fParallelAsyncIO(false),
|
||||
_fInterlockedSequential(false),
|
||||
_fDisableOSCache(false),
|
||||
_fDisableAllCache(false),
|
||||
_fZeroWriteBuffers(false),
|
||||
_dwThreadsPerFile(1),
|
||||
_ullThreadStride(0),
|
||||
_fCreateFile(false),
|
||||
_fPrecreated(false),
|
||||
_ullFileSize(0),
|
||||
_ullMaxFileSize(0),
|
||||
_ulWriteRatio(0),
|
||||
_fUseBurstSize(false),
|
||||
_dwBurstSize(0),
|
||||
_dwThinkTime(0),
|
||||
_fThinkTime(false),
|
||||
_fSequentialScanHint(false),
|
||||
_fRandomAccessHint(false),
|
||||
_fUseLargePages(false),
|
||||
_ioPriorityHint(IoPriorityHintNormal),
|
||||
_dwThroughputBytesPerMillisecond(0),
|
||||
_cbRandomDataWriteBuffer(0),
|
||||
_sRandomDataWriteBufferSourcePath(),
|
||||
_pRandomDataWriteBuffer(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void SetPath(string sPath) { _sPath = sPath; }
|
||||
string GetPath() const { return _sPath; }
|
||||
|
||||
void SetBlockSizeInBytes(DWORD dwBlockSize) { _dwBlockSize = dwBlockSize; }
|
||||
DWORD GetBlockSizeInBytes() const { return _dwBlockSize; }
|
||||
|
||||
void SetBlockAlignmentInBytes(UINT64 ullBlockAlignment)
|
||||
{
|
||||
_ullBlockAlignment = ullBlockAlignment;
|
||||
_fBlockAlignmentValid = true;
|
||||
}
|
||||
|
||||
UINT64 GetBlockAlignmentInBytes() const
|
||||
{
|
||||
return _fBlockAlignmentValid ? _ullBlockAlignment : _dwBlockSize;
|
||||
}
|
||||
|
||||
void SetUseRandomAccessPattern(bool fUseRandomAccessPattern) { _fUseRandomAccessPattern = fUseRandomAccessPattern; }
|
||||
bool GetUseRandomAccessPattern() const { return _fUseRandomAccessPattern; }
|
||||
|
||||
void SetBaseFileOffsetInBytes(UINT64 ullBaseFileOffset) { _ullBaseFileOffset = ullBaseFileOffset; }
|
||||
UINT64 GetBaseFileOffsetInBytes() const { return _ullBaseFileOffset; }
|
||||
|
||||
void SetSequentialScanHint(bool fSequentialScanHint) { _fSequentialScanHint = fSequentialScanHint; }
|
||||
bool GetSequentialScanHint() const { return _fSequentialScanHint; }
|
||||
|
||||
void SetRandomAccessHint(bool fRandomAccessHint) { _fRandomAccessHint = fRandomAccessHint; }
|
||||
bool GetRandomAccessHint() const { return _fRandomAccessHint; }
|
||||
|
||||
void SetUseLargePages(bool fUseLargePages) { _fUseLargePages = fUseLargePages; }
|
||||
bool GetUseLargePages() const { return _fUseLargePages; }
|
||||
|
||||
void SetRequestCount(DWORD dwRequestCount) { _dwRequestCount = dwRequestCount; }
|
||||
DWORD GetRequestCount() const { return _dwRequestCount; }
|
||||
|
||||
void SetDisableOSCache(bool fDisableOSCache) { _fDisableOSCache = fDisableOSCache; }
|
||||
bool GetDisableOSCache() const { return _fDisableOSCache; }
|
||||
|
||||
void SetDisableAllCache(bool fDisableAllCache) { _fDisableAllCache = fDisableAllCache; }
|
||||
bool GetDisableAllCache() const { return _fDisableAllCache; }
|
||||
|
||||
void SetZeroWriteBuffers(bool fZeroWriteBuffers) { _fZeroWriteBuffers = fZeroWriteBuffers; }
|
||||
bool GetZeroWriteBuffers() const { return _fZeroWriteBuffers; }
|
||||
|
||||
void SetRandomDataWriteBufferSize(UINT64 cbWriteBuffer) { _cbRandomDataWriteBuffer = cbWriteBuffer; }
|
||||
UINT64 GetRandomDataWriteBufferSize(void) const { return _cbRandomDataWriteBuffer; }
|
||||
|
||||
void SetRandomDataWriteBufferSourcePath(string sPath) { _sRandomDataWriteBufferSourcePath = sPath; }
|
||||
string GetRandomDataWriteBufferSourcePath() const { return _sRandomDataWriteBufferSourcePath; }
|
||||
|
||||
void SetUseBurstSize(bool fUseBurstSize) { _fUseBurstSize = fUseBurstSize; }
|
||||
bool GetUseBurstSize() const { return _fUseBurstSize; }
|
||||
|
||||
void SetBurstSize(DWORD dwBurstSize) { _dwBurstSize = dwBurstSize; }
|
||||
DWORD GetBurstSize() const { return _dwBurstSize; }
|
||||
|
||||
void SetThinkTime(DWORD dwThinkTime) { _dwThinkTime = dwThinkTime; }
|
||||
DWORD GetThinkTime() const { return _dwThinkTime; }
|
||||
|
||||
void SetEnableThinkTime(bool fEnable) { _fThinkTime = fEnable; }
|
||||
bool GetEnableThinkTime() const { return _fThinkTime; }
|
||||
|
||||
void SetThreadsPerFile(DWORD dwThreadsPerFile) { _dwThreadsPerFile = dwThreadsPerFile; }
|
||||
DWORD GetThreadsPerFile() const { return _dwThreadsPerFile; }
|
||||
|
||||
void SetCreateFile(bool fCreateFile) { _fCreateFile = fCreateFile; }
|
||||
bool GetCreateFile() const { return _fCreateFile; }
|
||||
|
||||
void SetFileSize(UINT64 ullFileSize) { _ullFileSize = ullFileSize; }
|
||||
UINT64 GetFileSize() const { return _ullFileSize; } // TODO: InBytes
|
||||
|
||||
void SetMaxFileSize(UINT64 ullMaxFileSize) { _ullMaxFileSize = ullMaxFileSize; }
|
||||
UINT64 GetMaxFileSize() const { return _ullMaxFileSize; }
|
||||
|
||||
void SetWriteRatio(UINT32 ulWriteRatio) { _ulWriteRatio = ulWriteRatio; }
|
||||
UINT32 GetWriteRatio() const { return _ulWriteRatio; }
|
||||
|
||||
void SetUseParallelAsyncIO(bool fParallelAsyncIO) { _fParallelAsyncIO = fParallelAsyncIO; }
|
||||
bool GetUseParallelAsyncIO() const { return _fParallelAsyncIO; }
|
||||
|
||||
void SetUseInterlockedSequential(bool fInterlockedSequential) { _fInterlockedSequential = fInterlockedSequential; }
|
||||
bool GetUseInterlockedSequential() const { return _fInterlockedSequential; }
|
||||
|
||||
void SetThreadStrideInBytes(UINT64 ullThreadStride) { _ullThreadStride = ullThreadStride; }
|
||||
UINT64 GetThreadStrideInBytes() const { return _ullThreadStride; }
|
||||
|
||||
void SetIOPriorityHint(PRIORITY_HINT _hint)
|
||||
{
|
||||
assert(_hint < MaximumIoPriorityHintType);
|
||||
_ioPriorityHint = _hint;
|
||||
}
|
||||
PRIORITY_HINT GetIOPriorityHint() const { return _ioPriorityHint; }
|
||||
|
||||
void SetPrecreated(bool fPrecreated) { _fPrecreated = fPrecreated; }
|
||||
bool GetPrecreated() const { return _fPrecreated; }
|
||||
|
||||
void SetThroughput(DWORD dwThroughputBytesPerMillisecond) { _dwThroughputBytesPerMillisecond = dwThroughputBytesPerMillisecond; }
|
||||
DWORD GetThroughputInBytesPerMillisecond() const { return _dwThroughputBytesPerMillisecond; }
|
||||
|
||||
string GetXml() const;
|
||||
|
||||
bool AllocateAndFillRandomDataWriteBuffer();
|
||||
void FreeRandomDataWriteBuffer();
|
||||
BYTE* GetRandomDataWriteBuffer();
|
||||
|
||||
private:
|
||||
string _sPath;
|
||||
DWORD _dwBlockSize;
|
||||
DWORD _dwRequestCount; // TODO: change the name to something more descriptive (OutstandingRequestCount?)
|
||||
|
||||
UINT64 _ullBlockAlignment;
|
||||
bool _fBlockAlignmentValid;
|
||||
bool _fUseRandomAccessPattern;
|
||||
|
||||
UINT64 _ullBaseFileOffset;
|
||||
bool _fParallelAsyncIO;
|
||||
bool _fInterlockedSequential;
|
||||
bool _fDisableOSCache;
|
||||
bool _fDisableAllCache;
|
||||
bool _fZeroWriteBuffers;
|
||||
DWORD _dwThreadsPerFile;
|
||||
UINT64 _ullThreadStride;
|
||||
|
||||
bool _fCreateFile;
|
||||
bool _fPrecreated; // used to track which files have been created before the first timespan and which have to be created later
|
||||
UINT64 _ullFileSize;
|
||||
UINT64 _ullMaxFileSize;
|
||||
UINT32 _ulWriteRatio;
|
||||
bool _fUseBurstSize; // TODO: "use" or "enable"?; since burst size must be specified with the think time, one variable should be sufficient
|
||||
DWORD _dwBurstSize; // number of IOs in a burst
|
||||
DWORD _dwThinkTime; // time to pause before issuing the next burst of IOs
|
||||
// TODO: could this be removed by using _dwThinkTime==0?
|
||||
bool _fThinkTime; //variable to decide whether to think between IOs (default is false)
|
||||
DWORD _dwThroughputBytesPerMillisecond; // set to 0 to disable throttling
|
||||
|
||||
bool _fSequentialScanHint; // open file with the FILE_FLAG_SEQUENTIAL_SCAN hint
|
||||
bool _fRandomAccessHint; // open file with the FILE_FLAG_RANDOM_ACCESS hint
|
||||
bool _fUseLargePages; // Use large pages for IO buffers
|
||||
|
||||
UINT64 _cbRandomDataWriteBuffer; // if > 0, then the write buffer should be filled with random data
|
||||
string _sRandomDataWriteBufferSourcePath; // file that should be used for filling the write buffer (if the path is not available, use a crypto provider)
|
||||
BYTE *_pRandomDataWriteBuffer; // a buffer used for write data when _cbWriteBuffer > 0; it's shared by all the threads working on this target
|
||||
|
||||
PRIORITY_HINT _ioPriorityHint;
|
||||
|
||||
bool _FillRandomDataWriteBuffer();
|
||||
|
||||
friend class UnitTests::ProfileUnitTests;
|
||||
friend class UnitTests::TargetUnitTests;
|
||||
};
|
||||
|
||||
class TimeSpan
|
||||
{
|
||||
public:
|
||||
TimeSpan() :
|
||||
_ulDuration(10),
|
||||
_ulWarmUp(5),
|
||||
_ulCoolDown(0),
|
||||
_ulRandSeed(0),
|
||||
_dwThreadCount(0),
|
||||
_fGroupAffinity(false),
|
||||
_fDisableAffinity(false),
|
||||
_fCompletionRoutines(false),
|
||||
_fMeasureLatency(false),
|
||||
_fCalculateIopsStdDev(false),
|
||||
_ulIoBucketDurationInMilliseconds(1000)
|
||||
{
|
||||
}
|
||||
|
||||
void AddAffinityAssignment(UINT32 ulAffinity)
|
||||
{
|
||||
_vAffinity.push_back(ulAffinity);
|
||||
}
|
||||
vector<UINT32> GetAffinityAssignments() const { return _vAffinity; }
|
||||
|
||||
void AddTarget(const Target& target)
|
||||
{
|
||||
_vTargets.push_back(Target(target));
|
||||
}
|
||||
vector<Target> GetTargets() const { return _vTargets; }
|
||||
|
||||
void SetDuration(UINT32 ulDuration) { _ulDuration = ulDuration; }
|
||||
UINT32 GetDuration() const { return _ulDuration; }
|
||||
|
||||
void SetWarmup(UINT32 ulWarmup) { _ulWarmUp = ulWarmup; }
|
||||
UINT32 GetWarmup() const { return _ulWarmUp; }
|
||||
|
||||
void SetCooldown(UINT32 ulCooldown) { _ulCoolDown = ulCooldown; }
|
||||
UINT32 GetCooldown() const { return _ulCoolDown; }
|
||||
|
||||
void SetRandSeed(UINT32 ulRandSeed) { _ulRandSeed = ulRandSeed; }
|
||||
UINT32 GetRandSeed() const { return _ulRandSeed; }
|
||||
|
||||
void SetThreadCount(DWORD dwThreadCount) { _dwThreadCount = dwThreadCount; }
|
||||
DWORD GetThreadCount() const { return _dwThreadCount; }
|
||||
|
||||
void SetGroupAffinity(bool fGroupAffinity) { _fGroupAffinity = fGroupAffinity; }
|
||||
bool GetGroupAffinity() const { return _fGroupAffinity; }
|
||||
|
||||
void SetDisableAffinity(bool fDisableAffinity) { _fDisableAffinity = fDisableAffinity; }
|
||||
bool GetDisableAffinity() const { return _fDisableAffinity; }
|
||||
|
||||
void SetCompletionRoutines(bool fCompletionRoutines) { _fCompletionRoutines = fCompletionRoutines; }
|
||||
bool GetCompletionRoutines() const { return _fCompletionRoutines; }
|
||||
|
||||
void SetMeasureLatency(bool fMeasureLatency) { _fMeasureLatency = fMeasureLatency; }
|
||||
bool GetMeasureLatency() const { return _fMeasureLatency; }
|
||||
|
||||
void SetCalculateIopsStdDev(bool fCalculateStdDev) { _fCalculateIopsStdDev = fCalculateStdDev; }
|
||||
bool GetCalculateIopsStdDev() const { return _fCalculateIopsStdDev; }
|
||||
|
||||
void SetIoBucketDurationInMilliseconds(UINT32 ulIoBucketDurationInMilliseconds) { _ulIoBucketDurationInMilliseconds = ulIoBucketDurationInMilliseconds; }
|
||||
UINT32 GetIoBucketDurationInMilliseconds() const { return _ulIoBucketDurationInMilliseconds; }
|
||||
|
||||
string GetXml() const;
|
||||
void MarkFilesAsPrecreated(const vector<string> vFiles);
|
||||
|
||||
private:
|
||||
vector<Target> _vTargets;
|
||||
UINT32 _ulDuration;
|
||||
UINT32 _ulWarmUp;
|
||||
UINT32 _ulCoolDown;
|
||||
UINT32 _ulRandSeed;
|
||||
DWORD _dwThreadCount;
|
||||
bool _fGroupAffinity;
|
||||
bool _fDisableAffinity;
|
||||
vector<UINT32> _vAffinity;
|
||||
bool _fCompletionRoutines;
|
||||
bool _fMeasureLatency;
|
||||
bool _fCalculateIopsStdDev;
|
||||
UINT32 _ulIoBucketDurationInMilliseconds;
|
||||
|
||||
friend class UnitTests::ProfileUnitTests;
|
||||
};
|
||||
|
||||
enum class ResultsFormat
|
||||
{
|
||||
Text,
|
||||
Xml
|
||||
};
|
||||
|
||||
enum class PrecreateFiles
|
||||
{
|
||||
None,
|
||||
UseMaxSize,
|
||||
OnlyFilesWithConstantSizes,
|
||||
OnlyFilesWithConstantOrZeroSizes
|
||||
};
|
||||
|
||||
class Profile
|
||||
{
|
||||
public:
|
||||
Profile() :
|
||||
_fVerbose(false),
|
||||
_dwProgress(0),
|
||||
_fEtwEnabled(false),
|
||||
_fEtwProcess(false),
|
||||
_fEtwThread(false),
|
||||
_fEtwImageLoad(false),
|
||||
_fEtwDiskIO(false),
|
||||
_fEtwMemoryPageFaults(false),
|
||||
_fEtwMemoryHardFaults(false),
|
||||
_fEtwNetwork(false),
|
||||
_fEtwRegistry(false),
|
||||
_fEtwUsePagedMemory(false),
|
||||
_fEtwUsePerfTimer(false),
|
||||
_fEtwUseSystemTimer(false),
|
||||
_fEtwUseCyclesCounter(false),
|
||||
_resultsFormat(ResultsFormat::Text),
|
||||
_precreateFiles(PrecreateFiles::None)
|
||||
{
|
||||
}
|
||||
|
||||
void AddTimeSpan(const TimeSpan& timeSpan)
|
||||
{
|
||||
_vTimeSpans.push_back(TimeSpan(timeSpan));
|
||||
}
|
||||
|
||||
const vector<TimeSpan>& GetTimeSpans() const { return _vTimeSpans; }
|
||||
|
||||
void SetVerbose(bool fVerbose) { _fVerbose = fVerbose; }
|
||||
bool GetVerbose() const { return _fVerbose; }
|
||||
|
||||
void SetProgress(DWORD dwProgress) { _dwProgress = dwProgress; }
|
||||
DWORD GetProgress() const { return _dwProgress; }
|
||||
|
||||
void SetCmdLine(string sCmdLine) { _sCmdLine = sCmdLine; }
|
||||
string GetCmdLine() const { return _sCmdLine; };
|
||||
|
||||
void SetResultsFormat(ResultsFormat format) { _resultsFormat = format; }
|
||||
ResultsFormat GetResultsFormat() const { return _resultsFormat; }
|
||||
|
||||
void SetPrecreateFiles(PrecreateFiles c) { _precreateFiles = c; }
|
||||
PrecreateFiles GetPrecreateFiles() const { return _precreateFiles; }
|
||||
|
||||
//ETW
|
||||
void SetEtwEnabled(bool fEtwEnabled) { _fEtwEnabled = fEtwEnabled; }
|
||||
void SetEtwProcess(bool fEtwProcess) { _fEtwProcess = fEtwProcess; }
|
||||
void SetEtwThread(bool fEtwThread) { _fEtwThread = fEtwThread; }
|
||||
void SetEtwImageLoad(bool fEtwImageLoad) { _fEtwImageLoad = fEtwImageLoad; }
|
||||
void SetEtwDiskIO(bool fEtwDiskIO) { _fEtwDiskIO = fEtwDiskIO; }
|
||||
void SetEtwMemoryPageFaults(bool fEtwMemoryPageFaults) { _fEtwMemoryPageFaults = fEtwMemoryPageFaults; }
|
||||
void SetEtwMemoryHardFaults(bool fEtwMemoryHardFaults) { _fEtwMemoryHardFaults = fEtwMemoryHardFaults; }
|
||||
void SetEtwNetwork(bool fEtwNetwork) { _fEtwNetwork = fEtwNetwork; }
|
||||
void SetEtwRegistry(bool fEtwRegistry) { _fEtwRegistry = fEtwRegistry; }
|
||||
void SetEtwUsePagedMemory(bool fEtwUsePagedMemory) { _fEtwUsePagedMemory = fEtwUsePagedMemory; }
|
||||
void SetEtwUsePerfTimer(bool fEtwUsePerfTimer) { _fEtwUsePerfTimer = fEtwUsePerfTimer; }
|
||||
void SetEtwUseSystemTimer(bool fEtwUseSystemTimer) { _fEtwUseSystemTimer = fEtwUseSystemTimer; }
|
||||
void SetEtwUseCyclesCounter(bool fEtwUseCyclesCounter) { _fEtwUseCyclesCounter = fEtwUseCyclesCounter; }
|
||||
|
||||
bool GetEtwEnabled() const { return _fEtwEnabled; }
|
||||
bool GetEtwProcess() const { return _fEtwProcess; }
|
||||
bool GetEtwThread() const { return _fEtwThread; }
|
||||
bool GetEtwImageLoad() const { return _fEtwImageLoad; }
|
||||
bool GetEtwDiskIO() const { return _fEtwDiskIO; }
|
||||
bool GetEtwMemoryPageFaults() const { return _fEtwMemoryPageFaults; }
|
||||
bool GetEtwMemoryHardFaults() const { return _fEtwMemoryHardFaults; }
|
||||
bool GetEtwNetwork() const { return _fEtwNetwork; }
|
||||
bool GetEtwRegistry() const { return _fEtwRegistry; }
|
||||
bool GetEtwUsePagedMemory() const { return _fEtwUsePagedMemory; }
|
||||
bool GetEtwUsePerfTimer() const { return _fEtwUsePerfTimer; }
|
||||
bool GetEtwUseSystemTimer() const { return _fEtwUseSystemTimer; }
|
||||
bool GetEtwUseCyclesCounter() const { return _fEtwUseCyclesCounter; }
|
||||
|
||||
string GetXml() const;
|
||||
bool Validate(bool fSingleSpec) const;
|
||||
void MarkFilesAsPrecreated(const vector<string> vFiles);
|
||||
|
||||
private:
|
||||
Profile(const Profile& T);
|
||||
|
||||
vector<TimeSpan>_vTimeSpans;
|
||||
bool _fVerbose;
|
||||
DWORD _dwProgress;
|
||||
string _sCmdLine;
|
||||
ResultsFormat _resultsFormat;
|
||||
PrecreateFiles _precreateFiles;
|
||||
|
||||
//ETW
|
||||
bool _fEtwEnabled;
|
||||
bool _fEtwProcess;
|
||||
bool _fEtwThread;
|
||||
bool _fEtwImageLoad;
|
||||
bool _fEtwDiskIO;
|
||||
bool _fEtwMemoryPageFaults;
|
||||
bool _fEtwMemoryHardFaults;
|
||||
bool _fEtwNetwork;
|
||||
bool _fEtwRegistry;
|
||||
bool _fEtwUsePagedMemory;
|
||||
bool _fEtwUsePerfTimer;
|
||||
bool _fEtwUseSystemTimer;
|
||||
bool _fEtwUseCyclesCounter;
|
||||
|
||||
friend class UnitTests::ProfileUnitTests;
|
||||
};
|
||||
|
||||
class ThreadParameters
|
||||
{
|
||||
public:
|
||||
ThreadParameters() :
|
||||
pProfile(nullptr),
|
||||
pTimeSpan(nullptr),
|
||||
pullSharedSequentialOffsets(nullptr),
|
||||
ulRandSeed(0),
|
||||
ulThreadNo(0),
|
||||
ulRelativeThreadNo(0)
|
||||
{
|
||||
}
|
||||
|
||||
const Profile *pProfile;
|
||||
const TimeSpan *pTimeSpan;
|
||||
|
||||
vector<Target> vTargets;
|
||||
vector<HANDLE> vhTargets;
|
||||
vector<UINT64> vullFileSizes;
|
||||
vector<BYTE *> vpDataBuffers;
|
||||
vector<OVERLAPPED> vOverlapped; // each target has RequestCount OVERLAPPED structures
|
||||
vector<size_t> vOverlappedIdToTargetId;
|
||||
vector<size_t> vFirstOverlappedIdForTargetId; //id of the first overlapped structure in the vOverlapped vector by target
|
||||
vector<IOOperation> vdwIoType; //as many as vOverlapped; used by the completion routines
|
||||
vector<UINT64> vIoStartTimes;
|
||||
|
||||
// For vanilla sequential access (-s):
|
||||
// Private per-thread offsets, incremented directly, indexed to number of targets
|
||||
vector<UINT64> vullPrivateSequentialOffsets;
|
||||
|
||||
// For interlocked sequential access (-si):
|
||||
// Pointers to offsets shared between threads, incremented with an interlocked op
|
||||
UINT64* pullSharedSequentialOffsets;
|
||||
|
||||
UINT32 ulRandSeed;
|
||||
UINT32 ulThreadNo;
|
||||
UINT32 ulRelativeThreadNo;
|
||||
|
||||
// accounting
|
||||
volatile bool *pfAccountingOn;
|
||||
PUINT64 pullStartTime;
|
||||
ThreadResults *pResults;
|
||||
|
||||
//group affinity
|
||||
WORD wGroupNum;
|
||||
DWORD dwProcNum;
|
||||
GROUP_AFFINITY GroupAffinity;
|
||||
|
||||
HANDLE hStartEvent;
|
||||
|
||||
// TODO: check how it's used
|
||||
HANDLE hEndEvent; //used only in case of completion routines (not for IO Completion Ports)
|
||||
|
||||
bool AllocateAndFillBufferForTarget(const Target& target);
|
||||
BYTE* GetReadBuffer(size_t iTarget, size_t iRequest);
|
||||
BYTE* GetWriteBuffer(size_t iTarget, size_t iRequest);
|
||||
DWORD GetTotalRequestCount() const;
|
||||
|
||||
private:
|
||||
ThreadParameters(const ThreadParameters& T);
|
||||
};
|
||||
|
||||
class IResultParser
|
||||
{
|
||||
public:
|
||||
virtual string ParseResults(Profile& profile, const SystemInformation& system, vector<Results> vResults) = 0;
|
||||
virtual int GetTotalScore() = 0;
|
||||
virtual double GetAverageLatency() = 0;
|
||||
};
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
#pragma push_macro("min")
|
||||
#pragma push_macro("max")
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
template<typename T>
|
||||
class Histogram
|
||||
{
|
||||
private:
|
||||
|
||||
unsigned _samples;
|
||||
|
||||
#define USE_HASH_TABLE
|
||||
#ifdef USE_HASH_TABLE
|
||||
std::unordered_map<T,unsigned> _data;
|
||||
|
||||
std::map<T,unsigned> _GetSortedData() const
|
||||
{
|
||||
return std::map<T,unsigned>(_data.begin(), _data.end());
|
||||
}
|
||||
#else
|
||||
std::map<T,unsigned> _data;
|
||||
|
||||
std::map<T,unsigned> _GetSortedData() const
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
|
||||
Histogram()
|
||||
: _samples(0)
|
||||
{}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
_data.clear();
|
||||
_samples = 0;
|
||||
}
|
||||
|
||||
void Add(T v)
|
||||
{
|
||||
_data[ v ]++;
|
||||
_samples++;
|
||||
}
|
||||
|
||||
void Merge(const Histogram<T> &other)
|
||||
{
|
||||
for (auto i : other._data)
|
||||
{
|
||||
_data[ i.first ] += i.second;
|
||||
}
|
||||
|
||||
_samples += other._samples;
|
||||
}
|
||||
|
||||
T GetMin() const
|
||||
{
|
||||
T min(std::numeric_limits<T>::max());
|
||||
|
||||
for (auto i : _data)
|
||||
{
|
||||
if (i.first < min)
|
||||
{
|
||||
min = i.first;
|
||||
}
|
||||
}
|
||||
|
||||
return min;
|
||||
}
|
||||
|
||||
T GetMax() const
|
||||
{
|
||||
T max(std::numeric_limits<T>::min());
|
||||
|
||||
for (auto i : _data)
|
||||
{
|
||||
if (i.first > max)
|
||||
{
|
||||
max = i.first;
|
||||
}
|
||||
}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
unsigned GetSampleSize() const
|
||||
{
|
||||
return _samples;
|
||||
}
|
||||
|
||||
T GetPercentile(double p) const
|
||||
{
|
||||
// ISSUE-REVIEW
|
||||
// What do the 0th and 100th percentile really mean?
|
||||
if ((p < 0) || (p > 1))
|
||||
{
|
||||
throw std::invalid_argument("Percentile must be >= 0 and <= 1");
|
||||
}
|
||||
|
||||
const double target = GetSampleSize() * p;
|
||||
|
||||
unsigned cur = 0;
|
||||
for (auto i : _GetSortedData())
|
||||
{
|
||||
cur += i.second;
|
||||
if (cur >= target)
|
||||
{
|
||||
return i.first;
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("Percentile is undefined");
|
||||
}
|
||||
|
||||
T GetPercentile(int p) const
|
||||
{
|
||||
return GetPercentile(static_cast<double>(p)/100);
|
||||
}
|
||||
|
||||
T GetMedian() const
|
||||
{
|
||||
return GetPercentile(0.5);
|
||||
}
|
||||
|
||||
double GetStdDev() const { return GetStandardDeviation(); }
|
||||
double GetAvg() const { return GetMean(); }
|
||||
|
||||
double GetMean() const
|
||||
{
|
||||
double sum(0);
|
||||
unsigned samples = GetSampleSize();
|
||||
|
||||
for (auto i : _data)
|
||||
{
|
||||
double bucket_val =
|
||||
static_cast<double>(i.first) * i.second / samples;
|
||||
|
||||
if (sum + bucket_val < 0)
|
||||
{
|
||||
throw std::overflow_error("while trying to accumulate sum");
|
||||
}
|
||||
|
||||
sum += bucket_val;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
double GetStandardDeviation() const
|
||||
{
|
||||
double mean(GetMean());
|
||||
double ssd(0);
|
||||
|
||||
for (auto i : _data)
|
||||
{
|
||||
double dev = static_cast<double>(i.first) - mean;
|
||||
double sqdev = dev*dev;
|
||||
ssd += i.second * sqdev;
|
||||
}
|
||||
|
||||
return sqrt(ssd / GetSampleSize());
|
||||
}
|
||||
|
||||
std::string GetHistogramCsv(const unsigned bins) const
|
||||
{
|
||||
return GetHistogramCsv(bins, GetMin(), GetMax());
|
||||
}
|
||||
|
||||
std::string GetHistogramCsv(const unsigned bins, const T LOW, const T HIGH) const
|
||||
{
|
||||
// ISSUE-REVIEW
|
||||
// Currently bins are defined as strictly less-than
|
||||
// their upper limit, with the exception of the last
|
||||
// bin. Otherwise where would I put the max value?
|
||||
const double binSize = static_cast<double>((HIGH - LOW) / bins);
|
||||
double limit = static_cast<double>(LOW);
|
||||
|
||||
std::ostringstream os;
|
||||
os.precision(std::numeric_limits<T>::digits10);
|
||||
|
||||
std::map<T,unsigned> sortedData = _GetSortedData();
|
||||
|
||||
auto pos = sortedData.begin();
|
||||
|
||||
unsigned cumulative = 0;
|
||||
|
||||
for (unsigned bin = 1; bin <= bins; ++bin)
|
||||
{
|
||||
unsigned count = 0;
|
||||
limit += binSize;
|
||||
|
||||
while (pos != sortedData.end() &&
|
||||
(pos->first < limit || bin == bins))
|
||||
{
|
||||
count += pos->second;
|
||||
++pos;
|
||||
}
|
||||
|
||||
cumulative += count;
|
||||
|
||||
os << limit << "," << count << "," << cumulative << std::endl;
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string GetRawCsv() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
os.precision(std::numeric_limits<T>::digits10);
|
||||
|
||||
for (auto i : _GetSortedData())
|
||||
{
|
||||
os << i.first << "," << i.second << std::endl;
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string GetRaw() const
|
||||
{
|
||||
std::ostringstream os;
|
||||
|
||||
for (auto i : _GetSortedData())
|
||||
{
|
||||
os << i.second << " " << i.first << std::endl;
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
};
|
||||
|
||||
#pragma pop_macro("min")
|
||||
#pragma pop_macro("max")
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "IoBucketizer.h"
|
||||
|
||||
const unsigned __int64 INVALID_BUCKET_DURATION = 0;
|
||||
|
||||
IoBucketizer::IoBucketizer()
|
||||
: _bucketDuration(INVALID_BUCKET_DURATION),
|
||||
_validBuckets(0)
|
||||
{}
|
||||
|
||||
void IoBucketizer::Initialize(unsigned __int64 bucketDuration, size_t validBuckets)
|
||||
{
|
||||
if (_bucketDuration != INVALID_BUCKET_DURATION)
|
||||
{
|
||||
throw std::runtime_error("IoBucketizer has already been initialized");
|
||||
}
|
||||
if (bucketDuration == INVALID_BUCKET_DURATION)
|
||||
{
|
||||
throw std::invalid_argument("Bucket duration must be a positive integer");
|
||||
}
|
||||
|
||||
_bucketDuration = bucketDuration;
|
||||
_validBuckets = validBuckets;
|
||||
_vBuckets.reserve(_validBuckets);
|
||||
}
|
||||
|
||||
void IoBucketizer::Add(unsigned __int64 ioCompletionTime)
|
||||
{
|
||||
if (_bucketDuration == INVALID_BUCKET_DURATION)
|
||||
{
|
||||
throw std::runtime_error("IoBucketizer has not been initialized");
|
||||
}
|
||||
|
||||
size_t bucketNumber = static_cast<size_t>(ioCompletionTime / _bucketDuration);
|
||||
size_t currentSize = _vBuckets.size();
|
||||
if (currentSize < bucketNumber + 1)
|
||||
{
|
||||
_vBuckets.resize(bucketNumber + 1);
|
||||
// Zero the new entries. Note that size is 1-based and bucketNumber is 0-based.
|
||||
for (size_t i = currentSize; i <= bucketNumber; i++)
|
||||
{
|
||||
_vBuckets[i] = 0;
|
||||
}
|
||||
}
|
||||
_vBuckets[bucketNumber]++;
|
||||
}
|
||||
|
||||
size_t IoBucketizer::GetNumberOfValidBuckets() const
|
||||
{
|
||||
// Buckets beyond this may exist since Add is willing to extend the vector
|
||||
// beyond the expected number of valid buckets, but they are not comparable
|
||||
// buckets (straggling IOs over the timespan boundary).
|
||||
return (_vBuckets.size() > _validBuckets ? _validBuckets : _vBuckets.size());
|
||||
}
|
||||
|
||||
size_t IoBucketizer::GetNumberOfBuckets() const
|
||||
{
|
||||
return _vBuckets.size();
|
||||
}
|
||||
|
||||
unsigned int IoBucketizer::GetIoBucket(size_t bucketNumber) const
|
||||
{
|
||||
return _vBuckets[bucketNumber];
|
||||
}
|
||||
|
||||
double IoBucketizer::_GetMean() const
|
||||
{
|
||||
size_t numBuckets = GetNumberOfValidBuckets();
|
||||
double sum = 0;
|
||||
|
||||
for (size_t i = 0; i < numBuckets; i++)
|
||||
{
|
||||
sum += static_cast<double>(_vBuckets[i]) / numBuckets;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
double IoBucketizer::GetStandardDeviation() const
|
||||
{
|
||||
size_t numBuckets = GetNumberOfValidBuckets();
|
||||
|
||||
if(numBuckets == 0)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double mean = _GetMean();
|
||||
double ssd = 0;
|
||||
|
||||
for (size_t i = 0; i < numBuckets; i++)
|
||||
{
|
||||
double dev = static_cast<double>(_vBuckets[i]) - mean;
|
||||
double sqdev = dev*dev;
|
||||
ssd += sqdev;
|
||||
}
|
||||
|
||||
return sqrt(ssd / numBuckets);
|
||||
}
|
||||
|
||||
void IoBucketizer::Merge(const IoBucketizer& other)
|
||||
{
|
||||
if(other._vBuckets.size() > _vBuckets.size())
|
||||
{
|
||||
_vBuckets.resize(other._vBuckets.size());
|
||||
}
|
||||
if (other._validBuckets > _validBuckets)
|
||||
{
|
||||
_validBuckets = other._validBuckets;
|
||||
}
|
||||
for(size_t i = 0; i < other._vBuckets.size(); i++)
|
||||
{
|
||||
_vBuckets[i] += other.GetIoBucket(i);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
class IoBucketizer
|
||||
{
|
||||
public:
|
||||
IoBucketizer();
|
||||
void Initialize(unsigned __int64 bucketDuration, size_t validBuckets);
|
||||
|
||||
size_t GetNumberOfValidBuckets() const;
|
||||
size_t GetNumberOfBuckets() const;
|
||||
unsigned int GetIoBucket(size_t bucketNumber) const;
|
||||
void Add(unsigned __int64 ioCompletionTime);
|
||||
double GetStandardDeviation() const;
|
||||
void Merge(const IoBucketizer& other);
|
||||
private:
|
||||
double _GetMean() const;
|
||||
|
||||
unsigned __int64 _bucketDuration;
|
||||
size_t _validBuckets;
|
||||
std::vector<unsigned int> _vBuckets;
|
||||
};
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#define INITGUID //Include this #define to use SystemTraceControlGuid in Evntrace.h.
|
||||
#include <Evntrace.h> //ETW
|
||||
#include <Winternl.h> //ntdll.dll
|
||||
|
||||
|
||||
void PrintError(const char *format, ...);
|
||||
void *ManagedMalloc(size_t size);
|
||||
namespace UnitTests
|
||||
{
|
||||
class IORequestGeneratorUnitTests;
|
||||
}
|
||||
|
||||
class IORequestGenerator
|
||||
{
|
||||
public:
|
||||
IORequestGenerator() :
|
||||
_hNTDLL(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool GenerateRequests(Profile& profile, IResultParser& resultParser, PRINTF pPrintOut, PRINTF pPrintError, PRINTF pPrintVerbose, struct Synchronization *pSynch, int *totalScore, double *averageLatency);
|
||||
static UINT64 GetNextFileOffset(ThreadParameters& tp, size_t targetNum, UINT64 prevOffset);
|
||||
static UINT64 GetStartingFileOffset(ThreadParameters& tp, size_t targetNum);
|
||||
static UINT64 GetThreadBaseFileOffset(ThreadParameters& tp, size_t targetNum);
|
||||
|
||||
private:
|
||||
|
||||
struct CreateFileParameters
|
||||
{
|
||||
string sPath;
|
||||
UINT64 ullFileSize;
|
||||
bool fZeroWriteBuffers;
|
||||
};
|
||||
|
||||
bool _GenerateRequestsForTimeSpan(const Profile& profile, const TimeSpan& timeSpan, Results& results, struct Synchronization *pSynch);
|
||||
void _AbortWorkerThreads(HANDLE hStartEvent, vector<HANDLE>& vhThreads) const;
|
||||
void _CloseOpenFiles(vector<HANDLE>& vhFiles) const;
|
||||
DWORD _CreateDirectoryPath(const char *path) const;
|
||||
bool _CreateFile(UINT64 ullFileSize, const char *pszFilename, bool fZeroBuffers, bool fVerbose) const;
|
||||
void _DisplayFileSizeVerbose(bool fVerbose, UINT64 fsize) const;
|
||||
bool _GetActiveGroupsAndProcs() const;
|
||||
struct ETWSessionInfo _GetResultETWSession(const EVENT_TRACE_PROPERTIES *pTraceProperties) const;
|
||||
bool _GetSystemPerfInfo(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *pInfo, UINT32 uCpuCount) const;
|
||||
void _InitializeGlobalParameters();
|
||||
bool _LoadDLLs();
|
||||
bool _StopETW(bool fUseETW, TRACEHANDLE hTraceSession) const;
|
||||
void _TerminateWorkerThreads(vector<HANDLE>& vhThreads) const;
|
||||
bool _ValidateProfile(const Profile& profile) const;
|
||||
vector<struct CreateFileParameters> _GetFilesToPrecreate(const Profile& profile) const;
|
||||
void _MarkFilesAsCreated(Profile& profile, const vector<struct CreateFileParameters>& vFiles) const;
|
||||
bool _PrecreateFiles(Profile& profile) const;
|
||||
|
||||
HINSTANCE volatile _hNTDLL; //handle to ntdll.dll
|
||||
|
||||
friend class UnitTests::IORequestGeneratorUnitTests;
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "OverlappedQueue.h"
|
||||
#include <assert.h>
|
||||
|
||||
OverlappedQueue::OverlappedQueue(void) :
|
||||
_pHead(nullptr),
|
||||
_pTail(nullptr),
|
||||
_cItems(0)
|
||||
{
|
||||
}
|
||||
|
||||
void OverlappedQueue::Add(OVERLAPPED *pOverlapped)
|
||||
{
|
||||
pOverlapped->Internal = NULL;
|
||||
if (_pHead == nullptr)
|
||||
{
|
||||
assert(_pTail == nullptr);
|
||||
_pHead = pOverlapped;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(_pTail != nullptr);
|
||||
_pTail->Internal = (ULONG_PTR)pOverlapped;
|
||||
}
|
||||
_pTail = pOverlapped;
|
||||
_cItems++;
|
||||
}
|
||||
|
||||
bool OverlappedQueue::IsEmpty(void) const
|
||||
{
|
||||
return (_pHead == nullptr);
|
||||
}
|
||||
|
||||
OVERLAPPED *OverlappedQueue::Remove(void)
|
||||
{
|
||||
assert(!IsEmpty());
|
||||
|
||||
OVERLAPPED *pOverlapped = _pHead;
|
||||
_pHead = (OVERLAPPED *)pOverlapped->Internal;
|
||||
if (_pHead == nullptr)
|
||||
{
|
||||
_pTail = nullptr;
|
||||
}
|
||||
_cItems--;
|
||||
return pOverlapped;
|
||||
}
|
||||
|
||||
size_t OverlappedQueue::GetCount() const
|
||||
{
|
||||
return _cItems;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
|
||||
//
|
||||
// OverlappedQueue is a simple class that implements a queue for OVERLAPPED elements
|
||||
//
|
||||
class OverlappedQueue
|
||||
{
|
||||
public:
|
||||
OverlappedQueue(void);
|
||||
|
||||
void Add(OVERLAPPED *pOverlapped);
|
||||
bool IsEmpty(void) const;
|
||||
OVERLAPPED * Remove(void);
|
||||
size_t GetCount() const;
|
||||
|
||||
private:
|
||||
OVERLAPPED *_pHead;
|
||||
OVERLAPPED *_pTail;
|
||||
size_t _cItems;
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "ThroughputMeter.h"
|
||||
|
||||
ThroughputMeter::ThroughputMeter(void) :
|
||||
_fRunning(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool ThroughputMeter::IsRunning(void) const
|
||||
{
|
||||
return _fRunning;
|
||||
}
|
||||
|
||||
void ThroughputMeter::Start(DWORD cBytesPerMillisecond, DWORD dwBlockSize, DWORD dwThinkTime, DWORD dwBurstSize)
|
||||
{
|
||||
// Initialization
|
||||
_cbCompleted = 0;
|
||||
_cIO = 0; // number of completed IOs in the current burst
|
||||
_cbBlockSize = dwBlockSize;
|
||||
|
||||
_fThrottle = false;
|
||||
_cBytesPerMillisecond = 0;
|
||||
_fThink = false;
|
||||
_ullDelayUntil = 0;
|
||||
_thinkTime = 0;
|
||||
_burstSize = 0;
|
||||
_fRunning = false;
|
||||
|
||||
/// GetTickCount64 -> GetTickCount
|
||||
_ullStartTimestamp = GetTickCount();
|
||||
|
||||
if (0 != cBytesPerMillisecond)
|
||||
{
|
||||
_fThrottle = true;
|
||||
_cBytesPerMillisecond = cBytesPerMillisecond;
|
||||
_fRunning = true;
|
||||
}
|
||||
else if (0 != dwThinkTime)
|
||||
{
|
||||
_fThink = true;
|
||||
_thinkTime = dwThinkTime;
|
||||
_burstSize = dwBurstSize;
|
||||
_fRunning = true;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD ThroughputMeter::GetSleepTime(void) const
|
||||
{
|
||||
if (_fThink)
|
||||
{
|
||||
/// GetTickCount64 -> GetTickCount
|
||||
ULONGLONG ullTimestamp = GetTickCount();
|
||||
if (ullTimestamp < _ullDelayUntil)
|
||||
{
|
||||
return (DWORD)(_ullDelayUntil - ullTimestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (_fThrottle) ? _GetThrottleTime() : 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_fThrottle) // think time has not been specified only check for throttling
|
||||
{
|
||||
return _GetThrottleTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DWORD ThroughputMeter::_GetThrottleTime(void) const
|
||||
{
|
||||
/// GetTickCount64 -> GetTickCount
|
||||
ULONGLONG cbExpected = (GetTickCount() - _ullStartTimestamp) * _cBytesPerMillisecond;
|
||||
return cbExpected >= (_cbCompleted + _cbBlockSize) ? 0 : 1;
|
||||
}
|
||||
|
||||
void ThroughputMeter::Adjust(size_t cb)
|
||||
{
|
||||
_cbCompleted += cb;
|
||||
_cIO++;
|
||||
if (_fThink)
|
||||
{
|
||||
if (_cIO >= _burstSize)
|
||||
{
|
||||
_cIO = 0;
|
||||
/// GetTickCount64 -> GetTickCount
|
||||
_ullDelayUntil = GetTickCount() + _thinkTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
|
||||
// ThroughputMeter class assists in metering out throughput over
|
||||
// time. The meter is started by calling Start() with the throughput
|
||||
// to be simulated. GetSleepTime() returns 0 when the next IO can be issued.
|
||||
// Adjust() is called to notify the ThroughputMeter about how many bytes were read/written.
|
||||
class ThroughputMeter
|
||||
{
|
||||
public:
|
||||
ThroughputMeter(void);
|
||||
|
||||
bool IsRunning(void) const;
|
||||
void Start(DWORD cBytesPerMillisecond, DWORD dwBlockSize, DWORD dwThinkTime, DWORD dwBurstSize);
|
||||
DWORD GetSleepTime(void) const;
|
||||
void Adjust(size_t cb);
|
||||
|
||||
private:
|
||||
DWORD _GetThrottleTime(void) const;
|
||||
|
||||
bool _fRunning; // true = throughput monitoring is on
|
||||
bool _fThrottle; // true = throttling is on
|
||||
bool _fThink; // true = think time is enabled
|
||||
ULONGLONG _cbCompleted; // completed IO
|
||||
DWORD _cbBlockSize;
|
||||
DWORD _cBytesPerMillisecond; // rate of throttling
|
||||
ULONGLONG _ullStartTimestamp;
|
||||
ULONGLONG _ullDelayUntil; // timestamp at which the next IO can be executed
|
||||
DWORD _thinkTime; // time to sleep between burst of IOs
|
||||
DWORD _burstSize; // number of IOs in a burst. meaningless if think time is zero
|
||||
DWORD _cIO; // count of IOs in the current burst
|
||||
};
|
||||
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "etw.h"
|
||||
#include "common.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <Wmistr.h> //WNODE_HEADER
|
||||
|
||||
#define INITGUID //Include this #define to use SystemTraceControlGuid in Evntrace.h.
|
||||
#include <Evntrace.h> //ETW
|
||||
|
||||
#include "IORequestGenerator.h"
|
||||
|
||||
// variables declared in IORequestGenerator.cpp
|
||||
extern struct ETWEventCounters g_EtwEventCounters;
|
||||
extern BOOL volatile g_bTracing;
|
||||
|
||||
|
||||
DEFINE_GUID ( /* 3d6fa8d4-fe05-11d0-9dda-00c04fd7ba7c */
|
||||
DiskIoGuid,
|
||||
0x3d6fa8d4,
|
||||
0xfe05,
|
||||
0x11d0,
|
||||
0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c
|
||||
);
|
||||
|
||||
DEFINE_GUID ( /* 90cbdc39-4a3e-11d1-84f4-0000f80464e3 */
|
||||
FileIoGuid,
|
||||
0x90cbdc39,
|
||||
0x4a3e,
|
||||
0x11d1,
|
||||
0x84, 0xf4, 0x00, 0x00, 0xf8, 0x04, 0x64, 0xe3
|
||||
);
|
||||
|
||||
DEFINE_GUID ( /* 2cb15d1d-5fc1-11d2-abe1-00a0c911f518 */
|
||||
ImageLoadGuid,
|
||||
0x2cb15d1d,
|
||||
0x5fc1,
|
||||
0x11d2,
|
||||
0xab, 0xe1, 0x00, 0xa0, 0xc9, 0x11, 0xf5, 0x18
|
||||
);
|
||||
|
||||
DEFINE_GUID ( /* 3d6fa8d3-fe05-11d0-9dda-00c04fd7ba7c */
|
||||
PageFaultGuid,
|
||||
0x3d6fa8d3,
|
||||
0xfe05,
|
||||
0x11d0,
|
||||
0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c
|
||||
);
|
||||
|
||||
DEFINE_GUID ( /* 9a280ac0-c8e0-11d1-84e2-00c04fb998a2 */
|
||||
TcpIpGuid,
|
||||
0x9a280ac0,
|
||||
0xc8e0,
|
||||
0x11d1,
|
||||
0x84, 0xe2, 0x00, 0xc0, 0x4f, 0xb9, 0x98, 0xa2
|
||||
);
|
||||
|
||||
DEFINE_GUID ( /* bf3a50c5-a9c9-4988-a005-2df0b7c80f80 */
|
||||
UdpIpGuid,
|
||||
0xbf3a50c5,
|
||||
0xa9c9,
|
||||
0x4988,
|
||||
0xa0, 0x05, 0x2d, 0xf0, 0xb7, 0xc8, 0x0f, 0x80
|
||||
);
|
||||
|
||||
DEFINE_GUID ( /* 3d6fa8d0-fe05-11d0-9dda-00c04fd7ba7c */
|
||||
ProcessGuid,
|
||||
0x3d6fa8d0,
|
||||
0xfe05,
|
||||
0x11d0,
|
||||
0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c
|
||||
);
|
||||
|
||||
DEFINE_GUID ( /* AE53722E-C863-11d2-8659-00C04FA321A1 */
|
||||
RegistryGuid,
|
||||
0xae53722e,
|
||||
0xc863,
|
||||
0x11d2,
|
||||
0x86, 0x59, 0x0, 0xc0, 0x4f, 0xa3, 0x21, 0xa1
|
||||
);
|
||||
|
||||
DEFINE_GUID ( /* 3d6fa8d1-fe05-11d0-9dda-00c04fd7ba7c */
|
||||
ThreadGuid,
|
||||
0x3d6fa8d1,
|
||||
0xfe05,
|
||||
0x11d0,
|
||||
0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c
|
||||
);
|
||||
|
||||
/*****************************************************************************/
|
||||
// consumes events' data
|
||||
//
|
||||
BOOL TraceEvents()
|
||||
{
|
||||
TRACEHANDLE handles[1];
|
||||
EVENT_TRACE_LOGFILE logfile;
|
||||
|
||||
memset(&logfile, 0, sizeof(EVENT_TRACE_LOGFILE));
|
||||
|
||||
logfile.LoggerName = KERNEL_LOGGER_NAME;
|
||||
logfile.LogFileName = NULL;
|
||||
logfile.LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
|
||||
|
||||
logfile.IsKernelTrace = true;
|
||||
|
||||
handles[0] = OpenTrace(&logfile);
|
||||
if( (TRACEHANDLE)INVALID_HANDLE_VALUE == handles[0] )
|
||||
{
|
||||
PrintError("ETW ERROR: OpenTrace failed (error code: %d)\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ProcessTrace(handles, 1, 0, 0);
|
||||
CloseTrace(handles[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// allocates memory for ETW properties structure
|
||||
//
|
||||
PEVENT_TRACE_PROPERTIES allocateEventTraceProperties()
|
||||
{
|
||||
PEVENT_TRACE_PROPERTIES pProperties = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
|
||||
size = sizeof(EVENT_TRACE_PROPERTIES)+sizeof(KERNEL_LOGGER_NAME);
|
||||
pProperties = (PEVENT_TRACE_PROPERTIES)malloc(size);
|
||||
if( NULL == pProperties )
|
||||
{
|
||||
PrintError("FATAL ERROR: unable to allocate memory (error code: %d)\n", GetLastError());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(pProperties, 0, size);
|
||||
|
||||
pProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
|
||||
pProperties->Wnode.BufferSize = (ULONG)size;
|
||||
pProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
|
||||
|
||||
strcpy_s((char *)pProperties+pProperties->LoggerNameOffset,
|
||||
size-pProperties->LoggerNameOffset, KERNEL_LOGGER_NAME);
|
||||
|
||||
return pProperties;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// callback function for disk I/O events
|
||||
void WINAPI eventDiskIo(PEVENT_TRACE pEvent)
|
||||
{
|
||||
if( EVENT_TRACE_TYPE_IO_READ == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullIORead;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_IO_WRITE == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullIOWrite;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// callback function for LoadImage events
|
||||
//
|
||||
void WINAPI eventLoadImage(PEVENT_TRACE pEvent)
|
||||
{
|
||||
if( EVENT_TRACE_TYPE_LOAD == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullImageLoad;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// callback function for memory events
|
||||
//
|
||||
void WINAPI eventPageFault(PEVENT_TRACE pEvent)
|
||||
{
|
||||
if( EVENT_TRACE_TYPE_MM_COW == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullMMCopyOnWrite;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_MM_DZF == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullMMDemandZeroFault;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_MM_GPF == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullMMGuardPageFault;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_MM_HPF == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullMMHardPageFault;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_MM_TF == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullMMTransitionFault;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// callback function for network and TCP/IP events
|
||||
//
|
||||
void WINAPI eventTcpIp(PEVENT_TRACE pEvent)
|
||||
{
|
||||
if( EVENT_TRACE_TYPE_ACCEPT == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullNetAccept;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_CONNECT == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullNetConnect;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_DISCONNECT == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullNetDisconnect;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_RECEIVE == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullNetTcpReceive;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_RECONNECT == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullNetReconnect;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_RETRANSMIT == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullNetRetransmit;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_SEND == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullNetTcpSend;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// callback function for UDP/IP events
|
||||
//
|
||||
void WINAPI eventUdpIp(PEVENT_TRACE pEvent)
|
||||
{
|
||||
if( EVENT_TRACE_TYPE_SEND == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullNetUdpSend;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_RECEIVE == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullNetUdpReceive;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// callback function for thread events
|
||||
//
|
||||
void WINAPI eventThread(PEVENT_TRACE pEvent)
|
||||
{
|
||||
if( EVENT_TRACE_TYPE_START == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullThreadStart;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_END == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullThreadEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// callback function for process events
|
||||
//
|
||||
void WINAPI eventProcess(PEVENT_TRACE pEvent)
|
||||
{
|
||||
if( EVENT_TRACE_TYPE_START == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullProcessStart;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_END == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullProcessEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// callback function for registry events
|
||||
//
|
||||
void WINAPI eventRegistry(PEVENT_TRACE pEvent)
|
||||
{
|
||||
if( EVENT_TRACE_TYPE_REGCREATE == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegCreate;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_REGDELETE == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegDelete;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_REGDELETEVALUE == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegDeleteValue;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_REGENUMERATEKEY == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegEnumerateKey;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_REGENUMERATEVALUEKEY == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegEnumerateValueKey;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_REGFLUSH == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegFlush;
|
||||
}
|
||||
// else if( EVENT_TRACE_TYPE_REGKCBDMP == pEvent->Header.Class.Type )
|
||||
// {
|
||||
// ++ETWEventCounters.ullRegKcbDmp;
|
||||
// }
|
||||
else if( EVENT_TRACE_TYPE_REGOPEN == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegOpen;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_REGQUERY == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegQuery;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_REGQUERYMULTIPLEVALUE == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegQueryMultipleValue;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_REGQUERYVALUE == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegQueryValue;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_REGSETINFORMATION == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegSetInformation;
|
||||
}
|
||||
else if( EVENT_TRACE_TYPE_REGSETVALUE == pEvent->Header.Class.Type )
|
||||
{
|
||||
++g_EtwEventCounters.ullRegSetValue;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// starts ETW session and sets callback functions for various groups of events
|
||||
//
|
||||
TRACEHANDLE StartETWSession(const Profile& profile)
|
||||
{
|
||||
PEVENT_TRACE_PROPERTIES pProperties;
|
||||
|
||||
pProperties = allocateEventTraceProperties();
|
||||
if (nullptr == pProperties)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE;
|
||||
|
||||
//use paged memory
|
||||
if (profile.GetEtwUsePagedMemory())
|
||||
{
|
||||
pProperties->LogFileMode |= EVENT_TRACE_USE_PAGED_MEMORY;
|
||||
}
|
||||
|
||||
//
|
||||
// event classes
|
||||
//
|
||||
if (profile.GetEtwProcess())
|
||||
{
|
||||
pProperties->EnableFlags |= EVENT_TRACE_FLAG_PROCESS;
|
||||
SetTraceCallback(&ProcessGuid, eventThread);
|
||||
}
|
||||
|
||||
if (profile.GetEtwThread())
|
||||
{
|
||||
pProperties->EnableFlags |= EVENT_TRACE_FLAG_THREAD;
|
||||
SetTraceCallback(&ThreadGuid, eventThread);
|
||||
}
|
||||
|
||||
if (profile.GetEtwImageLoad())
|
||||
{
|
||||
pProperties->EnableFlags |= EVENT_TRACE_FLAG_IMAGE_LOAD;
|
||||
SetTraceCallback(&ImageLoadGuid, eventLoadImage);
|
||||
}
|
||||
|
||||
if (profile.GetEtwDiskIO())
|
||||
{
|
||||
pProperties->EnableFlags |= EVENT_TRACE_FLAG_DISK_IO;
|
||||
SetTraceCallback(&DiskIoGuid, eventDiskIo);
|
||||
}
|
||||
|
||||
if (profile.GetEtwMemoryPageFaults())
|
||||
{
|
||||
pProperties->EnableFlags |= EVENT_TRACE_FLAG_MEMORY_PAGE_FAULTS;
|
||||
SetTraceCallback(&PageFaultGuid, eventPageFault);
|
||||
}
|
||||
|
||||
if (profile.GetEtwMemoryHardFaults())
|
||||
{
|
||||
pProperties->EnableFlags |= EVENT_TRACE_FLAG_MEMORY_HARD_FAULTS;
|
||||
SetTraceCallback(&PageFaultGuid, eventPageFault);
|
||||
}
|
||||
|
||||
if (profile.GetEtwNetwork())
|
||||
{
|
||||
pProperties->EnableFlags |= EVENT_TRACE_FLAG_NETWORK_TCPIP;
|
||||
SetTraceCallback(&TcpIpGuid, eventTcpIp);
|
||||
SetTraceCallback(&UdpIpGuid, eventUdpIp);
|
||||
}
|
||||
|
||||
if (profile.GetEtwRegistry())
|
||||
{
|
||||
pProperties->EnableFlags |= EVENT_TRACE_FLAG_REGISTRY;
|
||||
SetTraceCallback(&RegistryGuid, eventRegistry);
|
||||
}
|
||||
|
||||
//
|
||||
// timer
|
||||
//
|
||||
if (profile.GetEtwUsePerfTimer())
|
||||
{
|
||||
pProperties->Wnode.ClientContext = 1;
|
||||
}
|
||||
if (profile.GetEtwUseSystemTimer())
|
||||
{
|
||||
pProperties->Wnode.ClientContext = 2;
|
||||
}
|
||||
if (profile.GetEtwUseCyclesCounter())
|
||||
{
|
||||
pProperties->Wnode.ClientContext = 3;
|
||||
}
|
||||
|
||||
pProperties->Wnode.Guid = SystemTraceControlGuid;
|
||||
|
||||
TRACEHANDLE hTraceSession;
|
||||
ULONG ret = StartTrace(&hTraceSession, KERNEL_LOGGER_NAME, pProperties);
|
||||
free(pProperties);
|
||||
if (ERROR_SUCCESS != ret)
|
||||
{
|
||||
PrintError("Error starting trace session\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hTraceSession;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// stops ETW session
|
||||
//
|
||||
PEVENT_TRACE_PROPERTIES StopETWSession(TRACEHANDLE hTraceSession)
|
||||
{
|
||||
PEVENT_TRACE_PROPERTIES pProperties;
|
||||
|
||||
pProperties = allocateEventTraceProperties();
|
||||
if( NULL == pProperties )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ULONG ret;
|
||||
|
||||
ret = ControlTrace(hTraceSession, NULL, pProperties, EVENT_TRACE_CONTROL_STOP);
|
||||
if( ERROR_SUCCESS != ret )
|
||||
{
|
||||
PrintError("Error stopping trace session\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//wait
|
||||
while(g_bTracing)
|
||||
{
|
||||
Sleep(10); // TODO: remove active waiting
|
||||
}
|
||||
|
||||
return pProperties;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <Wmistr.h> ///WNODE_HEADER
|
||||
#define INITGUID //Include this #define to use SystemTraceControlGuid in Evntrace.h.
|
||||
#include <Evntrace.h> //ETW
|
||||
#include "..\Common\Common.h"
|
||||
|
||||
BOOL TraceEvents();
|
||||
TRACEHANDLE StartETWSession(const Profile& profile);
|
||||
PEVENT_TRACE_PROPERTIES StopETWSession(TRACEHANDLE hTraceSession);
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,14 @@
|
||||
DISKSPD
|
||||
=======
|
||||
|
||||
DISKSPD is a storage load generator / performance test tool from the Windows/Windows Server and Cloud Server Infrastructure Engineering teams. Please see the included documentation (docx and pdf formats).
|
||||
|
||||
Compilation is supported with Visual Studio and Visual Studio Express. Use the Visual Studio solution file inside the diskspd_vs2013 directory.
|
||||
|
||||
Source code is hosted at the following repo, if you did not clone it directly:
|
||||
|
||||
[https://github.com/microsoft/diskspd](https://github.com/microsoft/diskspd "https://github.com/microsoft/diskspd")
|
||||
|
||||
A binary release is hosted by Microsoft at the following location:
|
||||
|
||||
[http://aka.ms/diskspd](http://aka.ms/diskspd "http://aka.ms/diskspd")
|
||||
@@ -0,0 +1,848 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// ResultParser.cpp : Defines the entry point for the DLL application.
|
||||
//
|
||||
#include "ResultParser.h"
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <Winternl.h> //ntdll.dll
|
||||
|
||||
#include <Wmistr.h> //WNODE_HEADER
|
||||
#include <Evntrace.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
// TODO: refactor to a single function shared with the XmlResultParser
|
||||
void ResultParser::_Print(const char *format, ...)
|
||||
{
|
||||
assert(nullptr != format);
|
||||
va_list listArg;
|
||||
va_start(listArg, format);
|
||||
char buffer[4096] = {};
|
||||
vsprintf_s(buffer, _countof(buffer), format, listArg);
|
||||
va_end(listArg);
|
||||
_sResult += buffer;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
// display file size in a user-friendly form
|
||||
//
|
||||
|
||||
void ResultParser::_DisplayFileSize(UINT64 fsize)
|
||||
{
|
||||
if( fsize > (UINT64)10*1024*1024*1024 ) // > 10GB
|
||||
{
|
||||
_Print("%uGB", fsize >> 30);
|
||||
}
|
||||
else if( fsize > (UINT64)10*1024*1024 ) // > 10MB
|
||||
{
|
||||
_Print("%uMB", fsize >> 20);
|
||||
}
|
||||
else if( fsize > 10*1024 ) // > 10KB
|
||||
{
|
||||
_Print("%uKB", fsize >> 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
_Print("%I64uB", fsize);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void ResultParser::_DisplayETWSessionInfo(struct ETWSessionInfo sessionInfo)
|
||||
{
|
||||
_Print("\n\n");
|
||||
_Print(" ETW Buffer Settings & Statistics\n");
|
||||
_Print("--------------------------------------------------------\n");
|
||||
_Print("(KB) Buffers (Secs) (Mins)\n");
|
||||
_Print("Size | Min | Max | Free | Written | Flush Age\n");
|
||||
|
||||
_Print("%-5lu %5lu %-5lu %-2lu %8lu %8lu %8d\n\n",
|
||||
sessionInfo.ulBufferSize,
|
||||
sessionInfo.ulMinimumBuffers,
|
||||
sessionInfo.ulMaximumBuffers,
|
||||
sessionInfo.ulFreeBuffers,
|
||||
sessionInfo.ulBuffersWritten,
|
||||
sessionInfo.ulFlushTimer,
|
||||
sessionInfo.lAgeLimit);
|
||||
|
||||
_Print("Allocated Buffers: %lu\n",
|
||||
sessionInfo.ulNumberOfBuffers);
|
||||
|
||||
_Print("LOST EVENTS:%15lu\n",
|
||||
sessionInfo.ulEventsLost);
|
||||
|
||||
_Print("LOST LOG BUFFERS:%10lu\n",
|
||||
sessionInfo.ulLogBuffersLost);
|
||||
|
||||
_Print("LOST REAL TIME BUFFERS:%4lu\n",
|
||||
sessionInfo.ulRealTimeBuffersLost);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
void ResultParser::_DisplayETW(struct ETWMask ETWMask, struct ETWEventCounters EtwEventCounters)
|
||||
{
|
||||
_Print("\n\n\nETW:\n");
|
||||
_Print("----\n\n");
|
||||
|
||||
if (ETWMask.bDiskIO)
|
||||
{
|
||||
_Print("\tDisk I/O\n");
|
||||
|
||||
_Print("\t\tRead: %I64u\n", EtwEventCounters.ullIORead);
|
||||
_Print("\t\tWrite: %I64u\n", EtwEventCounters.ullIOWrite);
|
||||
}
|
||||
if (ETWMask.bImageLoad)
|
||||
{
|
||||
_Print("\tLoad Image\n");
|
||||
|
||||
_Print("\t\tLoad Image: %I64u\n", EtwEventCounters.ullImageLoad);
|
||||
}
|
||||
if (ETWMask.bMemoryPageFaults)
|
||||
{
|
||||
_Print("\tMemory Page Faults\n");
|
||||
|
||||
_Print("\t\tCopy on Write: %I64u\n", EtwEventCounters.ullMMCopyOnWrite);
|
||||
_Print("\t\tDemand Zero fault: %I64u\n", EtwEventCounters.ullMMDemandZeroFault);
|
||||
_Print("\t\tGuard Page fault: %I64u\n", EtwEventCounters.ullMMGuardPageFault);
|
||||
_Print("\t\tHard page fault: %I64u\n", EtwEventCounters.ullMMHardPageFault);
|
||||
_Print("\t\tTransition fault: %I64u\n", EtwEventCounters.ullMMTransitionFault);
|
||||
}
|
||||
if (ETWMask.bMemoryHardFaults && !ETWMask.bMemoryPageFaults )
|
||||
{
|
||||
_Print("\tMemory Hard Faults\n");
|
||||
_Print("\t\tHard page fault: %I64u\n", EtwEventCounters.ullMMHardPageFault);
|
||||
}
|
||||
if (ETWMask.bNetwork)
|
||||
{
|
||||
_Print("\tNetwork\n");
|
||||
|
||||
_Print("\t\tAccept: %I64u\n", EtwEventCounters.ullNetAccept);
|
||||
_Print("\t\tConnect: %I64u\n", EtwEventCounters.ullNetConnect);
|
||||
_Print("\t\tDisconnect: %I64u\n", EtwEventCounters.ullNetDisconnect);
|
||||
_Print("\t\tReconnect: %I64u\n", EtwEventCounters.ullNetReconnect);
|
||||
_Print("\t\tRetransmit: %I64u\n", EtwEventCounters.ullNetRetransmit);
|
||||
_Print("\t\tTCP/IP Send: %I64u\n", EtwEventCounters.ullNetTcpSend);
|
||||
_Print("\t\tTCP/IP Receive: %I64u\n", EtwEventCounters.ullNetTcpReceive);
|
||||
_Print("\t\tUDP/IP Send: %I64u\n", EtwEventCounters.ullNetUdpSend);
|
||||
_Print("\t\tUDP/IP Receive: %I64u\n", EtwEventCounters.ullNetUdpReceive);
|
||||
}
|
||||
if (ETWMask.bProcess)
|
||||
{
|
||||
_Print("\tProcess\n");
|
||||
|
||||
_Print("\t\tStart: %I64u\n", EtwEventCounters.ullProcessStart);
|
||||
_Print("\t\tEnd: %I64u\n", EtwEventCounters.ullProcessEnd);
|
||||
}
|
||||
if (ETWMask.bRegistry)
|
||||
{
|
||||
_Print("\tRegistry\n");
|
||||
|
||||
_Print("\t\tNtCreateKey: %I64u\n",
|
||||
EtwEventCounters.ullRegCreate);
|
||||
|
||||
_Print("\t\tNtDeleteKey: %I64u\n",
|
||||
EtwEventCounters.ullRegDelete);
|
||||
|
||||
_Print("\t\tNtDeleteValueKey: %I64u\n",
|
||||
EtwEventCounters.ullRegDeleteValue);
|
||||
|
||||
_Print("\t\tNtEnumerateKey: %I64u\n",
|
||||
EtwEventCounters.ullRegEnumerateKey);
|
||||
|
||||
_Print("\t\tNtEnumerateValueKey: %I64u\n",
|
||||
EtwEventCounters.ullRegEnumerateValueKey);
|
||||
|
||||
_Print("\t\tNtFlushKey: %I64u\n",
|
||||
EtwEventCounters.ullRegFlush);
|
||||
|
||||
_Print("\t\tKcbDump/create: %I64u\n",
|
||||
EtwEventCounters.ullRegKcbDmp);
|
||||
|
||||
_Print("\t\tNtOpenKey: %I64u\n",
|
||||
EtwEventCounters.ullRegOpen);
|
||||
|
||||
_Print("\t\tNtQueryKey: %I64u\n",
|
||||
EtwEventCounters.ullRegQuery);
|
||||
|
||||
_Print("\t\tNtQueryMultipleValueKey: %I64u\n",
|
||||
EtwEventCounters.ullRegQueryMultipleValue);
|
||||
|
||||
_Print("\t\tNtQueryValueKey: %I64u\n",
|
||||
EtwEventCounters.ullRegQueryValue);
|
||||
|
||||
_Print("\t\tNtSetInformationKey: %I64u\n",
|
||||
EtwEventCounters.ullRegSetInformation);
|
||||
|
||||
_Print("\t\tNtSetValueKey: %I64u\n",
|
||||
EtwEventCounters.ullRegSetValue);
|
||||
}
|
||||
if (ETWMask.bThread)
|
||||
{
|
||||
_Print("\tThread\n");
|
||||
|
||||
_Print("\t\tStart: %I64u\n", EtwEventCounters.ullThreadStart);
|
||||
_Print("\t\tEnd: %I64u\n", EtwEventCounters.ullThreadEnd);
|
||||
}
|
||||
}
|
||||
|
||||
void ResultParser::_PrintTarget(const Target &target, bool fUseThreadsPerFile, bool fCompletionRoutines)
|
||||
{
|
||||
_Print("\tpath: '%s'\n", target.GetPath().c_str());
|
||||
_Print("\t\tthink time: %ums\n", target.GetThinkTime());
|
||||
_Print("\t\tburst size: %u\n", target.GetBurstSize());
|
||||
// TODO: completion routines/ports
|
||||
|
||||
if (target.GetDisableAllCache())
|
||||
{
|
||||
_Print("\t\tsoftware and hardware write cache disabled\n");
|
||||
}
|
||||
else if (target.GetDisableOSCache())
|
||||
{
|
||||
_Print("\t\tsoftware cache disabled\n");
|
||||
}
|
||||
|
||||
if (!target.GetDisableAllCache() && !target.GetDisableOSCache())
|
||||
{
|
||||
_Print("\t\tusing software and hardware write cache\n");
|
||||
}
|
||||
|
||||
if (target.GetZeroWriteBuffers())
|
||||
{
|
||||
_Print("\t\tzeroing write buffers\n");
|
||||
}
|
||||
|
||||
if (target.GetRandomDataWriteBufferSize() > 0)
|
||||
{
|
||||
_Print("\t\twrite buffer size: %I64u\n", target.GetRandomDataWriteBufferSize());
|
||||
string sWriteBufferSourcePath = target.GetRandomDataWriteBufferSourcePath();
|
||||
if (sWriteBufferSourcePath != "")
|
||||
{
|
||||
_Print("\t\twrite buffer source: '%s'\n", sWriteBufferSourcePath.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (target.GetUseParallelAsyncIO())
|
||||
{
|
||||
_Print("\t\tusing parallel async I/O\n");
|
||||
}
|
||||
|
||||
if (target.GetWriteRatio() == 0)
|
||||
{
|
||||
_Print("\t\tperforming read test\n");
|
||||
}
|
||||
else if (target.GetWriteRatio() == 100)
|
||||
{
|
||||
_Print("\t\tperforming write test\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
_Print("\t\tperforming mix test (write/read ratio: %d/100)\n", target.GetWriteRatio());
|
||||
}
|
||||
_Print("\t\tblock size: %d\n", target.GetBlockSizeInBytes());
|
||||
if (target.GetUseRandomAccessPattern())
|
||||
{
|
||||
_Print("\t\tusing random I/O (alignment: ");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target.GetUseInterlockedSequential())
|
||||
{
|
||||
_Print("\t\tusing interlocked sequential I/O (stride: ");
|
||||
}
|
||||
else
|
||||
{
|
||||
_Print("\t\tusing sequential I/O (stride: ");
|
||||
}
|
||||
}
|
||||
_Print("%I64u)\n", target.GetBlockAlignmentInBytes());
|
||||
|
||||
_Print("\t\tnumber of outstanding I/O operations: %d\n", target.GetRequestCount());
|
||||
if (0 != target.GetBaseFileOffsetInBytes())
|
||||
{
|
||||
_Print("\t\tbase file offset: %I64u\n", target.GetBaseFileOffsetInBytes());
|
||||
}
|
||||
|
||||
if (0 != target.GetMaxFileSize())
|
||||
{
|
||||
_Print("\t\tmax file size: %I64u\n", target.GetMaxFileSize());
|
||||
}
|
||||
|
||||
_Print("\t\tthread stride size: %I64u\n", target.GetThreadStrideInBytes());
|
||||
|
||||
if (target.GetSequentialScanHint())
|
||||
{
|
||||
_Print("\t\tusing FILE_FLAG_SEQUENTIAL_SCAN hint\n");
|
||||
}
|
||||
|
||||
if (target.GetRandomAccessHint())
|
||||
{
|
||||
_Print("\t\tusing FILE_FLAG_RANDOM_ACCESS hint\n");
|
||||
}
|
||||
|
||||
if (fUseThreadsPerFile)
|
||||
{
|
||||
_Print("\t\tthreads per file: %d\n", target.GetThreadsPerFile());
|
||||
}
|
||||
if (target.GetRequestCount() > 1 && fUseThreadsPerFile)
|
||||
{
|
||||
if (fCompletionRoutines)
|
||||
{
|
||||
_Print("\t\tusing completion routines (ReadFileEx/WriteFileEx)\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
_Print("\t\tusing I/O Completion Ports\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (target.GetIOPriorityHint() == IoPriorityHintVeryLow)
|
||||
{
|
||||
_Print("\t\tIO priority: very low\n");
|
||||
}
|
||||
else if (target.GetIOPriorityHint() == IoPriorityHintLow)
|
||||
{
|
||||
_Print("\t\tIO priority: low\n");
|
||||
}
|
||||
else if (target.GetIOPriorityHint() == IoPriorityHintNormal)
|
||||
{
|
||||
_Print("\t\tIO priority: normal\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
_Print("\t\tIO priority: unknown\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ResultParser::_PrintTimeSpan(const TimeSpan& timeSpan)
|
||||
{
|
||||
_Print("\tduration: %us\n", timeSpan.GetDuration());
|
||||
_Print("\twarm up time: %us\n", timeSpan.GetWarmup());
|
||||
_Print("\tcool down time: %us\n", timeSpan.GetCooldown());
|
||||
if (timeSpan.GetDisableAffinity())
|
||||
{
|
||||
_Print("\taffinity disabled\n");
|
||||
}
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
_Print("\tmeasuring latency\n");
|
||||
}
|
||||
if (timeSpan.GetCalculateIopsStdDev())
|
||||
{
|
||||
_Print("\tcalculating IOPS stddev with bucket duration = %u milliseconds\n", timeSpan.GetIoBucketDurationInMilliseconds());
|
||||
}
|
||||
_Print("\trandom seed: %u\n", timeSpan.GetRandSeed());
|
||||
|
||||
vector<UINT32> vAffinity = timeSpan.GetAffinityAssignments();
|
||||
if ( vAffinity.size() > 0)
|
||||
{
|
||||
_Print("\tadvanced affinity: ");
|
||||
for (unsigned int x = 0; x < vAffinity.size(); ++x)
|
||||
{
|
||||
_Print("%d", vAffinity[x]);
|
||||
if (x < vAffinity.size() - 1)
|
||||
{
|
||||
_Print(", ");
|
||||
}
|
||||
}
|
||||
_Print("\n");
|
||||
}
|
||||
|
||||
vector<Target> vTargets(timeSpan.GetTargets());
|
||||
for (auto i = vTargets.begin(); i != vTargets.end(); i++)
|
||||
{
|
||||
_PrintTarget(*i, (timeSpan.GetThreadCount() == 0), timeSpan.GetCompletionRoutines());
|
||||
}
|
||||
}
|
||||
|
||||
void ResultParser::_PrintProfile(const Profile& profile)
|
||||
{
|
||||
_Print("\nCommand Line: %s\n", profile.GetCmdLine().c_str());
|
||||
_Print("\n");
|
||||
_Print("Input parameters:\n\n");
|
||||
if (profile.GetVerbose())
|
||||
{
|
||||
_Print("\tusing verbose mode\n");
|
||||
}
|
||||
|
||||
const vector<TimeSpan>& vTimeSpans = profile.GetTimeSpans();
|
||||
int c = 1;
|
||||
for (auto i = vTimeSpans.begin(); i != vTimeSpans.end(); i++)
|
||||
{
|
||||
_Print("\ttimespan: %3d\n", c++);
|
||||
_Print("\t-------------\n");
|
||||
_PrintTimeSpan(*i);
|
||||
_Print("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void ResultParser::_PrintCpuUtilization(const Results& results)
|
||||
{
|
||||
size_t ulProcCount = results.vSystemProcessorPerfInfo.size();
|
||||
double fTime = PerfTimer::PerfTimeToSeconds(results.ullTimeCount);
|
||||
|
||||
char szFloatBuffer[1024];
|
||||
|
||||
_Print("\nCPU | Usage | User | Kernel | Idle\n");
|
||||
_Print("-------------------------------------------\n");
|
||||
|
||||
double busyTime = 0;
|
||||
double totalIdleTime = 0;
|
||||
double totalUserTime = 0;
|
||||
double totalKrnlTime = 0;
|
||||
|
||||
for (unsigned int x = 0; x<ulProcCount; ++x)
|
||||
{
|
||||
double idleTime;
|
||||
double userTime;
|
||||
double krnlTime;
|
||||
double thisTime;
|
||||
|
||||
idleTime = 100.0 * results.vSystemProcessorPerfInfo[x].IdleTime.QuadPart / 10000000 / fTime;
|
||||
krnlTime = 100.0 * results.vSystemProcessorPerfInfo[x].KernelTime.QuadPart / 10000000 / fTime;
|
||||
userTime = 100.0 * results.vSystemProcessorPerfInfo[x].UserTime.QuadPart / 10000000 / fTime;
|
||||
|
||||
thisTime = (krnlTime + userTime) - idleTime;
|
||||
|
||||
sprintf_s(szFloatBuffer, sizeof(szFloatBuffer), "%4u| %6.2lf%%| %6.2lf%%| %6.2lf%%| %6.2lf%%\n",
|
||||
x,
|
||||
thisTime,
|
||||
userTime,
|
||||
krnlTime - idleTime,
|
||||
idleTime);
|
||||
_Print("%s", szFloatBuffer);
|
||||
|
||||
busyTime += thisTime;
|
||||
totalIdleTime += idleTime;
|
||||
totalUserTime += userTime;
|
||||
totalKrnlTime += krnlTime;
|
||||
}
|
||||
_Print("-------------------------------------------\n");
|
||||
|
||||
sprintf_s(szFloatBuffer, sizeof(szFloatBuffer), "avg.| %6.2lf%%| %6.2lf%%| %6.2lf%%| %6.2lf%%\n",
|
||||
busyTime / ulProcCount,
|
||||
totalUserTime / ulProcCount,
|
||||
(totalKrnlTime - totalIdleTime) / ulProcCount,
|
||||
totalIdleTime / ulProcCount);
|
||||
_Print("%s", szFloatBuffer);
|
||||
}
|
||||
|
||||
void ResultParser::_PrintSectionFieldNames(const TimeSpan& timeSpan)
|
||||
{
|
||||
_Print("thread | bytes | I/Os | MB/s | I/O per s %s%s%s| file\n",
|
||||
timeSpan.GetMeasureLatency() ? "| AvgLat " : "",
|
||||
timeSpan.GetCalculateIopsStdDev() ? "| IopsStdDev " : "",
|
||||
timeSpan.GetMeasureLatency() ? "| LatStdDev " : "");
|
||||
}
|
||||
|
||||
void ResultParser::_PrintSectionBorderLine(const TimeSpan& timeSpan)
|
||||
{
|
||||
_Print("------------------------------------------------------------------%s%s%s------------\n",
|
||||
timeSpan.GetMeasureLatency() ? "-----------" : "" ,
|
||||
timeSpan.GetCalculateIopsStdDev() ? "-------------" : "",
|
||||
timeSpan.GetMeasureLatency() ? "------------" : "");
|
||||
}
|
||||
|
||||
void ResultParser::_PrintSection(_SectionEnum section, const TimeSpan& timeSpan, const Results& results)
|
||||
{
|
||||
double fTime = PerfTimer::PerfTimeToSeconds(results.ullTimeCount);
|
||||
double fBucketTime = timeSpan.GetIoBucketDurationInMilliseconds() / 1000.0;
|
||||
UINT64 ullTotalBytesCount = 0;
|
||||
UINT64 ullTotalIOCount = 0;
|
||||
Histogram<float> totalLatencyHistogram;
|
||||
IoBucketizer totalIoBucketizer;
|
||||
|
||||
_PrintSectionFieldNames(timeSpan);
|
||||
|
||||
_PrintSectionBorderLine(timeSpan);
|
||||
|
||||
for (unsigned int iThread = 0; iThread < results.vThreadResults.size(); ++iThread)
|
||||
{
|
||||
const ThreadResults& threadResults = results.vThreadResults[iThread];
|
||||
for (unsigned int iFile = 0; iFile < threadResults.vTargetResults.size(); iFile++)
|
||||
{
|
||||
const TargetResults& targetResults = threadResults.vTargetResults[iFile];
|
||||
|
||||
UINT64 ullBytesCount = 0;
|
||||
UINT64 ullIOCount = 0;
|
||||
|
||||
Histogram<float> latencyHistogram;
|
||||
IoBucketizer ioBucketizer;
|
||||
|
||||
if ((section == _SectionEnum::WRITE) || (section == _SectionEnum::TOTAL))
|
||||
{
|
||||
ullBytesCount += targetResults.ullWriteBytesCount;
|
||||
ullIOCount += targetResults.ullWriteIOCount;
|
||||
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
latencyHistogram.Merge(targetResults.writeLatencyHistogram);
|
||||
totalLatencyHistogram.Merge(targetResults.writeLatencyHistogram);
|
||||
}
|
||||
|
||||
if (timeSpan.GetCalculateIopsStdDev())
|
||||
{
|
||||
ioBucketizer.Merge(targetResults.writeBucketizer);
|
||||
totalIoBucketizer.Merge(targetResults.writeBucketizer);
|
||||
}
|
||||
}
|
||||
|
||||
if ((section == _SectionEnum::READ) || (section == _SectionEnum::TOTAL))
|
||||
{
|
||||
ullBytesCount += targetResults.ullReadBytesCount;
|
||||
ullIOCount += targetResults.ullReadIOCount;
|
||||
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
latencyHistogram.Merge(targetResults.readLatencyHistogram);
|
||||
totalLatencyHistogram.Merge(targetResults.readLatencyHistogram);
|
||||
}
|
||||
|
||||
if (timeSpan.GetCalculateIopsStdDev())
|
||||
{
|
||||
ioBucketizer.Merge(targetResults.readBucketizer);
|
||||
totalIoBucketizer.Merge(targetResults.readBucketizer);
|
||||
}
|
||||
}
|
||||
|
||||
_Print("%6u | %15llu | %12llu | %10.2f | %10.2f",
|
||||
iThread,
|
||||
ullBytesCount,
|
||||
ullIOCount,
|
||||
(double) ullBytesCount / 1024 / 1024 / fTime,
|
||||
(double) ullIOCount / fTime);
|
||||
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
double avgLat = latencyHistogram.GetAvg() / 1000;
|
||||
_Print(" | %8.3f", avgLat);
|
||||
}
|
||||
|
||||
if (timeSpan.GetCalculateIopsStdDev())
|
||||
{
|
||||
double iopsStdDev = ioBucketizer.GetStandardDeviation() / fBucketTime;
|
||||
_Print(" | %10.2f", iopsStdDev);
|
||||
}
|
||||
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
if (latencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
double latStdDev = latencyHistogram.GetStandardDeviation() / 1000;
|
||||
_Print(" | %8.3f", latStdDev);
|
||||
}
|
||||
else
|
||||
{
|
||||
_Print(" | N/A");
|
||||
}
|
||||
}
|
||||
|
||||
_Print(" | %s (", targetResults.sPath.c_str());
|
||||
|
||||
_DisplayFileSize(targetResults.ullFileSize);
|
||||
_Print(")\n");
|
||||
|
||||
ullTotalBytesCount += ullBytesCount;
|
||||
ullTotalIOCount += ullIOCount;
|
||||
}
|
||||
}
|
||||
|
||||
_PrintSectionBorderLine(timeSpan);
|
||||
|
||||
double totalAvgLat = 0;
|
||||
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
totalAvgLat = totalLatencyHistogram.GetAvg() / 1000;
|
||||
}
|
||||
|
||||
_Print("total: %15llu | %12llu | %10.2f | %10.2f",
|
||||
ullTotalBytesCount,
|
||||
ullTotalIOCount,
|
||||
(double) ullTotalBytesCount / 1024 / 1024 / fTime,
|
||||
(double) ullTotalIOCount / fTime);
|
||||
|
||||
|
||||
if (section == _SectionEnum::TOTAL)
|
||||
{
|
||||
_totalScore = (int)(ullTotalBytesCount / 1000 / fTime);
|
||||
}
|
||||
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
_Print(" | %8.3f", totalAvgLat);
|
||||
if (section == _SectionEnum::TOTAL)
|
||||
{
|
||||
_averageLatency = totalAvgLat;
|
||||
}
|
||||
}
|
||||
|
||||
if (timeSpan.GetCalculateIopsStdDev())
|
||||
{
|
||||
double iopsStdDev = totalIoBucketizer.GetStandardDeviation() / fBucketTime;
|
||||
_Print(" | %10.2f", iopsStdDev);
|
||||
}
|
||||
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
if (totalLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
double latStdDev = totalLatencyHistogram.GetStandardDeviation() / 1000;
|
||||
_Print(" | %8.3f", latStdDev);
|
||||
}
|
||||
else
|
||||
{
|
||||
_Print(" | N/A");
|
||||
}
|
||||
}
|
||||
|
||||
_Print("\n");
|
||||
}
|
||||
|
||||
void ResultParser::_PrintLatencyPercentiles(const Results& results)
|
||||
{
|
||||
Histogram<float> readLatencyHistogram;
|
||||
Histogram<float> writeLatencyHistogram;
|
||||
Histogram<float> totalLatencyHistogram;
|
||||
|
||||
for (const auto& thread : results.vThreadResults)
|
||||
{
|
||||
for (const auto& target : thread.vTargetResults)
|
||||
{
|
||||
readLatencyHistogram.Merge(target.readLatencyHistogram);
|
||||
|
||||
writeLatencyHistogram.Merge(target.writeLatencyHistogram);
|
||||
|
||||
totalLatencyHistogram.Merge(target.writeLatencyHistogram);
|
||||
totalLatencyHistogram.Merge(target.readLatencyHistogram);
|
||||
}
|
||||
}
|
||||
|
||||
bool fHasReads = readLatencyHistogram.GetSampleSize() > 0;
|
||||
bool fHasWrites = writeLatencyHistogram.GetSampleSize() > 0;
|
||||
|
||||
_Print(" %%-ile | Read (ms) | Write (ms) | Total (ms)\n");
|
||||
_Print("----------------------------------------------\n");
|
||||
|
||||
string readMin =
|
||||
fHasReads ?
|
||||
Util::DoubleToStringHelper(readLatencyHistogram.GetMin()/1000) :
|
||||
"N/A";
|
||||
|
||||
string writeMin =
|
||||
fHasWrites ?
|
||||
Util::DoubleToStringHelper(writeLatencyHistogram.GetMin() / 1000) :
|
||||
"N/A";
|
||||
|
||||
_Print(" min | %10s | %10s | %10.3lf\n",
|
||||
readMin.c_str(), writeMin.c_str(), totalLatencyHistogram.GetMin()/1000);
|
||||
|
||||
PercentileDescriptor percentiles[] =
|
||||
{
|
||||
{ 0.25, "25th" },
|
||||
{ 0.50, "50th" },
|
||||
{ 0.75, "75th" },
|
||||
{ 0.90, "90th" },
|
||||
{ 0.95, "95th" },
|
||||
{ 0.99, "99th" },
|
||||
{ 0.999, "3-nines" },
|
||||
{ 0.9999, "4-nines" },
|
||||
{ 0.99999, "5-nines" },
|
||||
{ 0.999999, "6-nines" },
|
||||
{ 0.9999999, "7-nines" },
|
||||
{ 0.99999999, "8-nines" },
|
||||
};
|
||||
|
||||
for (auto p : percentiles)
|
||||
{
|
||||
string readPercentile =
|
||||
fHasReads ?
|
||||
Util::DoubleToStringHelper(readLatencyHistogram.GetPercentile(p.Percentile) / 1000) :
|
||||
"N/A";
|
||||
|
||||
string writePercentile =
|
||||
fHasWrites ?
|
||||
Util::DoubleToStringHelper(writeLatencyHistogram.GetPercentile(p.Percentile) / 1000) :
|
||||
"N/A";
|
||||
|
||||
_Print("%7s | %10s | %10s | %10.3lf\n",
|
||||
p.Name.c_str(),
|
||||
readPercentile.c_str(),
|
||||
writePercentile.c_str(),
|
||||
totalLatencyHistogram.GetPercentile(p.Percentile)/1000);
|
||||
}
|
||||
|
||||
string readMax = Util::DoubleToStringHelper(readLatencyHistogram.GetMax() / 1000);
|
||||
string writeMax = Util::DoubleToStringHelper(writeLatencyHistogram.GetMax() / 1000);
|
||||
|
||||
_Print(" max | %10s | %10s | %10.3lf\n",
|
||||
fHasReads ? readMax.c_str() : "N/A",
|
||||
fHasWrites ? writeMax.c_str() : "N/A",
|
||||
totalLatencyHistogram.GetMax()/1000);
|
||||
}
|
||||
|
||||
int ResultParser::GetTotalScore()
|
||||
{
|
||||
return _totalScore;
|
||||
}
|
||||
|
||||
double ResultParser::GetAverageLatency()
|
||||
{
|
||||
return _averageLatency;
|
||||
}
|
||||
|
||||
string ResultParser::ParseResults(Profile& profile, const SystemInformation& system, vector<Results> vResults)
|
||||
{
|
||||
// TODO: print text representation of system information (see xml parser)
|
||||
UNREFERENCED_PARAMETER(system);
|
||||
|
||||
_sResult.clear();
|
||||
|
||||
_PrintProfile(profile);
|
||||
|
||||
for (size_t iResult = 0; iResult < vResults.size(); iResult++)
|
||||
{
|
||||
_Print("\n\nResults for timespan %d:\n", iResult + 1);
|
||||
_Print("*******************************************************************************\n");
|
||||
|
||||
const Results& results = vResults[iResult];
|
||||
const TimeSpan& timeSpan = profile.GetTimeSpans()[iResult];
|
||||
|
||||
size_t ulProcCount = results.vSystemProcessorPerfInfo.size();
|
||||
double fTime = PerfTimer::PerfTimeToSeconds(results.ullTimeCount); //test duration
|
||||
|
||||
char szFloatBuffer[1024];
|
||||
|
||||
// There either is a fixed number of threads for all files to share (GetThreadCount() > 0) or a number of threads per file.
|
||||
// In the latter case vThreadResults.size() == number of threads per file * file count
|
||||
size_t ulThreadCnt = (timeSpan.GetThreadCount() > 0) ? timeSpan.GetThreadCount() : results.vThreadResults.size();
|
||||
|
||||
if (fTime < 0.0000001)
|
||||
{
|
||||
_Print("The test was interrupted before the measurements began. No results are displayed.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: parameters.bCreateFile;
|
||||
|
||||
_Print("\n");
|
||||
sprintf_s(szFloatBuffer, sizeof(szFloatBuffer), "actual test time:\t%.2lfs\n", fTime);
|
||||
_Print("%s", szFloatBuffer);
|
||||
_Print("thread count:\t\t%u\n", ulThreadCnt);
|
||||
|
||||
_Print("proc count:\t\t%u\n", ulProcCount);
|
||||
_PrintCpuUtilization(results);
|
||||
|
||||
_Print("\nTotal IO\n");
|
||||
_PrintSection(_SectionEnum::TOTAL, timeSpan, results);
|
||||
|
||||
_Print("\nRead IO\n");
|
||||
_PrintSection(_SectionEnum::READ, timeSpan, results);
|
||||
|
||||
_Print("\nWrite IO\n");
|
||||
_PrintSection(_SectionEnum::WRITE, timeSpan, results);
|
||||
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
_Print("\n\n");
|
||||
_PrintLatencyPercentiles(results);
|
||||
}
|
||||
|
||||
//etw
|
||||
if (results.fUseETW)
|
||||
{
|
||||
_DisplayETW(results.EtwMask, results.EtwEventCounters);
|
||||
_DisplayETWSessionInfo(results.EtwSessionInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vResults.size() > 1)
|
||||
{
|
||||
_Print("\n\nTotals:\n");
|
||||
_Print("*******************************************************************************\n\n");
|
||||
_Print("type | bytes | I/Os | MB/s | I/O per s\n");
|
||||
_Print("-------------------------------------------------------------------------------\n");
|
||||
|
||||
|
||||
UINT64 cbTotalWritten = 0;
|
||||
UINT64 cbTotalRead = 0;
|
||||
UINT64 cTotalWriteIO = 0;
|
||||
UINT64 cTotalReadIO = 0;
|
||||
UINT64 cTotalTicks = 0;
|
||||
for (auto pResults = vResults.begin(); pResults != vResults.end(); pResults++)
|
||||
{
|
||||
double time = PerfTimer::PerfTimeToSeconds(pResults->ullTimeCount);
|
||||
if (time >= 0.0000001) // skip timespans that were interrupted
|
||||
{
|
||||
cTotalTicks += pResults->ullTimeCount;
|
||||
auto vThreadResults = pResults->vThreadResults;
|
||||
for (auto pThreadResults = vThreadResults.begin(); pThreadResults != vThreadResults.end(); pThreadResults++)
|
||||
{
|
||||
for (auto pTargetResults = pThreadResults->vTargetResults.begin(); pTargetResults != pThreadResults->vTargetResults.end(); pTargetResults++)
|
||||
{
|
||||
cbTotalRead += pTargetResults->ullReadBytesCount;
|
||||
cbTotalWritten += pTargetResults->ullWriteBytesCount;
|
||||
cTotalReadIO += pTargetResults->ullReadIOCount;
|
||||
cTotalWriteIO += pTargetResults->ullWriteIOCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double totalTime = PerfTimer::PerfTimeToSeconds(cTotalTicks);
|
||||
|
||||
_Print("write | %15I64u | %12I64u | %10.2lf | %10.2lf\n",
|
||||
cbTotalWritten,
|
||||
cTotalWriteIO,
|
||||
(double)cbTotalWritten / 1024 / 1024 / totalTime,
|
||||
(double)cTotalWriteIO / totalTime);
|
||||
|
||||
_Print("read | %15I64u | %12I64u | %10.2lf | %10.2lf\n",
|
||||
cbTotalRead,
|
||||
cTotalReadIO,
|
||||
(double)cbTotalRead / 1024 / 1024 / totalTime,
|
||||
(double)cTotalReadIO / totalTime);
|
||||
_Print("-------------------------------------------------------------------------------\n");
|
||||
_Print("total | %15I64u | %12I64u | %10.2lf | %10.2lf\n\n",
|
||||
cbTotalRead + cbTotalWritten,
|
||||
cTotalReadIO + cTotalWriteIO,
|
||||
(double)(cbTotalRead + cbTotalWritten) / 1024 / 1024 / totalTime,
|
||||
(double)(cTotalReadIO + cTotalWriteIO) / totalTime);
|
||||
|
||||
_Print("total test time:\t%.2lfs\n", totalTime);
|
||||
}
|
||||
|
||||
return _sResult;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "Common.h"
|
||||
|
||||
namespace UnitTests
|
||||
{
|
||||
class ResultParserUnitTests;
|
||||
}
|
||||
|
||||
class ResultParser : public IResultParser
|
||||
{
|
||||
public:
|
||||
string ParseResults(Profile& profile, const SystemInformation& system, vector<Results> vResults);
|
||||
int GetTotalScore();
|
||||
double GetAverageLatency();
|
||||
|
||||
private:
|
||||
void _DisplayFileSize(UINT64 fsize);
|
||||
void _DisplayETWSessionInfo(struct ETWSessionInfo sessionInfo);
|
||||
void _DisplayETW(struct ETWMask ETWMask, struct ETWEventCounters EtwEventCounters);
|
||||
void _Print(const char *format, ...);
|
||||
void _PrintProfile(const Profile& profile);
|
||||
void _PrintCpuUtilization(const Results&);
|
||||
enum class _SectionEnum {TOTAL, READ, WRITE};
|
||||
void _PrintSectionFieldNames(const TimeSpan& timeSpan);
|
||||
void _PrintSectionBorderLine(const TimeSpan& timeSpan);
|
||||
void _PrintSection(_SectionEnum, const TimeSpan&, const Results&);
|
||||
void _PrintLatencyPercentiles(const Results&);
|
||||
void _PrintTimeSpan(const TimeSpan &timeSpan);
|
||||
void _PrintTarget(const Target &target, bool fUseThreadsPerFile, bool fCompletionRoutines);
|
||||
|
||||
string _sResult;
|
||||
int _totalScore;
|
||||
double _averageLatency;
|
||||
|
||||
friend class UnitTests::ResultParserUnitTests;
|
||||
};
|
||||
@@ -0,0 +1,885 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "XmlProfileParser.h"
|
||||
#include <Objbase.h>
|
||||
#include <msxml6.h>
|
||||
#include <assert.h>
|
||||
|
||||
// the vc com headers define a partial set of smartptr typedefs, which unfortunately
|
||||
// aren't 1) complete for our use case and 2) vary between revs of the headers.
|
||||
// this define disables the automatic definitions, letting us do them ourselves.
|
||||
#define _COM_NO_STANDARD_GUIDS_
|
||||
#include <comdef.h>
|
||||
|
||||
_COM_SMARTPTR_TYPEDEF(IXMLDOMDocument2, __uuidof(IXMLDOMDocument2));
|
||||
_COM_SMARTPTR_TYPEDEF(IXMLDOMNode, __uuidof(IXMLDOMNodeList));
|
||||
_COM_SMARTPTR_TYPEDEF(IXMLDOMNodeList, __uuidof(IXMLDOMNodeList));
|
||||
|
||||
bool XmlProfileParser::ParseFile(const char *pszPath, Profile *pProfile)
|
||||
{
|
||||
assert(pszPath != nullptr);
|
||||
assert(pProfile != nullptr);
|
||||
|
||||
bool fComInitialized = false;
|
||||
HRESULT hr = CoInitialize(nullptr);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
fComInitialized = true;
|
||||
IXMLDOMDocument2Ptr spXmlDoc;
|
||||
hr = CoCreateInstance(__uuidof(DOMDocument60), nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spXmlDoc));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = spXmlDoc->put_async(VARIANT_FALSE);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
VARIANT_BOOL fvIsOk;
|
||||
_variant_t vPath(pszPath);
|
||||
hr = spXmlDoc->load(vPath, &fvIsOk);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fVerbose;
|
||||
hr = _GetVerbose(spXmlDoc, &fVerbose);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetVerbose(fVerbose);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DWORD dwProgress;
|
||||
hr = _GetProgress(spXmlDoc, &dwProgress);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetProgress(dwProgress);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
string sResultFormat;
|
||||
hr = _GetString(spXmlDoc, "//Profile/ResultFormat", &sResultFormat);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE) && sResultFormat == "xml")
|
||||
{
|
||||
pProfile->SetResultsFormat(ResultsFormat::Xml);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
string sCreateFiles;
|
||||
hr = _GetString(spXmlDoc, "//Profile/PrecreateFiles", &sCreateFiles);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
if (sCreateFiles == "UseMaxSize")
|
||||
{
|
||||
pProfile->SetPrecreateFiles(PrecreateFiles::UseMaxSize);
|
||||
}
|
||||
else if (sCreateFiles == "CreateOnlyFilesWithConstantSizes")
|
||||
{
|
||||
pProfile->SetPrecreateFiles(PrecreateFiles::OnlyFilesWithConstantSizes);
|
||||
}
|
||||
else if (sCreateFiles == "CreateOnlyFilesWithConstantOrZeroSizes")
|
||||
{
|
||||
pProfile->SetPrecreateFiles(PrecreateFiles::OnlyFilesWithConstantOrZeroSizes);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = _ParseEtw(spXmlDoc, pProfile);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = _ParseTimeSpans(spXmlDoc, pProfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fComInitialized)
|
||||
{
|
||||
CoUninitialize();
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_ParseEtw(IXMLDOMDocument2 &XmlDoc, Profile *pProfile)
|
||||
{
|
||||
bool fEtwProcess;
|
||||
HRESULT hr = _GetBool(XmlDoc, "//Profile/ETW/Process", &fEtwProcess);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwProcess(fEtwProcess);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwThread;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/Thread", &fEtwThread);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwThread(fEtwThread);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwImageLoad;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/ImageLoad", &fEtwImageLoad);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwImageLoad(fEtwImageLoad);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwDiskIO;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/DiskIO", &fEtwDiskIO);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwDiskIO(fEtwDiskIO);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwMemoryPageFaults;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/MemoryPageFaults", &fEtwMemoryPageFaults);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwMemoryPageFaults(fEtwMemoryPageFaults);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwMemoryHardFaults;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/MemoryHardFaults", &fEtwMemoryHardFaults);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwMemoryHardFaults(fEtwMemoryHardFaults);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwNetwork;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/Network", &fEtwNetwork);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwNetwork(fEtwNetwork);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwRegistry;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/Registry", &fEtwRegistry);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwRegistry(fEtwRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwUsePagedMemory;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/UsePagedMemory", &fEtwUsePagedMemory);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwUsePagedMemory(fEtwUsePagedMemory);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwUsePerfTimer;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/UsePerfTimer", &fEtwUsePerfTimer);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwUsePerfTimer(fEtwUsePerfTimer);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwUseSystemTimer;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/UseSystemTimer", &fEtwUseSystemTimer);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwUseSystemTimer(fEtwUseSystemTimer);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fEtwUseCyclesCounter;
|
||||
hr = _GetBool(XmlDoc, "//Profile/ETW/UseCyclesCounter", &fEtwUseCyclesCounter);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pProfile->SetEtwEnabled(true);
|
||||
pProfile->SetEtwUseCyclesCounter(fEtwUseCyclesCounter);
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_ParseTimeSpans(IXMLDOMDocument2 &XmlDoc, Profile *pProfile)
|
||||
{
|
||||
IXMLDOMNodeListPtr spNodeList;
|
||||
_variant_t query("//Profile/TimeSpans/TimeSpan");
|
||||
HRESULT hr = XmlDoc.selectNodes(query.bstrVal, &spNodeList);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
long cNodes;
|
||||
hr = spNodeList->get_length(&cNodes);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
for (int i = 0; i < cNodes; i++)
|
||||
{
|
||||
IXMLDOMNodePtr spNode;
|
||||
hr = spNodeList->get_item(i, &spNode);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
TimeSpan timeSpan;
|
||||
hr = _ParseTimeSpan(spNode, &timeSpan);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pProfile->AddTimeSpan(timeSpan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_ParseTimeSpan(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan)
|
||||
{
|
||||
UINT32 ulDuration;
|
||||
HRESULT hr = _GetUINT32(XmlNode, "Duration", &ulDuration);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetDuration(ulDuration);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT32 ulWarmup;
|
||||
hr = _GetUINT32(XmlNode, "Warmup", &ulWarmup);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetWarmup(ulWarmup);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT32 ulCooldown;
|
||||
hr = _GetUINT32(XmlNode, "Cooldown", &ulCooldown);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetCooldown(ulCooldown);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT32 ulRandSeed;
|
||||
hr = _GetUINT32(XmlNode, "RandSeed", &ulRandSeed);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetRandSeed(ulRandSeed);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT32 ulThreadCount;
|
||||
hr = _GetUINT32(XmlNode, "ThreadCount", &ulThreadCount);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetThreadCount(ulThreadCount);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fGroupAffinity;
|
||||
hr = _GetBool(XmlNode, "GroupAffinity", &fGroupAffinity);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetGroupAffinity(fGroupAffinity);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fDisableAffinity;
|
||||
hr = _GetBool(XmlNode, "DisableAffinity", &fDisableAffinity);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetDisableAffinity(fDisableAffinity);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fCompletionRoutines;
|
||||
hr = _GetBool(XmlNode, "CompletionRoutines", &fCompletionRoutines);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetCompletionRoutines(fCompletionRoutines);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fMeasureLatency;
|
||||
hr = _GetBool(XmlNode, "MeasureLatency", &fMeasureLatency);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetMeasureLatency(fMeasureLatency);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fCalculateIopsStdDev;
|
||||
hr = _GetBool(XmlNode, "CalculateIopsStdDev", &fCalculateIopsStdDev);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetCalculateIopsStdDev(fCalculateIopsStdDev);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT32 ulIoBucketDuration;
|
||||
hr = _GetUINT32(XmlNode, "IoBucketDuration", &ulIoBucketDuration);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTimeSpan->SetIoBucketDurationInMilliseconds(ulIoBucketDuration);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = _ParseAffinityAssignment(XmlNode, pTimeSpan);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = _ParseTargets(XmlNode, pTimeSpan);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_ParseTargets(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan)
|
||||
{
|
||||
_variant_t query("Targets/Target");
|
||||
IXMLDOMNodeListPtr spNodeList;
|
||||
HRESULT hr = XmlNode.selectNodes(query.bstrVal, &spNodeList);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
long cNodes;
|
||||
hr = spNodeList->get_length(&cNodes);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
for (int i = 0; i < cNodes; i++)
|
||||
{
|
||||
IXMLDOMNodePtr spNode;
|
||||
hr = spNodeList->get_item(i, &spNode);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
Target target;
|
||||
_ParseTarget(spNode, &target);
|
||||
pTimeSpan->AddTarget(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_ParseRandomDataSource(IXMLDOMNode &XmlNode, Target *pTarget)
|
||||
{
|
||||
IXMLDOMNodeListPtr spNodeList;
|
||||
_variant_t query("RandomDataSource");
|
||||
HRESULT hr = XmlNode.selectNodes(query.bstrVal, &spNodeList);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
long cNodes;
|
||||
hr = spNodeList->get_length(&cNodes);
|
||||
if (SUCCEEDED(hr) && (cNodes == 1))
|
||||
{
|
||||
IXMLDOMNodePtr spNode;
|
||||
hr = spNodeList->get_item(0, &spNode);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT64 cb;
|
||||
hr = _GetUINT64(spNode, "SizeInBytes", &cb);
|
||||
if (SUCCEEDED(hr) && (S_FALSE != hr))
|
||||
{
|
||||
pTarget->SetRandomDataWriteBufferSize(cb);
|
||||
|
||||
string sPath;
|
||||
hr = _GetString(spNode, "FilePath", &sPath);
|
||||
if (SUCCEEDED(hr) && (S_FALSE != hr))
|
||||
{
|
||||
pTarget->SetRandomDataWriteBufferSourcePath(sPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_ParseWriteBufferContent(IXMLDOMNode &XmlNode, Target *pTarget)
|
||||
{
|
||||
IXMLDOMNodeListPtr spNodeList;
|
||||
_variant_t query("WriteBufferContent");
|
||||
HRESULT hr = XmlNode.selectNodes(query.bstrVal, &spNodeList);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
long cNodes;
|
||||
hr = spNodeList->get_length(&cNodes);
|
||||
if (SUCCEEDED(hr) && (cNodes == 1))
|
||||
{
|
||||
IXMLDOMNodePtr spNode;
|
||||
hr = spNodeList->get_item(0, &spNode);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
string sPattern;
|
||||
hr = _GetString(spNode, "Pattern", &sPattern);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
if (sPattern == "sequential")
|
||||
{
|
||||
// that's the default option - do nothing
|
||||
}
|
||||
else if (sPattern == "zero")
|
||||
{
|
||||
pTarget->SetZeroWriteBuffers(true);
|
||||
}
|
||||
else if (sPattern == "random")
|
||||
{
|
||||
hr = _ParseRandomDataSource(spNode, pTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_ParseTarget(IXMLDOMNode &XmlNode, Target *pTarget)
|
||||
{
|
||||
string sPath;
|
||||
HRESULT hr = _GetString(XmlNode, "Path", &sPath);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetPath(sPath);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DWORD dwBlockSize;
|
||||
hr = _GetDWORD(XmlNode, "BlockSize", &dwBlockSize);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetBlockSizeInBytes(dwBlockSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT64 ullStrideSize;
|
||||
hr = _GetUINT64(XmlNode, "StrideSize", &ullStrideSize);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetBlockAlignmentInBytes(ullStrideSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fInterlockedSequential;
|
||||
hr = _GetBool(XmlNode, "InterlockedSequential", &fInterlockedSequential);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetUseInterlockedSequential(fInterlockedSequential);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT64 ullBaseFileOffset;
|
||||
hr = _GetUINT64(XmlNode, "BaseFileOffset", &ullBaseFileOffset);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetBaseFileOffsetInBytes(ullBaseFileOffset);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fSequentialScan;
|
||||
hr = _GetBool(XmlNode, "SequentialScan", &fSequentialScan);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetSequentialScanHint(fSequentialScan);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fRandomAccess;
|
||||
hr = _GetBool(XmlNode, "RandomAccess", &fRandomAccess);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetRandomAccessHint(fRandomAccess);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fUseLargePages;
|
||||
hr = _GetBool(XmlNode, "UseLargePages", &fUseLargePages);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetUseLargePages(fUseLargePages);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DWORD dwRequestCount;
|
||||
hr = _GetDWORD(XmlNode, "RequestCount", &dwRequestCount);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetRequestCount(dwRequestCount);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT64 ullRandom;
|
||||
hr = _GetUINT64(XmlNode, "Random", &ullRandom);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetUseRandomAccessPattern(true);
|
||||
pTarget->SetBlockAlignmentInBytes(ullRandom);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fDisableOSCache;
|
||||
hr = _GetBool(XmlNode, "DisableOSCache", &fDisableOSCache);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetDisableOSCache(fDisableOSCache);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fDisableAllCache;
|
||||
hr = _GetBool(XmlNode, "DisableAllCache", &fDisableAllCache);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetDisableAllCache(fDisableAllCache);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = _ParseWriteBufferContent(XmlNode, pTarget);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DWORD dwBurstSize;
|
||||
hr = _GetDWORD(XmlNode, "BurstSize", &dwBurstSize);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetBurstSize(dwBurstSize);
|
||||
pTarget->SetUseBurstSize(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DWORD dwThinkTime;
|
||||
hr = _GetDWORD(XmlNode, "ThinkTime", &dwThinkTime);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetThinkTime(dwThinkTime);
|
||||
pTarget->SetEnableThinkTime(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DWORD dwThroughput;
|
||||
hr = _GetDWORD(XmlNode, "Throughput", &dwThroughput);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetThroughput(dwThroughput);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DWORD dwThreadsPerFile;
|
||||
hr = _GetDWORD(XmlNode, "ThreadsPerFile", &dwThreadsPerFile);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetThreadsPerFile(dwThreadsPerFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT64 ullFileSize;
|
||||
hr = _GetUINT64(XmlNode, "FileSize", &ullFileSize);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetFileSize(ullFileSize);
|
||||
pTarget->SetCreateFile(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT64 ullMaxFileSize;
|
||||
hr = _GetUINT64(XmlNode, "MaxFileSize", &ullMaxFileSize);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetMaxFileSize(ullMaxFileSize);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT32 ulWriteRatio;
|
||||
hr = _GetUINT32(XmlNode, "WriteRatio", &ulWriteRatio);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetWriteRatio(ulWriteRatio);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bool fParallelAsyncIO;
|
||||
hr = _GetBool(XmlNode, "ParallelAsyncIO", &fParallelAsyncIO);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetUseParallelAsyncIO(fParallelAsyncIO);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT64 ullThreadStride;
|
||||
hr = _GetUINT64(XmlNode, "ThreadStride", &ullThreadStride);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
pTarget->SetThreadStrideInBytes(ullThreadStride);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
UINT32 ulIOPriority;
|
||||
hr = _GetUINT32(XmlNode, "IOPriority", &ulIOPriority);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
PRIORITY_HINT hint[] = { IoPriorityHintVeryLow, IoPriorityHintLow, IoPriorityHintNormal };
|
||||
pTarget->SetIOPriorityHint(hint[ulIOPriority - 1]);
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_ParseAffinityAssignment(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan)
|
||||
{
|
||||
IXMLDOMNodeListPtr spNodeList;
|
||||
_variant_t query("Affinity/AffinityAssignment");
|
||||
HRESULT hr = XmlNode.selectNodes(query.bstrVal, &spNodeList);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
long cNodes;
|
||||
hr = spNodeList->get_length(&cNodes);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
for (int i = 0; i < cNodes; i++)
|
||||
{
|
||||
IXMLDOMNodePtr spNode;
|
||||
hr = spNodeList->get_item(i, &spNode);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
BSTR bstrText;
|
||||
hr = spNode->get_text(&bstrText);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
pTimeSpan->AddAffinityAssignment(_wtoi((wchar_t *)bstrText)); // TODO: change to unsigned
|
||||
SysFreeString(bstrText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_GetUINT32(IXMLDOMNode &XmlNode, const char *pszQuery, UINT32 *pulValue) const
|
||||
{
|
||||
IXMLDOMNodePtr spNode;
|
||||
_variant_t query(pszQuery);
|
||||
HRESULT hr = XmlNode.selectSingleNode(query.bstrVal, &spNode);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
BSTR bstrText;
|
||||
hr = spNode->get_text(&bstrText);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
*pulValue = _wtoi((wchar_t *)bstrText); // TODO: make sure it works on large unsigned ints
|
||||
SysFreeString(bstrText);
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_GetString(IXMLDOMNode &XmlNode, const char *pszQuery, string *psValue) const
|
||||
{
|
||||
IXMLDOMNodePtr spNode;
|
||||
_variant_t query(pszQuery);
|
||||
HRESULT hr = XmlNode.selectSingleNode(query.bstrVal, &spNode);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
BSTR bstrText;
|
||||
hr = spNode->get_text(&bstrText);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// TODO: use wstring?
|
||||
char path[MAX_PATH] = {};
|
||||
WideCharToMultiByte(CP_UTF8, 0 /*dwFlags*/, (wchar_t *)bstrText, static_cast<int>(wcslen((wchar_t *)bstrText)), path, sizeof(path)-1, 0 /*lpDefaultChar*/, 0 /*lpUsedDefaultChar*/);
|
||||
*psValue = string(path);
|
||||
}
|
||||
SysFreeString(bstrText);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_GetUINT64(IXMLDOMNode &XmlNode, const char *pszQuery, UINT64 *pullValue) const
|
||||
{
|
||||
IXMLDOMNodePtr spNode;
|
||||
_variant_t query(pszQuery);
|
||||
HRESULT hr = XmlNode.selectSingleNode(query.bstrVal, &spNode);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
BSTR bstrText;
|
||||
hr = spNode->get_text(&bstrText);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
*pullValue = _wtoi64((wchar_t *)bstrText); // TODO: make sure it works on large unsigned ints
|
||||
}
|
||||
SysFreeString(bstrText);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_GetDWORD(IXMLDOMNode &XmlNode, const char *pszQuery, DWORD *pdwValue) const
|
||||
{
|
||||
UINT32 value = 0;
|
||||
HRESULT hr = _GetUINT32(XmlNode, pszQuery, &value);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
*pdwValue = value;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_GetBool(IXMLDOMNode &XmlNode, const char *pszQuery, bool *pfValue) const
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
IXMLDOMNodePtr spNode;
|
||||
_variant_t query(pszQuery);
|
||||
hr = XmlNode.selectSingleNode(query.bstrVal, &spNode);
|
||||
if (SUCCEEDED(hr) && (hr != S_FALSE))
|
||||
{
|
||||
BSTR bstrText;
|
||||
hr = spNode->get_text(&bstrText);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
*pfValue = (_wcsicmp(L"true", (wchar_t *)bstrText) == 0);
|
||||
SysFreeString(bstrText);
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_GetVerbose(IXMLDOMDocument2 &pXmlDoc, bool *pfVerbose)
|
||||
{
|
||||
return _GetBool(pXmlDoc, "//Profile/Verbose", pfVerbose);
|
||||
}
|
||||
|
||||
HRESULT XmlProfileParser::_GetProgress(IXMLDOMDocument2 &pXmlDoc, DWORD *pdwProgress)
|
||||
{
|
||||
return _GetDWORD(pXmlDoc, "//Profile/Progress", pdwProgress);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <MsXml6.h>
|
||||
#include "Common.h"
|
||||
|
||||
class XmlProfileParser
|
||||
{
|
||||
public:
|
||||
bool ParseFile(const char *pszPath, Profile *pProfile);
|
||||
|
||||
private:
|
||||
HRESULT _ParseEtw(IXMLDOMDocument2 &XmlDoc, Profile *pProfile);
|
||||
HRESULT _ParseTimeSpans(IXMLDOMDocument2 &XmlDoc, Profile *pProfile);
|
||||
HRESULT _ParseTimeSpan(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan);
|
||||
HRESULT _ParseTargets(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan);
|
||||
HRESULT _ParseRandomDataSource(IXMLDOMNode &XmlNode, Target *pTarget);
|
||||
HRESULT _ParseWriteBufferContent(IXMLDOMNode &XmlNode, Target *pTarget);
|
||||
HRESULT _ParseTarget(IXMLDOMNode &XmlNode, Target *pTarget);
|
||||
HRESULT _ParseAffinityAssignment(IXMLDOMNode &XmlNode, TimeSpan *pTimeSpan);
|
||||
|
||||
HRESULT _GetString(IXMLDOMNode &XmlNode, const char *pszQuery, string *psValue) const;
|
||||
HRESULT _GetUINT32(IXMLDOMNode &XmlNode, const char *pszQuery, UINT32 *pulValue) const;
|
||||
HRESULT _GetUINT64(IXMLDOMNode &XmlNode, const char *pszQuery, UINT64 *pullValue) const;
|
||||
HRESULT _GetDWORD(IXMLDOMNode &XmlNode, const char *pszQuery, DWORD *pdwValue) const;
|
||||
HRESULT _GetBool(IXMLDOMNode &XmlNode, const char *pszQuery, bool *pfValue) const;
|
||||
|
||||
HRESULT _GetVerbose(IXMLDOMDocument2 &XmlDoc, bool *pfVerbose);
|
||||
HRESULT _GetProgress(IXMLDOMDocument2 &XmlDoc, DWORD *pdwProgress);
|
||||
};
|
||||
@@ -0,0 +1,273 @@
|
||||
#pragma once
|
||||
|
||||
#using <mscorlib.dll>
|
||||
#using <System.dll>
|
||||
#using <System.Data.dll>
|
||||
#using <System.Xml.dll>
|
||||
|
||||
using namespace System::Security::Permissions;
|
||||
[assembly:SecurityPermissionAttribute(SecurityAction::RequestMinimum, SkipVerification=false)];
|
||||
//
|
||||
// このソース コードは xsd によって自動生成されました。Version=4.0.30319.33440 です。
|
||||
//
|
||||
using namespace System;
|
||||
ref class NewDataSet;
|
||||
|
||||
|
||||
/// <summary>
|
||||
///Represents a strongly typed in-memory cache of data.
|
||||
///</summary>
|
||||
[System::Serializable,
|
||||
System::ComponentModel::DesignerCategoryAttribute(L"code"),
|
||||
System::ComponentModel::ToolboxItem(true),
|
||||
System::Xml::Serialization::XmlSchemaProviderAttribute(L"GetTypedDataSetSchema"),
|
||||
System::Xml::Serialization::XmlRootAttribute(L"NewDataSet"),
|
||||
System::ComponentModel::Design::HelpKeywordAttribute(L"vs.data.DataSet")]
|
||||
public ref class NewDataSet : public ::System::Data::DataSet {
|
||||
|
||||
private: ::System::Data::SchemaSerializationMode _schemaSerializationMode;
|
||||
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
NewDataSet();
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
NewDataSet(::System::Runtime::Serialization::SerializationInfo^ info, ::System::Runtime::Serialization::StreamingContext context);
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute,
|
||||
System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0"),
|
||||
System::ComponentModel::BrowsableAttribute(true),
|
||||
System::ComponentModel::DesignerSerializationVisibilityAttribute(::System::ComponentModel::DesignerSerializationVisibility::Visible)]
|
||||
virtual property ::System::Data::SchemaSerializationMode SchemaSerializationMode {
|
||||
::System::Data::SchemaSerializationMode get() override;
|
||||
System::Void set(::System::Data::SchemaSerializationMode value) override;
|
||||
}
|
||||
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute,
|
||||
System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0"),
|
||||
System::ComponentModel::DesignerSerializationVisibilityAttribute(::System::ComponentModel::DesignerSerializationVisibility::Hidden)]
|
||||
property ::System::Data::DataTableCollection^ Tables {
|
||||
::System::Data::DataTableCollection^ get() new;
|
||||
}
|
||||
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute,
|
||||
System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0"),
|
||||
System::ComponentModel::DesignerSerializationVisibilityAttribute(::System::ComponentModel::DesignerSerializationVisibility::Hidden)]
|
||||
property ::System::Data::DataRelationCollection^ Relations {
|
||||
::System::Data::DataRelationCollection^ get() new;
|
||||
}
|
||||
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Void InitializeDerivedDataSet() override;
|
||||
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Data::DataSet^ Clone() override;
|
||||
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Boolean ShouldSerializeTables() override;
|
||||
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Boolean ShouldSerializeRelations() override;
|
||||
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Void ReadXmlSerializable(::System::Xml::XmlReader^ reader) override;
|
||||
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Xml::Schema::XmlSchema^ GetSchemaSerializable() override;
|
||||
|
||||
internal: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
::System::Void InitVars();
|
||||
|
||||
internal: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
::System::Void InitVars(::System::Boolean initTable);
|
||||
|
||||
private: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
::System::Void InitClass();
|
||||
|
||||
private: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
::System::Void SchemaChanged(::System::Object^ sender, ::System::ComponentModel::CollectionChangeEventArgs^ e);
|
||||
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
static ::System::Xml::Schema::XmlSchemaComplexType^ GetTypedDataSetSchema(::System::Xml::Schema::XmlSchemaSet^ xs);
|
||||
};
|
||||
|
||||
|
||||
inline NewDataSet::NewDataSet() {
|
||||
this->BeginInit();
|
||||
this->InitClass();
|
||||
::System::ComponentModel::CollectionChangeEventHandler^ schemaChangedHandler = gcnew ::System::ComponentModel::CollectionChangeEventHandler(this, &NewDataSet::SchemaChanged);
|
||||
__super::Tables->CollectionChanged += schemaChangedHandler;
|
||||
__super::Relations->CollectionChanged += schemaChangedHandler;
|
||||
this->EndInit();
|
||||
}
|
||||
|
||||
inline NewDataSet::NewDataSet(::System::Runtime::Serialization::SerializationInfo^ info, ::System::Runtime::Serialization::StreamingContext context) :
|
||||
::System::Data::DataSet(info, context, false) {
|
||||
if (this->IsBinarySerialized(info, context) == true) {
|
||||
this->InitVars(false);
|
||||
::System::ComponentModel::CollectionChangeEventHandler^ schemaChangedHandler1 = gcnew ::System::ComponentModel::CollectionChangeEventHandler(this, &NewDataSet::SchemaChanged);
|
||||
this->Tables->CollectionChanged += schemaChangedHandler1;
|
||||
this->Relations->CollectionChanged += schemaChangedHandler1;
|
||||
return;
|
||||
}
|
||||
::System::String^ strSchema = (cli::safe_cast<::System::String^ >(info->GetValue(L"XmlSchema", ::System::String::typeid)));
|
||||
if (this->DetermineSchemaSerializationMode(info, context) == ::System::Data::SchemaSerializationMode::IncludeSchema) {
|
||||
::System::Data::DataSet^ ds = (gcnew ::System::Data::DataSet());
|
||||
ds->ReadXmlSchema((gcnew ::System::Xml::XmlTextReader((gcnew ::System::IO::StringReader(strSchema)))));
|
||||
this->DataSetName = ds->DataSetName;
|
||||
this->Prefix = ds->Prefix;
|
||||
this->Namespace = ds->Namespace;
|
||||
this->Locale = ds->Locale;
|
||||
this->CaseSensitive = ds->CaseSensitive;
|
||||
this->EnforceConstraints = ds->EnforceConstraints;
|
||||
this->Merge(ds, false, ::System::Data::MissingSchemaAction::Add);
|
||||
this->InitVars();
|
||||
}
|
||||
else {
|
||||
this->ReadXmlSchema((gcnew ::System::Xml::XmlTextReader((gcnew ::System::IO::StringReader(strSchema)))));
|
||||
}
|
||||
this->GetSerializationData(info, context);
|
||||
::System::ComponentModel::CollectionChangeEventHandler^ schemaChangedHandler = gcnew ::System::ComponentModel::CollectionChangeEventHandler(this, &NewDataSet::SchemaChanged);
|
||||
__super::Tables->CollectionChanged += schemaChangedHandler;
|
||||
this->Relations->CollectionChanged += schemaChangedHandler;
|
||||
}
|
||||
|
||||
inline ::System::Data::SchemaSerializationMode NewDataSet::SchemaSerializationMode::get() {
|
||||
return this->_schemaSerializationMode;
|
||||
}
|
||||
inline System::Void NewDataSet::SchemaSerializationMode::set(::System::Data::SchemaSerializationMode value) {
|
||||
this->_schemaSerializationMode = __identifier(value);
|
||||
}
|
||||
|
||||
inline ::System::Data::DataTableCollection^ NewDataSet::Tables::get() {
|
||||
return __super::Tables;
|
||||
}
|
||||
|
||||
inline ::System::Data::DataRelationCollection^ NewDataSet::Relations::get() {
|
||||
return __super::Relations;
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::InitializeDerivedDataSet() {
|
||||
this->BeginInit();
|
||||
this->InitClass();
|
||||
this->EndInit();
|
||||
}
|
||||
|
||||
inline ::System::Data::DataSet^ NewDataSet::Clone() {
|
||||
NewDataSet^ cln = (cli::safe_cast<NewDataSet^ >(__super::Clone()));
|
||||
cln->InitVars();
|
||||
cln->SchemaSerializationMode = this->SchemaSerializationMode;
|
||||
return cln;
|
||||
}
|
||||
|
||||
inline ::System::Boolean NewDataSet::ShouldSerializeTables() {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline ::System::Boolean NewDataSet::ShouldSerializeRelations() {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::ReadXmlSerializable(::System::Xml::XmlReader^ reader) {
|
||||
if (this->DetermineSchemaSerializationMode(reader) == ::System::Data::SchemaSerializationMode::IncludeSchema) {
|
||||
this->Reset();
|
||||
::System::Data::DataSet^ ds = (gcnew ::System::Data::DataSet());
|
||||
ds->ReadXml(reader);
|
||||
this->DataSetName = ds->DataSetName;
|
||||
this->Prefix = ds->Prefix;
|
||||
this->Namespace = ds->Namespace;
|
||||
this->Locale = ds->Locale;
|
||||
this->CaseSensitive = ds->CaseSensitive;
|
||||
this->EnforceConstraints = ds->EnforceConstraints;
|
||||
this->Merge(ds, false, ::System::Data::MissingSchemaAction::Add);
|
||||
this->InitVars();
|
||||
}
|
||||
else {
|
||||
this->ReadXml(reader);
|
||||
this->InitVars();
|
||||
}
|
||||
}
|
||||
|
||||
inline ::System::Xml::Schema::XmlSchema^ NewDataSet::GetSchemaSerializable() {
|
||||
::System::IO::MemoryStream^ stream = (gcnew ::System::IO::MemoryStream());
|
||||
this->WriteXmlSchema((gcnew ::System::Xml::XmlTextWriter(stream, nullptr)));
|
||||
stream->Position = 0;
|
||||
return ::System::Xml::Schema::XmlSchema::Read((gcnew ::System::Xml::XmlTextReader(stream)), nullptr);
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::InitVars() {
|
||||
this->InitVars(true);
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::InitVars(::System::Boolean initTable) {
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::InitClass() {
|
||||
this->DataSetName = L"NewDataSet";
|
||||
this->Prefix = L"";
|
||||
this->Namespace = L"http://microsoft.com/diskspd/DiskSpdConfig.xsd";
|
||||
this->Locale = (gcnew ::System::Globalization::CultureInfo(L""));
|
||||
this->EnforceConstraints = true;
|
||||
this->SchemaSerializationMode = ::System::Data::SchemaSerializationMode::IncludeSchema;
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::SchemaChanged(::System::Object^ sender, ::System::ComponentModel::CollectionChangeEventArgs^ e) {
|
||||
if (e->Action == ::System::ComponentModel::CollectionChangeAction::Remove) {
|
||||
this->InitVars();
|
||||
}
|
||||
}
|
||||
|
||||
inline ::System::Xml::Schema::XmlSchemaComplexType^ NewDataSet::GetTypedDataSetSchema(::System::Xml::Schema::XmlSchemaSet^ xs) {
|
||||
NewDataSet^ ds = (gcnew NewDataSet());
|
||||
::System::Xml::Schema::XmlSchemaComplexType^ type = (gcnew ::System::Xml::Schema::XmlSchemaComplexType());
|
||||
::System::Xml::Schema::XmlSchemaSequence^ sequence = (gcnew ::System::Xml::Schema::XmlSchemaSequence());
|
||||
::System::Xml::Schema::XmlSchemaAny^ any = (gcnew ::System::Xml::Schema::XmlSchemaAny());
|
||||
any->Namespace = ds->Namespace;
|
||||
sequence->Items->Add(any);
|
||||
type->Particle = sequence;
|
||||
::System::Xml::Schema::XmlSchema^ dsSchema = ds->GetSchemaSerializable();
|
||||
if (xs->Contains(dsSchema->TargetNamespace)) {
|
||||
::System::IO::MemoryStream^ s1 = (gcnew ::System::IO::MemoryStream());
|
||||
::System::IO::MemoryStream^ s2 = (gcnew ::System::IO::MemoryStream());
|
||||
try {
|
||||
::System::Xml::Schema::XmlSchema^ schema = nullptr;
|
||||
dsSchema->Write(s1);
|
||||
for ( ::System::Collections::IEnumerator^ schemas = xs->Schemas(dsSchema->TargetNamespace)->GetEnumerator(); schemas->MoveNext(); ) {
|
||||
schema = (cli::safe_cast<::System::Xml::Schema::XmlSchema^ >(schemas->Current));
|
||||
s2->SetLength(0);
|
||||
schema->Write(s2);
|
||||
if (s1->Length == s2->Length) {
|
||||
s1->Position = 0;
|
||||
s2->Position = 0;
|
||||
for ( ; ((s1->Position != s1->Length)
|
||||
&& (s1->ReadByte() == s2->ReadByte())); ) {
|
||||
;
|
||||
}
|
||||
if (s1->Position == s1->Length) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (s1 != nullptr) {
|
||||
s1->Close();
|
||||
}
|
||||
if (s2 != nullptr) {
|
||||
s2->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
xs->Add(dsSchema);
|
||||
return type;
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema targetNamespace="http://microsoft.com/diskspd/DiskSpdConfig.xsd"
|
||||
elementFormDefault="qualified"
|
||||
xmlns="http://microsoft.com/diskspd/DiskSpdConfig.xsd"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
>
|
||||
<xs:complexType name="Profile">
|
||||
<xs:all>
|
||||
<xs:element name="TimeSpans" minOccurs="1" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="TimeSpan" minOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Targets" minOccurs="1" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Target" minOccurs="1">
|
||||
<!-- file / disk -->
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<!-- string _sPath -->
|
||||
<xs:element name="Path" type="xs:string" minOccurs="1" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- DWORD dwBlockSize -->
|
||||
<xs:element name="BlockSize" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT64 ullStrideSize -->
|
||||
<xs:element name="StrideSize" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT64 ullBaseFileOffset -->
|
||||
<xs:element name="BaseFileOffset" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- BOOL bSequentialScan (open file with the FILE_FLAG_SEQUENTIAL_SCAN flag) -->
|
||||
<xs:element name="SequentialScan" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- BOOL bRandomAccess (open file with the FILE_FLAG_RANDOM_ACCESS flag) -->
|
||||
<xs:element name="RandomAccess" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- BOOL bUseLargePages (Use large pages for IO buffers) -->
|
||||
<xs:element name="UseLargePages" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- DWORD dwRequestCount -->
|
||||
<!-- -o<count> number of overlapped I/O requests per file per thread
|
||||
(1=synchronous I/O, unless more than 1 thread is specified with -F) [default=2]-->
|
||||
<xs:element name="RequestCount" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT64 ullRandom
|
||||
-r<align>[K|M|G|b] random I/O aligned to <align> bytes (doesn't make sense with -s)
|
||||
<align> can be stated in bytes/KB/MB/GB/blocks [default access=sequential, default alignment=block size] -->
|
||||
<xs:element name="Random" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- BOOL bDisableOSCache -->
|
||||
<xs:element name="DisableOSCache" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- BOOL bDisableAllCache -->
|
||||
<xs:element name="DisableAllCache" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<xs:element name="WriteBufferContent" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
|
||||
<xs:element name="Pattern">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="sequential"></xs:enumeration>
|
||||
<xs:enumeration value="zero"></xs:enumeration>
|
||||
<xs:enumeration value="random"></xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
|
||||
<!-- used only with pattern == random -->
|
||||
<xs:element name="RandomDataSource">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="SizeInBytes" type="xs:unsignedLong" minOccurs="1" maxOccurs="1"></xs:element>
|
||||
<xs:element name="FilePath" type="xs:string" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- DWORD dwBurstSize (number of IOs in a burst) -->
|
||||
<xs:element name="BurstSize" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- DWORD dwThinkTime (time to pause before issuing the next burst of IOs) -->
|
||||
<xs:element name="ThinkTime" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- DWORD dwThroughput (in bytes per millisecond); this can not be specified when using completion routines -->
|
||||
<xs:element name="Throughput" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- DWORD dwThreadsPerFile -->
|
||||
<xs:element name="ThreadsPerFile" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT64 ullFileSize -->
|
||||
<!-- used by the -c (create file) switch-->
|
||||
<xs:element name="FileSize" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT64 ullMaxFileSize -->
|
||||
<xs:element name="MaxFileSize" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT32 ulWriteRatio -->
|
||||
<xs:element name="WriteRatio" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- BOOL bParallelAsyncIO
|
||||
-p start async (overlapped) I/O operations with the same offset (makes sense only with -o2 or grater) -->
|
||||
<xs:element name="ParallelAsyncIO" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT64 ullThreadStride -->
|
||||
<xs:element name="ThreadStride" type="xs:unsignedLong" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- 0 - not set, 1 - very low, 2 - low, 3 - normal -->
|
||||
<xs:element name="IOPriority" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- UINT32 ulDuration -->
|
||||
<xs:element name="Duration" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT32 ulWarmUp -->
|
||||
<xs:element name="Warmup" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT32 ulCoolDown -->
|
||||
<xs:element name="Cooldown" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT32 ulRandSeed
|
||||
-z set random seed [default=0 if parameter not provided, GetTickCount() if value not provided] -->
|
||||
<xs:element name="RandSeed" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- DWORD dwThreadCount
|
||||
-F<count> total number of threads (cannot be used with -t) this cannot be used if per-file thread count is provided -->
|
||||
<xs:element name="ThreadCount" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- BOOL bGroupAffinity -->
|
||||
<xs:element name="GroupAffinity" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- UINT32 *puAffinity -->
|
||||
<xs:element name="Affinity" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="AffinityAssignment" type="xs:unsignedInt" minOccurs="1"></xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- BOOL bDisableAffinity
|
||||
-n disable affinity (cannot be used with -a) -->
|
||||
<xs:element name="DisableAffinity" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- BOOL bCompletionRoutines -->
|
||||
<!-- TODO: this should be decided on a target level -->
|
||||
<xs:element name="CompletionRoutines" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<xs:element name="MeasureLatency" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<xs:element name="CalculateIopsStdDev" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<xs:element name="IoBucketDuration" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- BOOL bVerbose -->
|
||||
<xs:element name="Verbose" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<!-- DWORD dwProgress -->
|
||||
<xs:element name="Progress" type="xs:unsignedInt" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
|
||||
<xs:element name="ResultFormat" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="text"></xs:enumeration>
|
||||
<xs:enumeration value="xml"></xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
|
||||
<!-- ETWMask -->
|
||||
<xs:element name="ETW">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<!-- BOOL bProcess -->
|
||||
<xs:element name="Process" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bThread -->
|
||||
<xs:element name="Thread" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bImageLoad -->
|
||||
<xs:element name="ImageLoad" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bDiskIO -->
|
||||
<xs:element name="DiskIO" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bMemoryPageFaults -->
|
||||
<xs:element name="MemoryPageFaults" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bMemoryHardFaults -->
|
||||
<xs:element name="MemoryHardFaults" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bNetwork -->
|
||||
<xs:element name="Network" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bRegistry -->
|
||||
<xs:element name="Registry" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bUsePagedMemory -->
|
||||
<xs:element name="UsePagedMemory" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bUsePerfTimer -->
|
||||
<xs:element name="UsePerfTimer" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bUseSystemTimer -->
|
||||
<xs:element name="UseSystemTimer" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
<!-- BOOL bUseCyclesCounter -->
|
||||
<xs:element name="UseCyclesCounter" type="xs:boolean" minOccurs="0" maxOccurs="1"></xs:element>
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- files should be created before the first time span -->
|
||||
<xs:element name="PrecreateFiles" minOccurs="0" maxOccurs="1">
|
||||
<xs:simpleType>
|
||||
<xs:restriction base="xs:string">
|
||||
<!-- if the same path exists in multiple time spans, the max size will be used -->
|
||||
<xs:enumeration value="UseMaxSize"></xs:enumeration>
|
||||
<xs:enumeration value="CreateOnlyFilesWithConstantSizes"></xs:enumeration>
|
||||
<xs:enumeration value="CreateOnlyFilesWithConstantOrZeroSizes"></xs:enumeration>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
</xs:element>
|
||||
|
||||
</xs:all>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#include "xmlresultparser.h"
|
||||
|
||||
// TODO: refactor to a single function shared with the ResultParser
|
||||
void XmlResultParser::_Print(const char *format, ...)
|
||||
{
|
||||
assert(nullptr != format);
|
||||
va_list listArg;
|
||||
va_start(listArg, format);
|
||||
char buffer[4096] = {};
|
||||
vsprintf_s(buffer, _countof(buffer), format, listArg);
|
||||
va_end(listArg);
|
||||
_sResult += buffer;
|
||||
}
|
||||
|
||||
|
||||
void XmlResultParser::_PrintTargetResults(const TargetResults& results)
|
||||
{
|
||||
// TODO: results.readBucketizer;
|
||||
// TODO: results.writeBucketizer;
|
||||
|
||||
_Print("<Path>%s</Path>\n", results.sPath.c_str());
|
||||
_Print("<BytesCount>%I64u</BytesCount>\n", results.ullBytesCount);
|
||||
_Print("<FileSize>%I64u</FileSize>\n", results.ullFileSize);
|
||||
_Print("<IOCount>%I64u</IOCount>\n", results.ullIOCount);
|
||||
_Print("<ReadBytes>%I64u</ReadBytes>\n", results.ullReadBytesCount);
|
||||
_Print("<ReadCount>%I64u</ReadCount>\n", results.ullReadIOCount);
|
||||
_Print("<WriteBytes>%I64u</WriteBytes>\n", results.ullWriteBytesCount);
|
||||
_Print("<WriteCount>%I64u</WriteCount>\n", results.ullWriteIOCount);
|
||||
}
|
||||
|
||||
void XmlResultParser::_PrintTargetLatency(const TargetResults& results)
|
||||
{
|
||||
if (results.readLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<AverageReadLatencyMilliseconds>%.3f</AverageReadLatencyMilliseconds>\n", results.readLatencyHistogram.GetAvg() / 1000);
|
||||
_Print("<ReadLatencyStdev>%.3f</ReadLatencyStdev>\n", results.readLatencyHistogram.GetStandardDeviation() / 1000);
|
||||
}
|
||||
if (results.writeLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<AverageWriteLatencyMilliseconds>%.3f</AverageWriteLatencyMilliseconds>\n", results.writeLatencyHistogram.GetAvg() / 1000);
|
||||
_Print("<WriteLatencyStdev>%.3f</WriteLatencyStdev>\n", results.writeLatencyHistogram.GetStandardDeviation() / 1000);
|
||||
}
|
||||
Histogram<float> totalLatencyHistogram;
|
||||
totalLatencyHistogram.Merge(results.readLatencyHistogram);
|
||||
totalLatencyHistogram.Merge(results.writeLatencyHistogram);
|
||||
if (totalLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<AverageLatencyMilliseconds>%.3f</AverageLatencyMilliseconds>\n", totalLatencyHistogram.GetAvg() / 1000);
|
||||
_Print("<LatencyStdev>%.3f</LatencyStdev>\n", totalLatencyHistogram.GetStandardDeviation() / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
void XmlResultParser::_PrintTargetIops(const IoBucketizer& readBucketizer, const IoBucketizer& writeBucketizer, UINT32 bucketTimeInMs)
|
||||
{
|
||||
_Print("<Iops>\n");
|
||||
|
||||
IoBucketizer totalIoBucketizer;
|
||||
totalIoBucketizer.Merge(readBucketizer);
|
||||
totalIoBucketizer.Merge(writeBucketizer);
|
||||
|
||||
if (readBucketizer.GetNumberOfValidBuckets() > 0)
|
||||
{
|
||||
_Print("<ReadIopsStdDev>%.3f</ReadIopsStdDev>\n", readBucketizer.GetStandardDeviation() / (bucketTimeInMs / 1000.0));
|
||||
}
|
||||
if (writeBucketizer.GetNumberOfValidBuckets() > 0)
|
||||
{
|
||||
_Print("<WriteIopsStdDev>%.3f</WriteIopsStdDev>\n", writeBucketizer.GetStandardDeviation() / (bucketTimeInMs / 1000.0));
|
||||
}
|
||||
if (totalIoBucketizer.GetNumberOfValidBuckets() > 0)
|
||||
{
|
||||
_Print("<IopsStdDev>%.3f</IopsStdDev>\n", totalIoBucketizer.GetStandardDeviation() / (bucketTimeInMs / 1000.0));
|
||||
}
|
||||
_PrintIops(readBucketizer, writeBucketizer, bucketTimeInMs);
|
||||
_Print("</Iops>\n");
|
||||
}
|
||||
|
||||
void XmlResultParser::_PrintETWSessionInfo(struct ETWSessionInfo sessionInfo)
|
||||
{
|
||||
_Print("<ETWSessionInfo>\n");
|
||||
_Print("<BufferSizeKB>%lu</BufferSizeKB>\n", sessionInfo.ulBufferSize);
|
||||
_Print("<MinimimBuffers>%lu</MinimimBuffers>\n", sessionInfo.ulMinimumBuffers);
|
||||
_Print("<MaximumBuffers>%lu</MaximumBuffers>\n", sessionInfo.ulMaximumBuffers);
|
||||
_Print("<FreeBuffers>%lu</FreeBuffers>", sessionInfo.ulFreeBuffers);
|
||||
_Print("<BuffersWritten>%lu</BuffersWritten>\n", sessionInfo.ulBuffersWritten);
|
||||
_Print("<FlushTimerSeconds>%lu</FlushTimerSeconds>\n", sessionInfo.ulFlushTimer);
|
||||
_Print("<AgeLimitMinues>%d</AgeLimitMinues>\n", sessionInfo.lAgeLimit);
|
||||
|
||||
_Print("<AllocatedBuffers>%lu</AllocatedBuffers>\n", sessionInfo.ulNumberOfBuffers);
|
||||
_Print("<LostEvents>%15lu</LostEvents>\n", sessionInfo.ulEventsLost);
|
||||
_Print("<LostLogBuffers>%10lu</LostLogBuffers>\n", sessionInfo.ulLogBuffersLost);
|
||||
_Print("<LostRealTimeBuffers>%4lu</LostRealTimeBuffers>\n", sessionInfo.ulRealTimeBuffersLost);
|
||||
_Print("</ETWSessionInfo>\n");
|
||||
}
|
||||
|
||||
void XmlResultParser::_PrintETW(struct ETWMask ETWMask, struct ETWEventCounters EtwEventCounters)
|
||||
{
|
||||
_Print("<ETW>\n");
|
||||
if (ETWMask.bDiskIO)
|
||||
{
|
||||
_Print("<DiskIO>\n");
|
||||
_Print("<Read>%I64u</Read>\n", EtwEventCounters.ullIORead);
|
||||
_Print("<Write>%I64u</Write>\n", EtwEventCounters.ullIOWrite);
|
||||
_Print("</DiskIO>\n");
|
||||
}
|
||||
if (ETWMask.bImageLoad)
|
||||
{
|
||||
_Print("<LoadImage>%I64u</LoadImage>\n", EtwEventCounters.ullImageLoad);
|
||||
}
|
||||
if (ETWMask.bMemoryPageFaults)
|
||||
{
|
||||
_Print("<MemoryPageFaults>\n");
|
||||
_Print("<CopyOnWrite>%I64u</CopyOnWrite>\n", EtwEventCounters.ullMMCopyOnWrite);
|
||||
_Print("<DemandZeroFault>%I64u</DemandZeroFault>\n", EtwEventCounters.ullMMDemandZeroFault);
|
||||
_Print("<GuardPageFault>%I64u</GuardPageFault>\n", EtwEventCounters.ullMMGuardPageFault);
|
||||
_Print("<HardPageFault>%I64u</HardPageFault>\n", EtwEventCounters.ullMMHardPageFault);
|
||||
_Print("<TransitionFault>%I64u</TransitionFault>\n", EtwEventCounters.ullMMTransitionFault);
|
||||
_Print("</MemoryPageFaults>\n");
|
||||
}
|
||||
if (ETWMask.bMemoryHardFaults && !ETWMask.bMemoryPageFaults)
|
||||
{
|
||||
_Print("<HardPageFault>%I64u</HardPageFault>\n", EtwEventCounters.ullMMHardPageFault);
|
||||
}
|
||||
if (ETWMask.bNetwork)
|
||||
{
|
||||
_Print("<Network>\n");
|
||||
_Print("<Accept>%I64u</Accept>\n", EtwEventCounters.ullNetAccept);
|
||||
_Print("<Connect>%I64u</Connect>\n", EtwEventCounters.ullNetConnect);
|
||||
_Print("<Disconnect>%I64u</Disconnect>\n", EtwEventCounters.ullNetDisconnect);
|
||||
_Print("<Reconnect>%I64u</Reconnect>\n", EtwEventCounters.ullNetReconnect);
|
||||
_Print("<Retransmit>%I64u</Retransmit>\n", EtwEventCounters.ullNetRetransmit);
|
||||
_Print("<TCPIPSend>%I64u</TCPIPSend>\n", EtwEventCounters.ullNetTcpSend);
|
||||
_Print("<TCPIPReceive>%I64u</TCPIPReceive>\n", EtwEventCounters.ullNetTcpReceive);
|
||||
_Print("<UDPIPSend>%I64u</UDPIPSend>\n", EtwEventCounters.ullNetUdpSend);
|
||||
_Print("<UDPIPReceive>%I64u</UDPIPReceive>\n", EtwEventCounters.ullNetUdpReceive);
|
||||
_Print("</Network>\n");
|
||||
}
|
||||
if (ETWMask.bProcess)
|
||||
{
|
||||
_Print("<Process>\n");
|
||||
_Print("<Start>%I64u</Start>\n", EtwEventCounters.ullProcessStart);
|
||||
_Print("<End>%I64u</End>\n", EtwEventCounters.ullProcessEnd);
|
||||
_Print("</Process>\n");
|
||||
}
|
||||
if (ETWMask.bRegistry)
|
||||
{
|
||||
_Print("<Registry>\n");
|
||||
_Print("<NtCreateKey>%I64u</NtCreateKey>\n", EtwEventCounters.ullRegCreate);
|
||||
_Print("<NtDeleteKey>%I64u</NtDeleteKey>\n", EtwEventCounters.ullRegDelete);
|
||||
_Print("<NtDeleteValueKey>%I64u</NtDeleteValueKey>\n", EtwEventCounters.ullRegDeleteValue);
|
||||
_Print("<NtEnumerateKey>%I64u</NtEnumerateKey>\n", EtwEventCounters.ullRegEnumerateKey);
|
||||
_Print("<NtEnumerateValueKey>%I64u</NtEnumerateValueKey>\n", EtwEventCounters.ullRegEnumerateValueKey);
|
||||
_Print("<NtFlushKey>%I64u</NtFlushKey>\n", EtwEventCounters.ullRegFlush);
|
||||
_Print("<KcbDump>%I64u</KcbDump>\n", EtwEventCounters.ullRegKcbDmp);
|
||||
_Print("<NtOpenKey>%I64u</NtOpenKey>\n", EtwEventCounters.ullRegOpen);
|
||||
_Print("<NtQueryKey>%I64u</NtQueryKey>\n", EtwEventCounters.ullRegQuery);
|
||||
_Print("<NtQueryMultipleValueKey>%I64u</NtQueryMultipleValueKey>\n", EtwEventCounters.ullRegQueryMultipleValue);
|
||||
_Print("<NtQueryValueKey>%I64u</NtQueryValueKey>\n", EtwEventCounters.ullRegQueryValue);
|
||||
_Print("<NtSetInformationKey>%I64u</NtSetInformationKey>\n", EtwEventCounters.ullRegSetInformation);
|
||||
_Print("<NtSetValueKey>%I64u</NtSetValueKey>\n", EtwEventCounters.ullRegSetValue);
|
||||
_Print("</Registry>\n");
|
||||
}
|
||||
if (ETWMask.bThread)
|
||||
{
|
||||
_Print("<Thread>\n");
|
||||
_Print("<Start>%I64u</Start>\n", EtwEventCounters.ullThreadStart);
|
||||
_Print("<End>%I64u</End>\n", EtwEventCounters.ullThreadEnd);
|
||||
_Print("</Thread>\n");
|
||||
}
|
||||
_Print("</ETW>\n");
|
||||
}
|
||||
|
||||
void XmlResultParser::_PrintCpuUtilization(const Results& results)
|
||||
{
|
||||
size_t ulProcCount = results.vSystemProcessorPerfInfo.size();
|
||||
double fTime = PerfTimer::PerfTimeToSeconds(results.ullTimeCount);
|
||||
|
||||
_Print("<CpuUtilization>\n");
|
||||
|
||||
double busyTime = 0;
|
||||
double totalIdleTime = 0;
|
||||
double totalUserTime = 0;
|
||||
double totalKrnlTime = 0;
|
||||
|
||||
for (unsigned int x = 0; x<ulProcCount; ++x)
|
||||
{
|
||||
double idleTime;
|
||||
double userTime;
|
||||
double krnlTime;
|
||||
double thisTime;
|
||||
|
||||
idleTime = 100.0 * results.vSystemProcessorPerfInfo[x].IdleTime.QuadPart / 10000000 / fTime;
|
||||
krnlTime = 100.0 * results.vSystemProcessorPerfInfo[x].KernelTime.QuadPart / 10000000 / fTime;
|
||||
userTime = 100.0 * results.vSystemProcessorPerfInfo[x].UserTime.QuadPart / 10000000 / fTime;
|
||||
|
||||
thisTime = (krnlTime + userTime) - idleTime;
|
||||
|
||||
_Print("<CPU>\n");
|
||||
_Print("<Id>%d</Id>\n", x);
|
||||
_Print("<UsagePercent>%.2f</UsagePercent>\n", thisTime);
|
||||
_Print("<UserPercent>%.2f</UserPercent>\n", userTime);
|
||||
_Print("<KernelPercent>%.2f</KernelPercent>\n", krnlTime - idleTime);
|
||||
_Print("<IdlePercent>%.2f</IdlePercent>\n", idleTime);
|
||||
_Print("</CPU>\n");
|
||||
|
||||
busyTime += thisTime;
|
||||
totalIdleTime += idleTime;
|
||||
totalUserTime += userTime;
|
||||
totalKrnlTime += krnlTime;
|
||||
}
|
||||
_Print("<Average>\n");
|
||||
_Print("<UsagePercent>%.2f</UsagePercent>\n", busyTime / ulProcCount);
|
||||
_Print("<UserPercent>%.2f</UserPercent>\n", totalUserTime / ulProcCount);
|
||||
_Print("<KernelPercent>%.2f</KernelPercent>\n", (totalKrnlTime - totalIdleTime) / ulProcCount);
|
||||
_Print("<IdlePercent>%.2f</IdlePercent>\n", totalIdleTime / ulProcCount);
|
||||
_Print("</Average>\n");
|
||||
|
||||
_Print("</CpuUtilization>\n");
|
||||
}
|
||||
|
||||
// emit the iops time series (this obviates needing perfmon counters, in common cases, and provides file level data)
|
||||
void XmlResultParser::_PrintIops(const IoBucketizer& readBucketizer, const IoBucketizer& writeBucketizer, UINT32 bucketTimeInMs)
|
||||
{
|
||||
bool done = false;
|
||||
for (size_t i = 0; !done; i++)
|
||||
{
|
||||
done = true;
|
||||
|
||||
double r = 0.0;
|
||||
double w = 0.0;
|
||||
|
||||
if (readBucketizer.GetNumberOfValidBuckets() > i)
|
||||
{
|
||||
r = readBucketizer.GetIoBucket(i) / (bucketTimeInMs / 1000.0);
|
||||
done = false;
|
||||
}
|
||||
if (writeBucketizer.GetNumberOfValidBuckets() > i)
|
||||
{
|
||||
w = writeBucketizer.GetIoBucket(i) / (bucketTimeInMs / 1000.0);
|
||||
done = false;
|
||||
}
|
||||
if (!done)
|
||||
{
|
||||
_Print("<Bucket SampleMillisecond=\"%lu\" Read=\"%.0f\" Write=\"%.0f\" Total=\"%.0f\"/>\n", bucketTimeInMs*(i + 1), r, w, r + w);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void XmlResultParser::_PrintOverallIops(const Results& results, UINT32 bucketTimeInMs)
|
||||
{
|
||||
IoBucketizer readBucketizer;
|
||||
IoBucketizer writeBucketizer;
|
||||
|
||||
for (const auto& thread : results.vThreadResults)
|
||||
{
|
||||
for (const auto& target : thread.vTargetResults)
|
||||
{
|
||||
readBucketizer.Merge(target.readBucketizer);
|
||||
writeBucketizer.Merge(target.writeBucketizer);
|
||||
}
|
||||
}
|
||||
|
||||
_PrintTargetIops(readBucketizer, writeBucketizer, bucketTimeInMs);
|
||||
}
|
||||
|
||||
void XmlResultParser::_PrintLatencyPercentiles(const Results& results)
|
||||
{
|
||||
Histogram<float> readLatencyHistogram;
|
||||
Histogram<float> writeLatencyHistogram;
|
||||
Histogram<float> totalLatencyHistogram;
|
||||
|
||||
for (const auto& thread : results.vThreadResults)
|
||||
{
|
||||
for (const auto& target : thread.vTargetResults)
|
||||
{
|
||||
readLatencyHistogram.Merge(target.readLatencyHistogram);
|
||||
|
||||
writeLatencyHistogram.Merge(target.writeLatencyHistogram);
|
||||
|
||||
totalLatencyHistogram.Merge(target.writeLatencyHistogram);
|
||||
totalLatencyHistogram.Merge(target.readLatencyHistogram);
|
||||
}
|
||||
}
|
||||
|
||||
_Print("<Latency>\n");
|
||||
if (readLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<AverageReadMilliseconds>%.3f</AverageReadMilliseconds>\n", readLatencyHistogram.GetAvg() / 1000);
|
||||
_Print("<ReadLatencyStdev>%.3f</ReadLatencyStdev>\n", readLatencyHistogram.GetStandardDeviation() / 1000);
|
||||
}
|
||||
if (writeLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<AverageWriteMilliseconds>%.3f</AverageWriteMilliseconds>\n", writeLatencyHistogram.GetAvg() / 1000);
|
||||
_Print("<WriteLatencyStdev>%.3f</WriteLatencyStdev>\n", writeLatencyHistogram.GetStandardDeviation() / 1000);
|
||||
}
|
||||
if (totalLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<AverageTotalMilliseconds>%.3f</AverageTotalMilliseconds>\n", totalLatencyHistogram.GetAvg() / 1000);
|
||||
_Print("<LatencyStdev>%.3f</LatencyStdev>\n", totalLatencyHistogram.GetStandardDeviation() / 1000);
|
||||
}
|
||||
|
||||
_Print("<Bucket>\n");
|
||||
_Print("<Percentile>0</Percentile>\n");
|
||||
if (readLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<ReadMilliseconds>%.3f</ReadMilliseconds>\n", readLatencyHistogram.GetMin() / 1000);
|
||||
}
|
||||
if (writeLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<WriteMilliseconds>%.3f</WriteMilliseconds>\n", writeLatencyHistogram.GetMin() / 1000);
|
||||
}
|
||||
if (totalLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<TotalMilliseconds>%.3f</TotalMilliseconds>\n", totalLatencyHistogram.GetMin() / 1000);
|
||||
}
|
||||
_Print("</Bucket>\n");
|
||||
|
||||
// Construct vector of percentiles and decimal precision to squelch trailing zeroes. This is more
|
||||
// detailed than summary text output, and does not contain the decorated names (15th, etc.)
|
||||
|
||||
vector<pair<int, double>> vPercentiles;
|
||||
for (int p = 1; p <= 99; p++)
|
||||
{
|
||||
vPercentiles.push_back(make_pair(0, p));
|
||||
}
|
||||
|
||||
vPercentiles.push_back(make_pair(1, 99.9));
|
||||
vPercentiles.push_back(make_pair(2, 99.99));
|
||||
vPercentiles.push_back(make_pair(3, 99.999));
|
||||
vPercentiles.push_back(make_pair(4, 99.9999));
|
||||
vPercentiles.push_back(make_pair(5, 99.99999));
|
||||
vPercentiles.push_back(make_pair(6, 99.999999));
|
||||
|
||||
for (auto p : vPercentiles)
|
||||
{
|
||||
_Print("<Bucket>\n");
|
||||
_Print("<Percentile>%.*f</Percentile>\n", p.first, p.second);
|
||||
if (readLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<ReadMilliseconds>%.3f</ReadMilliseconds>\n", readLatencyHistogram.GetPercentile(p.second / 100) / 1000);
|
||||
}
|
||||
if (writeLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<WriteMilliseconds>%.3f</WriteMilliseconds>\n", writeLatencyHistogram.GetPercentile(p.second / 100) / 1000);
|
||||
}
|
||||
if (totalLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<TotalMilliseconds>%.3f</TotalMilliseconds>\n", totalLatencyHistogram.GetPercentile(p.second / 100) / 1000);
|
||||
}
|
||||
_Print("</Bucket>\n");
|
||||
}
|
||||
|
||||
_Print("<Bucket>\n");
|
||||
_Print("<Percentile>100</Percentile>\n");
|
||||
if (readLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<ReadMilliseconds>%.3f</ReadMilliseconds>\n", readLatencyHistogram.GetMax() / 1000);
|
||||
}
|
||||
if (writeLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<WriteMilliseconds>%.3f</WriteMilliseconds>\n", writeLatencyHistogram.GetMax() / 1000);
|
||||
}
|
||||
if (totalLatencyHistogram.GetSampleSize() > 0)
|
||||
{
|
||||
_Print("<TotalMilliseconds>%.3f</TotalMilliseconds>\n", totalLatencyHistogram.GetMax() / 1000);
|
||||
}
|
||||
_Print("</Bucket>\n");
|
||||
_Print("</Latency>\n");
|
||||
}
|
||||
|
||||
int XmlResultParser::GetTotalScore()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
double XmlResultParser::GetAverageLatency()
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
string XmlResultParser::ParseResults(Profile& profile, const SystemInformation& system, vector<Results> vResults)
|
||||
{
|
||||
_sResult.clear();
|
||||
|
||||
_Print("<Results>\n");
|
||||
_sResult += system.GetXml();
|
||||
_sResult += profile.GetXml();
|
||||
for (size_t iResults = 0; iResults < vResults.size(); iResults++)
|
||||
{
|
||||
const Results& results = vResults[iResults];
|
||||
const TimeSpan& timeSpan = profile.GetTimeSpans()[iResults];
|
||||
|
||||
_Print("<TimeSpan>\n");
|
||||
double fTime = PerfTimer::PerfTimeToSeconds(results.ullTimeCount); //test duration
|
||||
if (fTime >= 0.0000001)
|
||||
{
|
||||
// There either is a fixed number of threads for all files to share (GetThreadCount() > 0) or a number of threads per file.
|
||||
// In the latter case vThreadResults.size() == number of threads per file * file count
|
||||
size_t ulThreadCnt = (timeSpan.GetThreadCount() > 0) ? timeSpan.GetThreadCount() : results.vThreadResults.size();
|
||||
size_t ulProcCount = results.vSystemProcessorPerfInfo.size();
|
||||
|
||||
_Print("<TestTimeSeconds>%.2f</TestTimeSeconds>\n", fTime);
|
||||
_Print("<ThreadCount>%u</ThreadCount>\n", ulThreadCnt);
|
||||
_Print("<ProcCount>%u</ProcCount>\n", ulProcCount);
|
||||
|
||||
_PrintCpuUtilization(results);
|
||||
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
_PrintLatencyPercentiles(results);
|
||||
}
|
||||
|
||||
if (timeSpan.GetCalculateIopsStdDev())
|
||||
{
|
||||
_PrintOverallIops(results, timeSpan.GetIoBucketDurationInMilliseconds());
|
||||
}
|
||||
|
||||
if (results.fUseETW)
|
||||
{
|
||||
_PrintETW(results.EtwMask, results.EtwEventCounters);
|
||||
_PrintETWSessionInfo(results.EtwSessionInfo);
|
||||
}
|
||||
|
||||
for (size_t iThread = 0; iThread < results.vThreadResults.size(); iThread++)
|
||||
{
|
||||
const ThreadResults& threadResults = results.vThreadResults[iThread];
|
||||
_Print("<Thread>\n");
|
||||
_Print("<Id>%u</Id>\n", iThread);
|
||||
for (const auto& targetResults : threadResults.vTargetResults)
|
||||
{
|
||||
_Print("<Target>\n");
|
||||
_PrintTargetResults(targetResults);
|
||||
if (timeSpan.GetMeasureLatency())
|
||||
{
|
||||
_PrintTargetLatency(targetResults);
|
||||
}
|
||||
if (timeSpan.GetCalculateIopsStdDev())
|
||||
{
|
||||
_PrintTargetIops(targetResults.readBucketizer, targetResults.writeBucketizer, timeSpan.GetIoBucketDurationInMilliseconds());
|
||||
}
|
||||
_Print("</Target>\n");
|
||||
}
|
||||
_Print("</Thread>\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_Print("<Error>The test was interrupted before the measurements began. No results are displayed.</Error>\n");
|
||||
}
|
||||
_Print("</TimeSpan>\n");
|
||||
}
|
||||
_Print("</Results>");
|
||||
return _sResult;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
DISKSPD
|
||||
|
||||
Copyright(c) Microsoft Corporation
|
||||
All rights reserved.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "Common.h"
|
||||
|
||||
class XmlResultParser: public IResultParser
|
||||
{
|
||||
public:
|
||||
string ParseResults(Profile& profile, const SystemInformation& system, vector<Results> vResults);
|
||||
int GetTotalScore();
|
||||
double GetAverageLatency();
|
||||
|
||||
private:
|
||||
void _PrintCpuUtilization(const Results& results);
|
||||
void _PrintETW(struct ETWMask ETWMask, struct ETWEventCounters EtwEventCounters);
|
||||
void _PrintETWSessionInfo(struct ETWSessionInfo sessionInfo);
|
||||
void _PrintLatencyPercentiles(const Results& results);
|
||||
void _PrintTargetResults(const TargetResults& results);
|
||||
void _PrintTargetLatency(const TargetResults& results);
|
||||
void _PrintTargetIops(const IoBucketizer& readBucketizer, const IoBucketizer& writeBucketizer, UINT32 bucketTimeInMs);
|
||||
void _PrintOverallIops(const Results& results, UINT32 bucketTimeInMs);
|
||||
void _PrintIops(const IoBucketizer& readBucketizer, const IoBucketizer& writeBucketizer, UINT32 bucketTimeInMs);
|
||||
void _Print(const char *format, ...);
|
||||
|
||||
string _sResult;
|
||||
};
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{0EF5CE78-8E92-4A1B-A255-0F544AADA291}</ProjectGuid>
|
||||
<RootNamespace>CmdLineParser</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\CmdLineParser\CmdLineParser.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\CmdLineParser\CmdLineParser.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D238F8AA-DE12-49E7-B4A7-9B69579A69C0}</ProjectGuid>
|
||||
<RootNamespace>CmdRequestCreator</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
<TargetName>diskspd</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
<TargetName>diskspd</TargetName>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
<TargetName>diskspd32</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
<TargetName>diskspd64</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(SolutionDir)$(Configuration)\xmlprofileparser.lib;$(SolutionDir)$(Configuration)\iorequestgenerator.lib;$(SolutionDir)$(Configuration)\resultparser.lib;$(SolutionDir)$(Configuration)\xmlresultparser.lib;$(SolutionDir)$(Configuration)\common.lib;msxml6.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(SolutionDir)$(Platform)\$(Configuration)\xmlprofileparser.lib;$(SolutionDir)$(Platform)\$(Configuration)\iorequestgenerator.lib;$(SolutionDir)$(Platform)\$(Configuration)\resultparser.lib;$(SolutionDir)$(Platform)\$(Configuration)\xmlresultparser.lib;$(SolutionDir)$(Platform)\$(Configuration)\common.lib;msxml6.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>fileextd.lib;$(SolutionDir)$(Configuration)\xmlprofileparser.lib;$(SolutionDir)$(Configuration)\iorequestgenerator.lib;$(SolutionDir)$(Configuration)\resultparser.lib;$(SolutionDir)$(Configuration)\xmlresultparser.lib;$(SolutionDir)$(Configuration)\common.lib;msxml6.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/SUBSYSTEM:CONSOLE,5.01 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>fileextd.lib;$(SolutionDir)$(Platform)\$(Configuration)\xmlprofileparser.lib;$(SolutionDir)$(Platform)\$(Configuration)\iorequestgenerator.lib;$(SolutionDir)$(Platform)\$(Configuration)\resultparser.lib;$(SolutionDir)$(Platform)\$(Configuration)\xmlresultparser.lib;$(SolutionDir)$(Platform)\$(Configuration)\common.lib;msxml6.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/SUBSYSTEM:CONSOLE,5.02 %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\CmdLineParser\CmdLineParser.vcxproj">
|
||||
<Project>{0ef5ce78-8e92-4a1b-a255-0f544aada291}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\CmdRequestCreator\CmdRequestCreator.h" />
|
||||
<ClInclude Include="..\..\CmdRequestCreator\errors.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\CmdRequestCreator\CmdRequestCreator.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
||||
@@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{B253AB42-F482-417A-82CE-EDAFCD26F366}</ProjectGuid>
|
||||
<RootNamespace>Common</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\Common\Common.cpp" />
|
||||
<ClCompile Include="..\..\Common\IoBucketizer.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\Common\Common.h" />
|
||||
<ClInclude Include="..\..\Common\Histogram.h" />
|
||||
<ClInclude Include="..\..\Common\IoBucketizer.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{62DB1E99-FBA0-45FD-9355-423059BA03B8}</ProjectGuid>
|
||||
<RootNamespace>IORequestGenerator</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>E:\fbl_ph_dev01\sdktools\phtools\diskspd\IORequestGenerator\IORequestGenerator.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>E:\fbl_ph_dev01\sdktools\phtools\diskspd\IORequestGenerator\IORequestGenerator.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>E:\fbl_ph_dev01\sdktools\phtools\diskspd\IORequestGenerator\IORequestGenerator.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>E:\fbl_ph_dev01\sdktools\phtools\diskspd\IORequestGenerator\IORequestGenerator.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\IORequestGenerator\etw.h" />
|
||||
<ClInclude Include="..\..\IORequestGenerator\IORequestGenerator.h" />
|
||||
<ClInclude Include="..\..\IORequestGenerator\OverlappedQueue.h" />
|
||||
<ClInclude Include="..\..\IORequestGenerator\ThroughputMeter.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\IORequestGenerator\etw.cpp" />
|
||||
<ClCompile Include="..\..\IORequestGenerator\IORequestGenerator.cpp" />
|
||||
<ClCompile Include="..\..\IORequestGenerator\OverlappedQueue.cpp" />
|
||||
<ClCompile Include="..\..\IORequestGenerator\ThroughputMeter.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{F6C211DC-B076-4716-BCDC-D7DE88973B66}</ProjectGuid>
|
||||
<RootNamespace>ResultParser</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>E:\fbl_ph_dev01\sdktools\phtools\diskspd\ResultParser\ResultParser.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>E:\fbl_ph_dev01\sdktools\phtools\diskspd\ResultParser\ResultParser.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>E:\fbl_ph_dev01\sdktools\phtools\diskspd\ResultParser\ResultParser.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>E:\fbl_ph_dev01\sdktools\phtools\diskspd\ResultParser\ResultParser.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\ResultParser\ResultParser.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\ResultParser\ResultParser.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{EFF06674-B068-45F1-9661-DB9363B025B3}</ProjectGuid>
|
||||
<RootNamespace>XmlProfileParser</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\XmlProfileParser\XmlProfileParser.h" />
|
||||
<ClInclude Include="diskspd.h">
|
||||
<DependentUpon>..\..\XmlProfileParser\diskspd.xsd</DependentUpon>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Xsd Include="..\..\XmlProfileParser\diskspd.xsd" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\XmlProfileParser\XmlProfileParser.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,277 @@
|
||||
#pragma once
|
||||
|
||||
#using <mscorlib.dll>
|
||||
#using <System.dll>
|
||||
#using <System.Data.dll>
|
||||
#using <System.Xml.dll>
|
||||
|
||||
using namespace System::Security::Permissions;
|
||||
[assembly:SecurityPermissionAttribute(SecurityAction::RequestMinimum, SkipVerification=false)];
|
||||
//
|
||||
// このソース コードは xsd によって自動生成されました。Version=4.6.1055.0 です。
|
||||
//
|
||||
namespace XmlProfileParser {
|
||||
using namespace System;
|
||||
ref class NewDataSet;
|
||||
|
||||
|
||||
/// <summary>
|
||||
///Represents a strongly typed in-memory cache of data.
|
||||
///</summary>
|
||||
[System::Serializable,
|
||||
System::ComponentModel::DesignerCategoryAttribute(L"code"),
|
||||
System::ComponentModel::ToolboxItem(true),
|
||||
System::Xml::Serialization::XmlSchemaProviderAttribute(L"GetTypedDataSetSchema"),
|
||||
System::Xml::Serialization::XmlRootAttribute(L"NewDataSet"),
|
||||
System::ComponentModel::Design::HelpKeywordAttribute(L"vs.data.DataSet")]
|
||||
public ref class NewDataSet : public ::System::Data::DataSet {
|
||||
|
||||
private: ::System::Data::SchemaSerializationMode _schemaSerializationMode;
|
||||
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
NewDataSet();
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
NewDataSet(::System::Runtime::Serialization::SerializationInfo^ info, ::System::Runtime::Serialization::StreamingContext context);
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute,
|
||||
System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0"),
|
||||
System::ComponentModel::BrowsableAttribute(true),
|
||||
System::ComponentModel::DesignerSerializationVisibilityAttribute(::System::ComponentModel::DesignerSerializationVisibility::Visible)]
|
||||
virtual property ::System::Data::SchemaSerializationMode SchemaSerializationMode {
|
||||
::System::Data::SchemaSerializationMode get() override;
|
||||
System::Void set(::System::Data::SchemaSerializationMode value) override;
|
||||
}
|
||||
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute,
|
||||
System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0"),
|
||||
System::ComponentModel::DesignerSerializationVisibilityAttribute(::System::ComponentModel::DesignerSerializationVisibility::Hidden)]
|
||||
property ::System::Data::DataTableCollection^ Tables {
|
||||
::System::Data::DataTableCollection^ get() new;
|
||||
}
|
||||
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute,
|
||||
System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0"),
|
||||
System::ComponentModel::DesignerSerializationVisibilityAttribute(::System::ComponentModel::DesignerSerializationVisibility::Hidden)]
|
||||
property ::System::Data::DataRelationCollection^ Relations {
|
||||
::System::Data::DataRelationCollection^ get() new;
|
||||
}
|
||||
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Void InitializeDerivedDataSet() override;
|
||||
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Data::DataSet^ Clone() override;
|
||||
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Boolean ShouldSerializeTables() override;
|
||||
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Boolean ShouldSerializeRelations() override;
|
||||
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Void ReadXmlSerializable(::System::Xml::XmlReader^ reader) override;
|
||||
|
||||
protected: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
virtual ::System::Xml::Schema::XmlSchema^ GetSchemaSerializable() override;
|
||||
|
||||
internal: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
::System::Void InitVars();
|
||||
|
||||
internal: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
::System::Void InitVars(::System::Boolean initTable);
|
||||
|
||||
private: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
::System::Void InitClass();
|
||||
|
||||
private: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
::System::Void SchemaChanged(::System::Object^ sender, ::System::ComponentModel::CollectionChangeEventArgs^ e);
|
||||
|
||||
public: [System::Diagnostics::DebuggerNonUserCodeAttribute]
|
||||
[System::CodeDom::Compiler::GeneratedCodeAttribute(L"System.Data.Design.TypedDataSetGenerator", L"4.0.0.0")]
|
||||
static ::System::Xml::Schema::XmlSchemaComplexType^ GetTypedDataSetSchema(::System::Xml::Schema::XmlSchemaSet^ xs);
|
||||
};
|
||||
}
|
||||
namespace XmlProfileParser {
|
||||
|
||||
|
||||
inline NewDataSet::NewDataSet() {
|
||||
this->BeginInit();
|
||||
this->InitClass();
|
||||
::System::ComponentModel::CollectionChangeEventHandler^ schemaChangedHandler = gcnew ::System::ComponentModel::CollectionChangeEventHandler(this, &XmlProfileParser::NewDataSet::SchemaChanged);
|
||||
__super::Tables->CollectionChanged += schemaChangedHandler;
|
||||
__super::Relations->CollectionChanged += schemaChangedHandler;
|
||||
this->EndInit();
|
||||
}
|
||||
|
||||
inline NewDataSet::NewDataSet(::System::Runtime::Serialization::SerializationInfo^ info, ::System::Runtime::Serialization::StreamingContext context) :
|
||||
::System::Data::DataSet(info, context, false) {
|
||||
if (this->IsBinarySerialized(info, context) == true) {
|
||||
this->InitVars(false);
|
||||
::System::ComponentModel::CollectionChangeEventHandler^ schemaChangedHandler1 = gcnew ::System::ComponentModel::CollectionChangeEventHandler(this, &XmlProfileParser::NewDataSet::SchemaChanged);
|
||||
this->Tables->CollectionChanged += schemaChangedHandler1;
|
||||
this->Relations->CollectionChanged += schemaChangedHandler1;
|
||||
return;
|
||||
}
|
||||
::System::String^ strSchema = (cli::safe_cast<::System::String^ >(info->GetValue(L"XmlSchema", ::System::String::typeid)));
|
||||
if (this->DetermineSchemaSerializationMode(info, context) == ::System::Data::SchemaSerializationMode::IncludeSchema) {
|
||||
::System::Data::DataSet^ ds = (gcnew ::System::Data::DataSet());
|
||||
ds->ReadXmlSchema((gcnew ::System::Xml::XmlTextReader((gcnew ::System::IO::StringReader(strSchema)))));
|
||||
this->DataSetName = ds->DataSetName;
|
||||
this->Prefix = ds->Prefix;
|
||||
this->Namespace = ds->Namespace;
|
||||
this->Locale = ds->Locale;
|
||||
this->CaseSensitive = ds->CaseSensitive;
|
||||
this->EnforceConstraints = ds->EnforceConstraints;
|
||||
this->Merge(ds, false, ::System::Data::MissingSchemaAction::Add);
|
||||
this->InitVars();
|
||||
}
|
||||
else {
|
||||
this->ReadXmlSchema((gcnew ::System::Xml::XmlTextReader((gcnew ::System::IO::StringReader(strSchema)))));
|
||||
}
|
||||
this->GetSerializationData(info, context);
|
||||
::System::ComponentModel::CollectionChangeEventHandler^ schemaChangedHandler = gcnew ::System::ComponentModel::CollectionChangeEventHandler(this, &XmlProfileParser::NewDataSet::SchemaChanged);
|
||||
__super::Tables->CollectionChanged += schemaChangedHandler;
|
||||
this->Relations->CollectionChanged += schemaChangedHandler;
|
||||
}
|
||||
|
||||
inline ::System::Data::SchemaSerializationMode NewDataSet::SchemaSerializationMode::get() {
|
||||
return this->_schemaSerializationMode;
|
||||
}
|
||||
inline System::Void NewDataSet::SchemaSerializationMode::set(::System::Data::SchemaSerializationMode value) {
|
||||
this->_schemaSerializationMode = __identifier(value);
|
||||
}
|
||||
|
||||
inline ::System::Data::DataTableCollection^ NewDataSet::Tables::get() {
|
||||
return __super::Tables;
|
||||
}
|
||||
|
||||
inline ::System::Data::DataRelationCollection^ NewDataSet::Relations::get() {
|
||||
return __super::Relations;
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::InitializeDerivedDataSet() {
|
||||
this->BeginInit();
|
||||
this->InitClass();
|
||||
this->EndInit();
|
||||
}
|
||||
|
||||
inline ::System::Data::DataSet^ NewDataSet::Clone() {
|
||||
XmlProfileParser::NewDataSet^ cln = (cli::safe_cast<XmlProfileParser::NewDataSet^ >(__super::Clone()));
|
||||
cln->InitVars();
|
||||
cln->SchemaSerializationMode = this->SchemaSerializationMode;
|
||||
return cln;
|
||||
}
|
||||
|
||||
inline ::System::Boolean NewDataSet::ShouldSerializeTables() {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline ::System::Boolean NewDataSet::ShouldSerializeRelations() {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::ReadXmlSerializable(::System::Xml::XmlReader^ reader) {
|
||||
if (this->DetermineSchemaSerializationMode(reader) == ::System::Data::SchemaSerializationMode::IncludeSchema) {
|
||||
this->Reset();
|
||||
::System::Data::DataSet^ ds = (gcnew ::System::Data::DataSet());
|
||||
ds->ReadXml(reader);
|
||||
this->DataSetName = ds->DataSetName;
|
||||
this->Prefix = ds->Prefix;
|
||||
this->Namespace = ds->Namespace;
|
||||
this->Locale = ds->Locale;
|
||||
this->CaseSensitive = ds->CaseSensitive;
|
||||
this->EnforceConstraints = ds->EnforceConstraints;
|
||||
this->Merge(ds, false, ::System::Data::MissingSchemaAction::Add);
|
||||
this->InitVars();
|
||||
}
|
||||
else {
|
||||
this->ReadXml(reader);
|
||||
this->InitVars();
|
||||
}
|
||||
}
|
||||
|
||||
inline ::System::Xml::Schema::XmlSchema^ NewDataSet::GetSchemaSerializable() {
|
||||
::System::IO::MemoryStream^ stream = (gcnew ::System::IO::MemoryStream());
|
||||
this->WriteXmlSchema((gcnew ::System::Xml::XmlTextWriter(stream, nullptr)));
|
||||
stream->Position = 0;
|
||||
return ::System::Xml::Schema::XmlSchema::Read((gcnew ::System::Xml::XmlTextReader(stream)), nullptr);
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::InitVars() {
|
||||
this->InitVars(true);
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::InitVars(::System::Boolean initTable) {
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::InitClass() {
|
||||
this->DataSetName = L"NewDataSet";
|
||||
this->Prefix = L"";
|
||||
this->Namespace = L"http://microsoft.com/diskspd/DiskSpdConfig.xsd";
|
||||
this->Locale = (gcnew ::System::Globalization::CultureInfo(L""));
|
||||
this->EnforceConstraints = true;
|
||||
this->SchemaSerializationMode = ::System::Data::SchemaSerializationMode::IncludeSchema;
|
||||
}
|
||||
|
||||
inline ::System::Void NewDataSet::SchemaChanged(::System::Object^ sender, ::System::ComponentModel::CollectionChangeEventArgs^ e) {
|
||||
if (e->Action == ::System::ComponentModel::CollectionChangeAction::Remove) {
|
||||
this->InitVars();
|
||||
}
|
||||
}
|
||||
|
||||
inline ::System::Xml::Schema::XmlSchemaComplexType^ NewDataSet::GetTypedDataSetSchema(::System::Xml::Schema::XmlSchemaSet^ xs) {
|
||||
XmlProfileParser::NewDataSet^ ds = (gcnew XmlProfileParser::NewDataSet());
|
||||
::System::Xml::Schema::XmlSchemaComplexType^ type = (gcnew ::System::Xml::Schema::XmlSchemaComplexType());
|
||||
::System::Xml::Schema::XmlSchemaSequence^ sequence = (gcnew ::System::Xml::Schema::XmlSchemaSequence());
|
||||
::System::Xml::Schema::XmlSchemaAny^ any = (gcnew ::System::Xml::Schema::XmlSchemaAny());
|
||||
any->Namespace = ds->Namespace;
|
||||
sequence->Items->Add(any);
|
||||
type->Particle = sequence;
|
||||
::System::Xml::Schema::XmlSchema^ dsSchema = ds->GetSchemaSerializable();
|
||||
if (xs->Contains(dsSchema->TargetNamespace)) {
|
||||
::System::IO::MemoryStream^ s1 = (gcnew ::System::IO::MemoryStream());
|
||||
::System::IO::MemoryStream^ s2 = (gcnew ::System::IO::MemoryStream());
|
||||
try {
|
||||
::System::Xml::Schema::XmlSchema^ schema = nullptr;
|
||||
dsSchema->Write(s1);
|
||||
for ( ::System::Collections::IEnumerator^ schemas = xs->Schemas(dsSchema->TargetNamespace)->GetEnumerator(); schemas->MoveNext(); ) {
|
||||
schema = (cli::safe_cast<::System::Xml::Schema::XmlSchema^ >(schemas->Current));
|
||||
s2->SetLength(0);
|
||||
schema->Write(s2);
|
||||
if (s1->Length == s2->Length) {
|
||||
s1->Position = 0;
|
||||
s2->Position = 0;
|
||||
for ( ; ((s1->Position != s1->Length)
|
||||
&& (s1->ReadByte() == s2->ReadByte())); ) {
|
||||
;
|
||||
}
|
||||
if (s1->Position == s1->Length) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (s1 != nullptr) {
|
||||
s1->Close();
|
||||
}
|
||||
if (s2 != nullptr) {
|
||||
s2->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
xs->Add(dsSchema);
|
||||
return type;
|
||||
}
|
||||
}
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{60A28E9C-C245-4D99-9C1C-EC911031743F}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>XmlResultParser</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Common;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>false</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
<StringPooling>true</StringPooling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
<Lib>
|
||||
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
|
||||
</Lib>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<StringPooling>true</StringPooling>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\XmlResultParser\xmlresultparser.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\XmlResultParser\xmlresultparser.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
Binary file not shown.
@@ -0,0 +1,96 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.30723.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdLineParser", "CmdLineParser\CmdLineParser.vcxproj", "{0EF5CE78-8E92-4A1B-A255-0F544AADA291}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdRequestCreator", "CmdRequestCreator\CmdRequestCreator.vcxproj", "{D238F8AA-DE12-49E7-B4A7-9B69579A69C0}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{B253AB42-F482-417A-82CE-EDAFCD26F366} = {B253AB42-F482-417A-82CE-EDAFCD26F366}
|
||||
{EFF06674-B068-45F1-9661-DB9363B025B3} = {EFF06674-B068-45F1-9661-DB9363B025B3}
|
||||
{0EF5CE78-8E92-4A1B-A255-0F544AADA291} = {0EF5CE78-8E92-4A1B-A255-0F544AADA291}
|
||||
{62DB1E99-FBA0-45FD-9355-423059BA03B8} = {62DB1E99-FBA0-45FD-9355-423059BA03B8}
|
||||
{60A28E9C-C245-4D99-9C1C-EC911031743F} = {60A28E9C-C245-4D99-9C1C-EC911031743F}
|
||||
{F6C211DC-B076-4716-BCDC-D7DE88973B66} = {F6C211DC-B076-4716-BCDC-D7DE88973B66}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "IORequestGenerator", "IORequestGenerator\IORequestGenerator.vcxproj", "{62DB1E99-FBA0-45FD-9355-423059BA03B8}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ResultParser", "ResultParser\ResultParser.vcxproj", "{F6C211DC-B076-4716-BCDC-D7DE88973B66}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XmlProfileParser", "XmlProfileParser\XmlProfileParser.vcxproj", "{EFF06674-B068-45F1-9661-DB9363B025B3}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "Common\Common.vcxproj", "{B253AB42-F482-417A-82CE-EDAFCD26F366}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XmlResultParser", "XmlResultParser\XmlResultParser.vcxproj", "{60A28E9C-C245-4D99-9C1C-EC911031743F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{0EF5CE78-8E92-4A1B-A255-0F544AADA291}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{0EF5CE78-8E92-4A1B-A255-0F544AADA291}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{0EF5CE78-8E92-4A1B-A255-0F544AADA291}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0EF5CE78-8E92-4A1B-A255-0F544AADA291}.Debug|x64.Build.0 = Debug|x64
|
||||
{0EF5CE78-8E92-4A1B-A255-0F544AADA291}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{0EF5CE78-8E92-4A1B-A255-0F544AADA291}.Release|Win32.Build.0 = Release|Win32
|
||||
{0EF5CE78-8E92-4A1B-A255-0F544AADA291}.Release|x64.ActiveCfg = Release|x64
|
||||
{0EF5CE78-8E92-4A1B-A255-0F544AADA291}.Release|x64.Build.0 = Release|x64
|
||||
{D238F8AA-DE12-49E7-B4A7-9B69579A69C0}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{D238F8AA-DE12-49E7-B4A7-9B69579A69C0}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{D238F8AA-DE12-49E7-B4A7-9B69579A69C0}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D238F8AA-DE12-49E7-B4A7-9B69579A69C0}.Debug|x64.Build.0 = Debug|x64
|
||||
{D238F8AA-DE12-49E7-B4A7-9B69579A69C0}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{D238F8AA-DE12-49E7-B4A7-9B69579A69C0}.Release|Win32.Build.0 = Release|Win32
|
||||
{D238F8AA-DE12-49E7-B4A7-9B69579A69C0}.Release|x64.ActiveCfg = Release|x64
|
||||
{D238F8AA-DE12-49E7-B4A7-9B69579A69C0}.Release|x64.Build.0 = Release|x64
|
||||
{62DB1E99-FBA0-45FD-9355-423059BA03B8}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{62DB1E99-FBA0-45FD-9355-423059BA03B8}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{62DB1E99-FBA0-45FD-9355-423059BA03B8}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{62DB1E99-FBA0-45FD-9355-423059BA03B8}.Debug|x64.Build.0 = Debug|x64
|
||||
{62DB1E99-FBA0-45FD-9355-423059BA03B8}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{62DB1E99-FBA0-45FD-9355-423059BA03B8}.Release|Win32.Build.0 = Release|Win32
|
||||
{62DB1E99-FBA0-45FD-9355-423059BA03B8}.Release|x64.ActiveCfg = Release|x64
|
||||
{62DB1E99-FBA0-45FD-9355-423059BA03B8}.Release|x64.Build.0 = Release|x64
|
||||
{F6C211DC-B076-4716-BCDC-D7DE88973B66}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{F6C211DC-B076-4716-BCDC-D7DE88973B66}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{F6C211DC-B076-4716-BCDC-D7DE88973B66}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F6C211DC-B076-4716-BCDC-D7DE88973B66}.Debug|x64.Build.0 = Debug|x64
|
||||
{F6C211DC-B076-4716-BCDC-D7DE88973B66}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{F6C211DC-B076-4716-BCDC-D7DE88973B66}.Release|Win32.Build.0 = Release|Win32
|
||||
{F6C211DC-B076-4716-BCDC-D7DE88973B66}.Release|x64.ActiveCfg = Release|x64
|
||||
{F6C211DC-B076-4716-BCDC-D7DE88973B66}.Release|x64.Build.0 = Release|x64
|
||||
{EFF06674-B068-45F1-9661-DB9363B025B3}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{EFF06674-B068-45F1-9661-DB9363B025B3}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{EFF06674-B068-45F1-9661-DB9363B025B3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{EFF06674-B068-45F1-9661-DB9363B025B3}.Debug|x64.Build.0 = Debug|x64
|
||||
{EFF06674-B068-45F1-9661-DB9363B025B3}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{EFF06674-B068-45F1-9661-DB9363B025B3}.Release|Win32.Build.0 = Release|Win32
|
||||
{EFF06674-B068-45F1-9661-DB9363B025B3}.Release|x64.ActiveCfg = Release|x64
|
||||
{EFF06674-B068-45F1-9661-DB9363B025B3}.Release|x64.Build.0 = Release|x64
|
||||
{B253AB42-F482-417A-82CE-EDAFCD26F366}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B253AB42-F482-417A-82CE-EDAFCD26F366}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B253AB42-F482-417A-82CE-EDAFCD26F366}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B253AB42-F482-417A-82CE-EDAFCD26F366}.Debug|x64.Build.0 = Debug|x64
|
||||
{B253AB42-F482-417A-82CE-EDAFCD26F366}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B253AB42-F482-417A-82CE-EDAFCD26F366}.Release|Win32.Build.0 = Release|Win32
|
||||
{B253AB42-F482-417A-82CE-EDAFCD26F366}.Release|x64.ActiveCfg = Release|x64
|
||||
{B253AB42-F482-417A-82CE-EDAFCD26F366}.Release|x64.Build.0 = Release|x64
|
||||
{60A28E9C-C245-4D99-9C1C-EC911031743F}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{60A28E9C-C245-4D99-9C1C-EC911031743F}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{60A28E9C-C245-4D99-9C1C-EC911031743F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{60A28E9C-C245-4D99-9C1C-EC911031743F}.Debug|x64.Build.0 = Debug|x64
|
||||
{60A28E9C-C245-4D99-9C1C-EC911031743F}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{60A28E9C-C245-4D99-9C1C-EC911031743F}.Release|Win32.Build.0 = Release|Win32
|
||||
{60A28E9C-C245-4D99-9C1C-EC911031743F}.Release|x64.ActiveCfg = Release|x64
|
||||
{60A28E9C-C245-4D99-9C1C-EC911031743F}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user