Skip to content

Commit

Permalink
Pull request for 2.0.21a release (#74)
Browse files Browse the repository at this point in the history
* Support for memory mapped I/O
Added support for memory mapped I/O to enhance storage-related memory device development and testing.

* Support for ETW events
Added support for ETW events to distinguish between various phases and to trace individual I/Os.

* Support for displaying system information
Added support for displaying system information such as the computer name and the time the run was started.

* Changed case of various files
Changed the case of various files and directories to match the rest of the project.

* Remove the use of runtime DLLs in Visual Studio
Updated the Visual Studio projects to remove the use of runtime DLLs.

* Depreciated in-branch documentation
Depreciated the use of in-branch documentation in favor of https://github.com/Microsoft/diskspd/wiki/Home.
  • Loading branch information
DanPear committed Sep 28, 2018
1 parent a2d7fcf commit 3c154ff
Show file tree
Hide file tree
Showing 32 changed files with 1,261 additions and 58 deletions.
88 changes: 80 additions & 8 deletions CmdLineParser/CmdLineParser.cpp
Expand Up @@ -176,6 +176,11 @@ void CmdLineParser::_DisplayUsageInfo(const char *pszFilename) const
printf(" -l Use large pages for IO buffers\n");
printf(" -L measure latency statistics\n");
printf(" -n disable default affinity (-a)\n");
printf(" -N<vni> specify the flush mode for memory mapped I/O\n");
printf(" v : uses the FlushViewOfFile API\n");
printf(" n : uses the RtlFlushNonVolatileMemory API\n");
printf(" i : uses RtlFlushNonVolatileMemory without waiting for the flush to drain\n");
printf(" [default: none]\n");
printf(" -o<count> number of outstanding I/O requests per target per thread\n");
printf(" (1=synchronous I/O, unless more than 1 thread is specified with -F)\n");
printf(" [default=2]\n");
Expand All @@ -194,14 +199,16 @@ void CmdLineParser::_DisplayUsageInfo(const char *pszFilename) const
printf(" manipulate a shared offset with InterlockedIncrement, which may reduce throughput,\n");
printf(" but promotes a more sequential pattern.\n");
printf(" (ignored if -r specified, -si conflicts with -T and -p)\n");
printf(" -S[bhruw] control caching behavior [default: caching is enabled, no writethrough]\n");
printf(" -S[bhmruw] control caching behavior [default: caching is enabled, no writethrough]\n");
printf(" non-conflicting flags may be combined in any order; ex: -Sbw, -Suw, -Swu\n");
printf(" -S equivalent to -Su\n");
printf(" -Sb enable caching (default, explicitly stated)\n");
printf(" -Sh equivalent -Suw\n");
printf(" -Sm enable memory mapped I/O\n");
printf(" -Su disable software caching, equivalent to FILE_FLAG_NO_BUFFERING\n");
printf(" -Sr disable local caching, with remote sw caching enabled; only valid for remote filesystems\n");
printf(" -Sw enable writethrough (no hardware write caching), equivalent to FILE_FLAG_WRITE_THROUGH\n");
printf(" -Sw enable writethrough (no hardware write caching), equivalent to FILE_FLAG_WRITE_THROUGH or\n");
printf(" non-temporal writes for memory mapped I/O (-Sm)\n");
printf(" -t<count> number of threads per target (conflicts with -F)\n");
printf(" -T<offs>[K|M|G|b] starting stride between I/O operations performed on the same target by different threads\n");
printf(" [default=0] (starting offset = base file offset + (thread number * <offs>)\n");
Expand Down Expand Up @@ -480,6 +487,39 @@ bool CmdLineParser::_ParseAffinity(const char *arg, TimeSpan *pTimeSpan)
return fOk;
}

