Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions Code/EntryPoint.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <iostream>

#include "GetProcessorInformation.hpp"
#include "OverlappedIOFileRead.hpp"

int main(int argc, const char * argv[]) {
Expand All @@ -9,9 +10,19 @@ int main(int argc, const char * argv[]) {
return -1;
}

const DWORD worker_thread_count = 6;
// TODO: Take the file as part of the command line parameters.
auto overlapped_io_file_read = PrepareToReadFile(argv[1], worker_thread_count);
auto processor_information = GetProcessorInformation();
if (!processor_information.has_value()) {
std::cerr << "Error: Could not find processor information." << std::endl;
return -1;
}

std::cout << "CPU cores: " << processor_information->actual_cores_;
if (processor_information->hyperthreading_cores_ != 0) {
std::cout << " (and " << processor_information->hyperthreading_cores_ << " hyperthreading cores)";
}
std::cout << std::endl;

auto overlapped_io_file_read = PrepareToReadFile(argv[1], processor_information->actual_cores_);
if (!overlapped_io_file_read.has_value()) {
std::cerr << "Error";
return -1;
Expand Down
90 changes: 90 additions & 0 deletions Code/GetProcessorInformation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include "GetProcessorInformation.hpp"

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>

#include <memory>

//#include <iostream>

/*struct ProcessorInformation {
int actual_cores_;
int hyperthreading_cores_;
};*/

std::optional<ProcessorCoreInformation> GetProcessorInformation() noexcept {
DWORD required_buffer_size = 0;
BOOL result = GetLogicalProcessorInformation(nullptr, &required_buffer_size);
if (result == FALSE) {
DWORD error_code = GetLastError();
if (error_code != ERROR_INSUFFICIENT_BUFFER) {
return std::nullopt;
}
}
size_t processor_information_count = required_buffer_size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
auto processor_information = std::make_unique<SYSTEM_LOGICAL_PROCESSOR_INFORMATION[]>(processor_information_count);
result = GetLogicalProcessorInformation(processor_information.get(), &required_buffer_size);
if (result == FALSE) {
return std::nullopt;
}

ProcessorCoreInformation processor_core_information = {};

for(DWORD i = 0; i < processor_information_count; i++) {
//std::cout << "Core " << i << ": " << processor_information[i].ProcessorMask << std::endl;
switch (processor_information[i].Relationship) {
/*
case RelationProcessorPackage:
std::cout << "\tPhysical package" << std::endl;
break;
case RelationNumaNode:
std::cout << "\tNUMA node: " << processor_information[i].NumaNode.NodeNumber << std::endl;
break;
*/
case RelationProcessorCore:
{
processor_core_information.actual_cores_++;
if (processor_information[i].ProcessorCore.Flags == 1) {
processor_core_information.hyperthreading_cores_++;
}
}
break;
/*
case RelationCache:
std::cout << "\tL";
switch (processor_information[i].Cache.Level) {
case 1:
std::cout << "1 ";
break;
case 2:
std::cout << "2 ";
break;
case 3:
std::cout << "3 ";
break;
}
switch (processor_information[i].Cache.Type) {
case CacheUnified:
std::cout << "unified";
break;
case CacheInstruction:
std::cout << "instuction";
break;
case CacheData:
std::cout << "data";
break;
case CacheTrace:
std::cout << "trace";
break;
}
std::cout << " cache, " << processor_information[i].Cache.Size << " KiB" << std::endl;
std::cout << "\tCache line size: " << processor_information[i].Cache.LineSize << " KiB" << std::endl;
break;
*/
}
}

return processor_core_information;
}
14 changes: 14 additions & 0 deletions Code/GetProcessorInformation.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef GETPROCESSORINFORMATION_HPP
#define GETPROCESSORINFORMATION_HPP

#include <optional>

class ProcessorCoreInformation {
public:
int actual_cores_;
int hyperthreading_cores_;
};

std::optional<ProcessorCoreInformation> GetProcessorInformation() noexcept;

#endif // #ifndef GETPROCESSORINFORMATION_HPP
23 changes: 21 additions & 2 deletions Code/OverlappedIOFileRead.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ namespace {
if (!allocation.has_value()) {
return std::nullopt;
}
//buffer = std::make_unique<char[]>(BUFFER_SIZE);
// TODO: Confirm the allocation is aligned to volume sector size
// TODO: Confirm buffer_size is a multiple of volume sector size

auto io_context = IOContext{std::move(overlapped), overlapped_io_file.handle_, std::move(*allocation), buffer_size, file_offset};

Expand Down Expand Up @@ -227,12 +228,30 @@ std::expected<OverlappedIOFileRead, PrepareToReadFileError> PrepareToReadFile(LP
return std::unexpected{PrepareToReadFileError::CouldNotGetFileSize};
}

std::cout << "File size: " << file_size.QuadPart << std::endl;

FILE_STORAGE_INFO file_storage_info;
result = GetFileInformationByHandleEx(file->handle_, FileStorageInfo, &file_storage_info, sizeof(file_storage_info));
if (result == FALSE) {
return std::unexpected{PrepareToReadFileError::CouldNotGetFileSize};
}
unsigned long partition_block_size = file_storage_info.PhysicalBytesPerSectorForPerformance;
unsigned long partition_block_size = file_storage_info.LogicalBytesPerSector;
// When doing writes instead of reads, prefer file_storage_info.PhysicalBytesPerSectorForPerformance;

// Get the page size
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
/*if (compiling for x86 or arm64) {
SYSTEM_INFO native_system_info;
GetNativeSystemInfo(&native_system_info);
}*/
partition_block_size = system_info.dwPageSize;
// TODO: Confirm the page size is a multiple of the logical bytes per sector

// On Windows, VirtualAlloc has 64 KiB granularity:
// https://devblogs.microsoft.com/oldnewthing/20031008-00/?p=42223
// TODO: Should we push the buffer size to 64 KiB?

std::cout << "Buffer size: " << partition_block_size << std::endl;

auto completion_port = CreateCompletionPort(*file, worker_thread_count);
Expand Down
2 changes: 2 additions & 0 deletions Projects/VisualStudio/FileReadSpeedTest.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\Code\EntryPoint.cpp" />
<ClCompile Include="..\..\Code\GetProcessorInformation.cpp" />
<ClCompile Include="..\..\Code\OSAllocator.cpp" />
<ClCompile Include="..\..\Code\OverlappedIOFileRead.cpp" />
<ClCompile Include="..\..\Code\Win32Types.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Code\GetProcessorInformation.hpp" />
<ClInclude Include="..\..\Code\OSAllocator.hpp" />
<ClInclude Include="..\..\Code\OverlappedIOFileRead.hpp" />
<ClInclude Include="..\..\Code\Win32Types.hpp" />
Expand Down
2 changes: 2 additions & 0 deletions Projects/VisualStudio/FileReadSpeedTest.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
<ClCompile Include="..\..\Code\OSAllocator.cpp" />
<ClCompile Include="..\..\Code\OverlappedIOFileRead.cpp" />
<ClCompile Include="..\..\Code\Win32Types.cpp" />
<ClCompile Include="..\..\Code\GetProcessorInformation.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Code\OSAllocator.hpp" />
<ClInclude Include="..\..\Code\OverlappedIOFileRead.hpp" />
<ClInclude Include="..\..\Code\Win32Types.hpp" />
<ClInclude Include="..\..\Code\GetProcessorInformation.hpp" />
</ItemGroup>
</Project>
Loading