Merge pull request #1452 from aws-lumberyard-dev/Streamer/ConfigUpdates

Streamer config updates
This commit is contained in:
AMZN-koppersr
2021-06-22 14:57:15 -07:00
committed by GitHub
14 changed files with 429 additions and 58 deletions
@@ -44,8 +44,7 @@ namespace AZ::IO
//! make adjustments. For the most optimal performance align read buffers to the physicalSectorSize.
u8 m_enableUnbufferedReads : 1;
//! Globally enable file sharing. This allows files to used outside AZ::IO::Streamer, including other applications
//! while in use by AZ::IO::Streamer. File sharing can negatively impact performance and is recommended for
//! development only.
//! while in use by AZ::IO::Streamer.
u8 m_enableSharing : 1;
//! If true, only information that's explicitly requested or issues are reported. If false, status information
//! such as when drives are created and destroyed is reported as well.
@@ -312,7 +312,7 @@ namespace AZ::IO
{
if (reportHardware)
{
AZ_Printf("Streamer", "Skipping drive '%s' because to no paths make use of it.\n", driveIt);
AZ_Printf("Streamer", "Skipping drive '%s' because no paths make use of it.\n", driveIt);
}
while (*driveIt++);
continue;
@@ -46,6 +46,7 @@ namespace AZ::IO
options.m_hasSeekPenalty = HasSeekPenalty;
options.m_enableUnbufferedReads = TestEnableUnbufferReads;
options.m_enableSharing = TestEnableSharedReads;
options.m_minimalReporting = true;
return StorageDriveWin({ "c:/" }, TestMaxFileHandles, TestMaxMetaDataEntries, TestPhysicalSectorSize,
TestLogicalSectorSize, TestMaxIOChannels, TestOverCommit, options);
@@ -151,6 +152,7 @@ namespace AZ::IO
m_configurationOptions.m_hasSeekPenalty = HasSeekPenalty;
m_configurationOptions.m_enableUnbufferedReads = TestEnableUnbufferReads;
m_configurationOptions.m_enableSharing = TestEnableSharedReads;
m_configurationOptions.m_minimalReporting = true;
m_storageDriveWin = AZStd::make_shared<AZ::IO::StorageDriveWin>(AZStd::vector<AZStd::string_view>{drive}, TestMaxFileHandles,
TestMaxMetaDataEntries, TestPhysicalSectorSize, TestLogicalSectorSize, TestMaxIOChannels, overCommit, m_configurationOptions);
@@ -1148,3 +1150,142 @@ namespace AZ::IO
azfree(buffers[numRequests - 1]);
}
} // namespace AZ::IO
#if defined(HAVE_BENCHMARK)
#include <benchmark/benchmark.h>
namespace Benchmark
{
class StorageDriveWindowsFixture : public benchmark::Fixture
{
public:
constexpr static char* TestFileName = "StreamerBenchmark.bin";
constexpr static size_t FileSize = 64_mib;
void SetupStreamer(bool enableFileSharing)
{
using namespace AZ::IO;
m_fileIO = new UnitTest::TestFileIOBase();
m_previousFileIO = AZ::IO::FileIOBase::GetInstance();
AZ::IO::FileIOBase::SetInstance(nullptr);
AZ::IO::FileIOBase::SetInstance(m_fileIO);
SystemFile file;
file.Open(TestFileName, SystemFile::OpenMode::SF_OPEN_CREATE | SystemFile::OpenMode::SF_OPEN_READ_WRITE);
AZStd::unique_ptr<char[]> buffer(new char[FileSize]);
::memset(buffer.get(), 'c', FileSize);
file.Write(buffer.get(), FileSize);
file.Close();
AZStd::optional<AZ::IO::FixedMaxPathString> absolutePath = AZ::Utils::ConvertToAbsolutePath(TestFileName);
if (absolutePath.has_value())
{
AZStd::string drive;
AZ::StringFunc::Path::GetDrive(absolutePath->c_str(), drive);
m_absolutePath = *absolutePath;
StorageDriveWin::ConstructionOptions options;
options.m_hasSeekPenalty = false;
options.m_enableUnbufferedReads = true; // Leave this on otherwise repeated loads will be using the Windows cache instead.
options.m_enableSharing = enableFileSharing;
options.m_minimalReporting = true;
AZStd::shared_ptr<StreamStackEntry> storageDriveWin =
AZStd::make_shared<StorageDriveWin>(AZStd::vector<AZStd::string_view>{ drive }, 32, 32, 4_kib, 512, 8, 0, options);
AZStd::unique_ptr<Scheduler> stack = AZStd::make_unique<Scheduler>(AZStd::move(storageDriveWin));
m_streamer = aznew Streamer(AZStd::thread_desc{}, AZStd::move(stack));
}
}
void TearDown([[maybe_unused]] const ::benchmark::State& state) override
{
using namespace AZ::IO;
AZStd::string temp;
m_absolutePath.swap(temp);
delete m_streamer;
SystemFile::Delete(TestFileName);
AZ::IO::FileIOBase::SetInstance(nullptr);
AZ::IO::FileIOBase::SetInstance(m_previousFileIO);
delete m_fileIO;
}
void RepeatedlyReadFile(benchmark::State& state)
{
using namespace AZ::IO;
using namespace AZStd::chrono;
AZStd::unique_ptr<char[]> buffer(new char[FileSize]);
for (auto _ : state)
{
AZStd::binary_semaphore waitForReads;
AZStd::atomic<system_clock::time_point> end;
auto callback = [&end, &waitForReads]([[maybe_unused]] FileRequestHandle request)
{
benchmark::DoNotOptimize(end = high_resolution_clock::now());
waitForReads.release();
};
FileRequestPtr request = m_streamer->Read(m_absolutePath, buffer.get(), state.range(0), state.range(0));
m_streamer->SetRequestCompleteCallback(request, callback);
system_clock::time_point start;
benchmark::DoNotOptimize(start = high_resolution_clock::now());
m_streamer->QueueRequest(request);
waitForReads.try_acquire_for(AZStd::chrono::seconds(5));
auto durationInSeconds = duration_cast<duration<double>>(end.load() - start);
state.SetIterationTime(durationInSeconds.count());
m_streamer->QueueRequest(m_streamer->FlushCaches());
}
}
AZStd::string m_absolutePath;
AZ::IO::Streamer* m_streamer{};
AZ::IO::FileIOBase* m_previousFileIO{};
UnitTest::TestFileIOBase* m_fileIO{};
};
BENCHMARK_DEFINE_F(StorageDriveWindowsFixture, ReadsBaseline)(benchmark::State& state)
{
constexpr bool EnableFileSharing = false;
SetupStreamer(EnableFileSharing);
RepeatedlyReadFile(state);
}
BENCHMARK_DEFINE_F(StorageDriveWindowsFixture, ReadsWithFileReadSharingEnabled)(benchmark::State& state)
{
using namespace AZ::IO;
constexpr bool EnableFileSharing = true;
SetupStreamer(EnableFileSharing);
RepeatedlyReadFile(state);
}
// For these benchmarks the CPU stat doesn't provide useful information because it uses GetThreadTimes on Window but since the main
// thread is mostly sleeping while waiting for the read on the Streamer thread to complete this will report values (close to) zero.
BENCHMARK_REGISTER_F(StorageDriveWindowsFixture, ReadsBaseline)
->RangeMultiplier(8)
->Range(1024, 64_mib)
->UseManualTime()
->Unit(benchmark::kMillisecond);
BENCHMARK_REGISTER_F(StorageDriveWindowsFixture, ReadsWithFileReadSharingEnabled)
->RangeMultiplier(8)
->Range(1024, 64_mib)
->UseManualTime()
->Unit(benchmark::kMillisecond);
} // namespace Benchmark
#endif // HAVE_BENCHMARK