bool CmdLineParser::_ParseFlushParameter(const char *arg, MemoryMappedIoFlushMode *FlushMode)
{
assert(nullptr != arg);
assert(0 != *arg);

bool fOk = true;
if (*(arg + 1) != '\0')
{
const char *c = arg + 1;
if (_stricmp(c, "v") == 0)
{
*FlushMode = MemoryMappedIoFlushMode::ViewOfFile;
}
else if (_stricmp(c, "n") == 0)
{
*FlushMode = MemoryMappedIoFlushMode::NonVolatileMemory;
}
else if (_stricmp(c, "i") == 0)
{
*FlushMode = MemoryMappedIoFlushMode::NonVolatileMemoryNoDrain;
}
else
{
fOk = false;
}
}
else
{
fOk = false;
}
return fOk;
}

bool CmdLineParser::_ReadParametersFromCmdLine(const int argc, const char *argv[], Profile *pProfile, struct Synchronization *synch)
{
/* Process any command-line options */
Expand Down Expand Up @@ -530,6 +570,8 @@ bool CmdLineParser::_ReadParametersFromCmdLine(const int argc, const char *argv[
// this allows for conflicts to be thrown for mixed -h/-S as needed.
TargetCacheMode t = TargetCacheMode::Undefined;
WriteThroughMode w = WriteThroughMode::Undefined;
MemoryMappedIoMode m = MemoryMappedIoMode::Undefined;
MemoryMappedIoFlushMode f = MemoryMappedIoFlushMode::Undefined;

TimeSpan timeSpan;
bool bExit = false;
Expand Down Expand Up @@ -837,6 +879,13 @@ bool CmdLineParser::_ReadParametersFromCmdLine(const int argc, const char *argv[
timeSpan.SetDisableAffinity(true);
break;

case 'N':
if (!_ParseFlushParameter(arg, &f))
{
fError = true;
}
break;

case 'o': //request count (1==synchronous)
{
int c = atoi(arg + 1);
Expand Down Expand Up @@ -989,14 +1038,27 @@ bool CmdLineParser::_ReadParametersFromCmdLine(const int argc, const char *argv[
break;
case 'h':
if (t == TargetCacheMode::Undefined &&
w == WriteThroughMode::Undefined)
w == WriteThroughMode::Undefined &&
m == MemoryMappedIoMode::Undefined)
{
t = TargetCacheMode::DisableOSCache;
w = WriteThroughMode::On;
}
else
{
fprintf(stderr, "-Sh conflicts with earlier specification of cache/writethrough\n");
fprintf(stderr, "-Sh conflicts with earlier specification of cache/writethrough/memory mapped\n");
fError = true;
}
break;
case 'm':
if (m == MemoryMappedIoMode::Undefined &&
t != TargetCacheMode::DisableOSCache)
{
m = MemoryMappedIoMode::On;
}
else
{
fprintf(stderr, "-Sm conflicts with earlier specification of memory mapped IO/unbuffered IO\n");
fError = true;
}
break;
Expand All @@ -1012,13 +1074,14 @@ bool CmdLineParser::_ReadParametersFromCmdLine(const int argc, const char *argv[
}
break;
case 'u':
if (t == TargetCacheMode::Undefined)
if (t == TargetCacheMode::Undefined &&
m == MemoryMappedIoMode::Undefined)
{
t = TargetCacheMode::DisableOSCache;
}
else
{
fprintf(stderr, "-Su conflicts with earlier specification of cache mode\n");
fprintf(stderr, "-Su conflicts with earlier specification of cache mode/memory mapped IO\n");
fError = true;
}
break;
Expand All @@ -1043,7 +1106,8 @@ bool CmdLineParser::_ReadParametersFromCmdLine(const int argc, const char *argv[
// bare -S, parse loop did not advance
if (!fError && idx == 1)
{
if (t == TargetCacheMode::Undefined)
if (t == TargetCacheMode::Undefined &&
m == MemoryMappedIoMode::Undefined)
{
t = TargetCacheMode::DisableOSCache;
}
Expand Down Expand Up @@ -1283,7 +1347,7 @@ bool CmdLineParser::_ReadParametersFromCmdLine(const int argc, const char *argv[
return false;
}

// apply resultant cache/writethrough modes to the targets
// apply resultant cache/writethrough/memory mapped io modes to the targets
for (auto i = vTargets.begin(); i != vTargets.end(); i++)
{
if (t != TargetCacheMode::Undefined)
Expand All @@ -1294,6 +1358,14 @@ bool CmdLineParser::_ReadParametersFromCmdLine(const int argc, const char *argv[
{
i->SetWriteThroughMode(w);
}
if (m != MemoryMappedIoMode::Undefined)
{
i->SetMemoryMappedIoMode(m);
}
if (f != MemoryMappedIoFlushMode::Undefined)
{
i->SetMemoryMappedIoFlushMode(f);
}
}

// ... and apply targets to the timespan
Expand Down
4 changes: 4 additions & 0 deletions CmdRequestCreator/CmdRequestCreator.cpp
Expand Up @@ -152,6 +152,8 @@ int __cdecl main(int argc, const char* argv[])
return 1;
}

TraceLoggingRegister(g_hEtwProvider);

//
// call IO request generator
//
Expand Down Expand Up @@ -179,6 +181,8 @@ int __cdecl main(int argc, const char* argv[])
return 1;
}

TraceLoggingUnregister(g_hEtwProvider);

if( NULL != synch.hStartEvent )
{
CloseHandle(synch.hStartEvent);
Expand Down
1 change: 1 addition & 0 deletions Common/CmdLineParser.h
Expand Up @@ -45,6 +45,7 @@ class CmdLineParser
bool _ReadParametersFromXmlFile(const char *pszPath, Profile *pProfile);

bool _ParseETWParameter(const char *arg, Profile *pProfile);
bool _ParseFlushParameter(const char *arg, MemoryMappedIoFlushMode *FlushMode );
bool _ParseAffinity(const char *arg, TimeSpan *pTimeSpan);

void _DisplayUsageInfo(const char *pszFilename) const;
Expand Down
129 changes: 129 additions & 0 deletions Common/Common.cpp
Expand Up @@ -29,6 +29,10 @@ SOFTWARE.

#include "Common.h"

TRACELOGGING_DEFINE_PROVIDER(g_hEtwProvider,
"Microsoft-Windows-DiskSpd", // {CA13DB84-D0A9-5145-FCA4-468DA92FDC2D}
(0xca13db84, 0xd0a9, 0x5145, 0xfc, 0xa4, 0x46, 0x8d, 0xa9, 0x2f, 0xdc, 0x2d));

SystemInformation g_SystemInformation;

UINT64 PerfTimer::GetTime()
Expand Down Expand Up @@ -288,6 +292,28 @@ string Target::GetXml() const
break;
}

// MemoryMappedIoMode::Off is implied default
switch (_memoryMappedIoMode)
{
case MemoryMappedIoMode::On:
sXml += "<MemoryMappedIo>true</MemoryMappedIo>\n";
break;
}

// MemoryMappedIoFlushMode::Undefined is implied default
switch (_memoryMappedIoFlushMode)
{
case MemoryMappedIoFlushMode::ViewOfFile:
sXml += "<FlushType>ViewOfFile</FlushType>\n";
break;
case MemoryMappedIoFlushMode::NonVolatileMemory:
sXml += "<FlushType>NonVolatileMemory</FlushType>\n";
break;
case MemoryMappedIoFlushMode::NonVolatileMemoryNoDrain:
sXml += "<FlushType>NonVolatileMemoryNoDrain</FlushType>\n";
break;
}

sXml += "<WriteBufferContent>\n";
if (_fZeroWriteBuffers)
{
Expand Down Expand Up @@ -854,6 +880,26 @@ bool Profile::Validate(bool fSingleSpec, SystemInformation *pSystem) const
}
}

if (target.GetMemoryMappedIoMode() == MemoryMappedIoMode::On)
{
if (timeSpan.GetCompletionRoutines())
{
fprintf(stderr, "ERROR: completion routines (-x) can't be used with memory mapped IO (-Sm)\n");
fOk = false;
}
if (target.GetCacheMode() == TargetCacheMode::DisableOSCache)
{
fprintf(stderr, "ERROR: unbuffered IO (-Su or -Sh) can't be used with memory mapped IO (-Sm)\n");
fOk = false;
}
}

if (target.GetMemoryMappedIoMode() == MemoryMappedIoMode::Off &&
target.GetMemoryMappedIoFlushMode() != MemoryMappedIoFlushMode::Undefined)
{
fprintf(stderr, "ERROR: memory mapped flush mode (-N) can only be specified with memory mapped IO (-Sm)\n");
}

// 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
Expand Down Expand Up @@ -960,6 +1006,45 @@ BYTE* ThreadParameters::GetWriteBuffer(size_t iTarget, size_t iRequest)
return pBuffer;
}

bool ThreadParameters::InitializeMappedViewForTarget(Target& target, DWORD DesiredAccess)
{
bool fOk = true;
DWORD dwProtect = PAGE_READWRITE;

if (DesiredAccess == GENERIC_READ)
{
dwProtect = PAGE_READONLY;
}

HANDLE hFile = CreateFileMapping(target.GetMappedViewFileHandle(), NULL, dwProtect, 0, 0, NULL);
fOk = (hFile != NULL);
if (fOk)
{
DWORD dwDesiredAccess = FILE_MAP_WRITE;

if (DesiredAccess == GENERIC_READ)
{
dwDesiredAccess = FILE_MAP_READ;
}

BYTE *mapView = (BYTE*) MapViewOfFile(hFile, dwDesiredAccess, 0, 0, 0);
fOk = (mapView != NULL);
if (fOk)
{
target.SetMappedView(mapView);
}
else
{
fprintf(stderr, "FATAL ERROR: Could not map view for target '%s'. Error code: 0x%x\n", target.GetPath().c_str(), GetLastError());
}
}
else
{
fprintf(stderr, "FATAL ERROR: Could not create a file mapping for target '%s'. Error code: 0x%x\n", target.GetPath().c_str(), GetLastError());
}
return fOk;
}

DWORD ThreadParameters::GetTotalRequestCount() const
{
DWORD cRequests = 0;
Expand All @@ -977,3 +1062,47 @@ DWORD ThreadParameters::GetTotalRequestCount() const

return cRequests;
}

void EtwResultParser::ParseResults(vector<Results> vResults)
{
if (TraceLoggingProviderEnabled(g_hEtwProvider,
TRACE_LEVEL_NONE,
DISKSPD_TRACE_INFO))
{
for (size_t ullResults = 0; ullResults < vResults.size(); ullResults++)
{
const Results& results = vResults[ullResults];
for (size_t ullThread = 0; ullThread < results.vThreadResults.size(); ullThread++)
{
const ThreadResults& threadResults = results.vThreadResults[ullThread];
for (const auto& targetResults : threadResults.vTargetResults)
{
if (targetResults.ullReadIOCount)
{
_WriteResults(IOOperation::ReadIO, targetResults, ullThread);
}
if (targetResults.ullWriteIOCount)
{
_WriteResults(IOOperation::WriteIO, targetResults, ullThread);
}
}
}
}
}
}

void EtwResultParser::_WriteResults(IOOperation type, const TargetResults& targetResults, size_t ullThread)
{
UINT64 ullIOCount = (type == IOOperation::ReadIO) ? targetResults.ullReadIOCount : targetResults.ullWriteIOCount;
UINT64 ullBytesCount = (type == IOOperation::ReadIO) ? targetResults.ullReadBytesCount : targetResults.ullWriteBytesCount;

TraceLoggingWrite(g_hEtwProvider,
"Statistics",
TraceLoggingLevel((TRACE_LEVEL_NONE)),
TraceLoggingString((type == IOOperation::ReadIO) ? "Read" : "Write", "IO Type"),
TraceLoggingUInt64(ullThread, "Thread"),
TraceLoggingUInt64(ullBytesCount, "Bytes"),
TraceLoggingUInt64(ullIOCount, "IO Count"),
TraceLoggingString(targetResults.sPath.c_str(), "Path"),
TraceLoggingUInt64(targetResults.ullFileSize, "File Size"));
}

0 comments on commit 3c154ff

Please sign in to comment.