所以我不知道为什么会这样,但我的应用程序可以选择使用CRC对非常大的文件(最大50gb)执行一些完整性检查。因为如果他们打开此选项我不想杀死用户的计算机,我在句柄上设置了IoPriorityHintVeryLow提示,并且还使用this API将线程优先级设置为THREAD_MODE_BACKGROUND_BEGIN。
我的代码中耗时的部分如下所示:
//
// Read one block of the changed data at a time, checking each CRC
//
DWORD blockNum = 0;
vector<BYTE> changeBuffer(DIRTY_BLOCK_SIZE);
outputDirtyBlockMap.reserve(crcList.size() / 8);
while (::ReadFile(hChangedFile, changeBuffer.data(), DIRTY_BLOCK_SIZE, &bytesRead, NULL) && bytesRead > 0)
{
// Check for cancellation every 500 blocks, doing it every time reduces CPU performance by 50% since WaitForSingleObject is quite expensive
if ((blockNum % 500 == 0) && IsCancelEventSignalled(hCancel))
{
RETURN_TRACED(ERROR_CANCELLED);
}
// Increase the size of the dirty block map?
ULONG mapByte = blockNum / 8;
if (mapByte == outputDirtyBlockMap.size())
{
outputDirtyBlockMap.resize(mapByte + 1);
}
DWORD mapBitNum = blockNum & 0x7L;
UCHAR mapBit = 1 << (7 - mapBitNum);
if (driverDirtyBlockMap.size() > mapByte && (driverDirtyBlockMap[mapByte] & mapBit))
{
//
// The bit is already set in the drivers block map, we don't have to bother generating comparing CRCs for this block
//
outputDirtyBlockMap[mapByte] |= mapBit;
}
else
{
// Validate that the CRC hasn't changed, if it has, mark it as such in the dirty block map
DWORD newCrc = CRC::Crc32(changeBuffer.data(), changeBuffer.size());
if ((blockNum >= crcList.size() || newCrc != crcList[blockNum]))
{
OPTIONAL_DEBUG(DEBUG_DIRTY_BLOCK_MAP & DEBUG_VERBOSE, "Detected change at block [%u], CRC [new 0x%x != old 0x%x]", blockNum, newCrc, blockNum < crcList.size() ? crcList[blockNum] : 0x0);
// The CRC is changed or the file has grown, mark it as such in the dirty block map
outputDirtyBlockMap[mapByte] |= mapBit;
}
}
++blockNum;
}
当我分析这段代码时,我很惊讶地发现当这个循环在THREAD_MODE_BACKGROUND_BEGIN中运行时,需要74秒才能运行500Mb文件。使用THREAD_PRIORITY_LOWEST运行时,运行500Mb文件需要2.7秒。 (我现在已经测试了大约8次,这是平均值)
在这两种情况下,我测试的机器都是空闲的,而不是运行这个循环。所以问题:
为什么THREAD_MODE_BACKGROUND_BEGIN需要这么长时间?我曾经想过,如果机器没有做任何其他事情,它应该仍然可以像其他任何优先级那样快速运行,因为它不需要优先处理?
我是否应该从这些优先事项中了解一些我无法从文档中找到的优先事项?
答案 0 :(得分:3)
设置背景模式具有以下效果:
将相对线程优先级设置为LOWEST时具有以下效果:
因此,通常,特别是如果您受I / O约束(即使在受CPU约束的情况下),则您肯定会希望线程具有优先级4,并以非常低的I / O优先级和后台内存优先级运行(1)比具有前景内存优先级(5)+普通I / O优先级为6的线程的性能差很多。
答案 1 :(得分:2)
THREAD_MODE_ *与THREAD_PRIORITY_ *不同可能并不令人惊讶?
我不知道是否在任何地方都记录了确切的差异,但如果CPU支持核心停车并且频率较低,后台模式会尝试在单核上运行所有内容,我不会感到惊讶。
SetThreadPriority文档还提示对线程执行的任何I / O进行一些更改:
THREAD_PRIORITY_ *值会影响线程的CPU调度优先级。对于执行后台工作的线程,例如文件I / O,网络I / O或数据处理,仅调整CPU调度优先级是不够的。即使空闲的CPU优先级线程在使用磁盘和内存时也很容易干扰系统响应。执行后台工作的线程应使用THREAD_MODE_BACKGROUND_BEGIN和THREAD_MODE_BACKGROUND_END值来调整其资源调度优先级;与用户交互的线程不应使用THREAD_MODE_BACKGROUND_BEGIN。
您是否尝试过测量以查看性能损失是ReadFile
还是CRC计算?
答案 2 :(得分:0)