问题标签 [overlapped-io]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
67 浏览

operating-system - 什么样的事情会导致整个系统看起来挂起 100 到 1000 毫秒?

我正在开发一款 Windows 游戏,在渲染时,一些计算机会遇到间歇性暂停(“卡顿”,因为没有更好的术语)。分析时,它们出现在代码中看似随机的位置。最终我注意到受影响的不仅仅是我的进程,而是(似乎)系统上的每个进程。我的应用程序中的所有线程都会立即连接。在这些故障期间 CPU 利用率下降,并且似乎大多数进程都没有进展。

这让我相信这可能是操作系统或驱动程序问题,但它仅在玩游戏时发生(并且仅在某些系统上)。操作系统可能正在执行什么样的操作,这将需要内核暂停所有用户线程并阻塞。某种I/O?起初我想到了分页,但我的印象是这只会影响一个进程,不是吗?

使用中的一些系统:Windows、DirectX (3d)、nVidia 卡(如果在 ATI 上复制则未知),使用重叠 io 进行流式传输

0 投票
1 回答
1098 浏览

winapi - 异步 NtQueryDirectoryFile?

有没有人设法弄清楚对NtQueryDirectoryFile的异步调用是如何工作的?

通过异步调用,我的意思是调用未使用FILE_SYNCHRONOUS_IO_ALERTFILE_SYNCHRONOUS_IO_NONALERT打开的NtQueryDirectoryFile目录。

对我来说,它似乎STATUS_PENDING像普通文件上的普通NtReadFile请求一样返回,但是当我尝试在目录上使用NtWaitForSingleObject时,它没有正确结束,我仍然没有得到所有数据......为什么这会发生吗?

0 投票
1 回答
2017 浏览

windows - 微小读取(重叠、缓冲)优于大型连续读取的解释?

(为有点冗长的介绍道歉)

在开发一个将整个大文件 (>400MB) 预置到缓冲区缓存中以加速以后实际运行的应用程序的开发过程中,我测试了一次读取 4MB 是否仍然比一次仅读取 1MB 块有任何明显的好处。令人惊讶的是,较小的请求实际上速度更快。这似乎违反直觉,所以我进行了更广泛的测试。

缓冲区缓存在运行测试之前被清除(只是为了笑,我也对缓冲区中的文件进行了一次运行。无论请求大小如何,缓冲区缓存都提供超过 2GB/s 的速度,尽管令人惊讶的是 +/- 30%随机方差)。
所有读取都使用与相同目标缓冲区重叠的 ReadFile(句柄打开时使用FILE_FLAG_OVERLAPPED不使用 FILE_FLAG_NO_BUFFERING)。使用的硬盘有些陈旧但功能齐全,NTFS 的集群大小为 8kB。磁盘在初始运行后进行了碎片整理(6 个碎片与未碎片化,零差异)。为了获得更好的数字,我也使用了更大的文件,以下数字用于读取 1GB。

结果真的很令人惊讶:

因此,这表明提交两个集群长度的一万个请求实际上比提交几百个大的连续读取要好。提交时间(ReadFile 返回之前的时间)确实随着请求数量的增加而大幅增加,但异步完成时间几乎减半。
在异步读取完成时,内核 CPU 时间在每种情况下大约为 5-6%(在四核上,所以应该说是 20-30%),这是一个令人惊讶的 CPU 数量——显然操作系统做了一些非也可以忽略不计的忙碌等待。30% CPU 在 2.6 GHz 下持续 25 秒,这对于“无所事事”来说是相当多的周期。

知道如何解释吗?也许这里有人对 Windows 重叠 IO 的内部工作有更深入的了解?或者,您可以使用 ReadFile 读取一兆字节数据的想法是否存在重大问题?

我可以看到 IO 调度程序如何通过最小化搜索来优化多个请求,尤其是当请求是随机访问时(它们不是!)。给定 NCQ 中的一些请求,我还可以看到硬盘如何执行类似的优化。
然而,我们谈论的是荒谬的小请求数量——尽管如此,它们的性能却比看起来合理的要高出 2 倍。

旁注:明显的赢家是内存映射。我几乎倾向于添加“不出所料”,因为我是内存映射的忠实粉丝,但在这种情况下,它确实让我感到惊讶,因为“请求”更小,操作系统应该更无法预测和安排 IO。起初我没有测试内存映射,因为它甚至可以远程竞争似乎违反直觉。你的直觉就这么多,呵呵。

以不同的偏移量重复映射/取消映射视图几乎需要零时间。使用 16MB 视图并使用简单的 for() 循环对每个页面进行故障排除,每页读取一个字节可在 9.2 秒内完成 @ ~111 MB/s。CPU 使用率始终低于 3%(一个核心)。相同的计算机,相同的磁盘,相同的一切。

尽管实际上只创建了一个页面,但 Windows 似乎一次将 8 个页面加载到缓冲区缓存中。每 8 页故障以相同的速度运行并从磁盘加载相同数量的数据,但显示较低的“物理内存”和“系统缓存”指标,并且只有 1/8 的页面故障。随后的读取证明页面仍然明确地位于缓冲区缓存中(没有延迟,没有磁盘活动)。

(可能与Memory-Mapped File is Faster on Huge Sequential Read 的关系非常非常遥远?

为了使其更具说明性:
在此处输入图像描述

更新:

使用FILE_FLAG_SEQUENTIAL_SCAN似乎在某种程度上“平衡”了 128k 的读取,将性能提高了 100%。另一方面,它会严重影响 512k 和 256k 的读取(您必须想知道为什么?),并且对其他任何内容都没有实际影响。可以说,较小块大小的 MB/s 图看起来更“均匀”,但运行时没有区别。

在此处输入图像描述

我可能也找到了较小块大小表现更好的解释。如您所知,如果操作系统可以立即处理请求,即从缓冲区(以及针对各种特定于版本的技术限制),异步请求可能会同步运行。

在考虑实际异步与“立即”异步读取时,人们注意到超过 256k,Windows 异步运行每个异步请求。块大小越小,“立即”处理的请求就越多,即使它们不能立即可用(即 ReadFile 只是同步运行)。我无法确定一个清晰的模式(例如“前 100 个请求”或“超过 1000 个请求”),但请求大小和同步性之间似乎存在反比关系。在 8k 的块大小下,每个异步请求都是同步服务的。
出于某种原因,缓冲同步传输的速度是异步传输的两倍(不知道为什么),因此请求大小越小,整体传输越快,因为更多传输是同步完成的。

对于内存映射预故障,FILE_FLAG_SEQUENTIAL_SCAN 会导致性能图的形状略有不同(有一个“缺口”向后移动了一点),但所花费的总时间完全相同(再次,这令人惊讶,但我不能帮助它)。

更新 2:

无缓冲 IO 使 1M、4M 和 512k 请求测试用例的性能图更高,更“尖峰”,最大值为 90 GB/s,但也有苛刻的最小值,1GB 的整体运行时间在 +/- 0.5 以内缓冲运行的 s(缓冲区大小较小的请求完成速度明显更快,但是,这是因为有超过 2558 个正在进行的请求,返回 ERROR_WORKING_SET_QUOTA)。在所有未缓冲的情况下,测得的 CPU 使用率为零,这不足为奇,因为发生的任何 IO 都通过 DMA 运行。

另一个非常有趣的观察结果FILE_FLAG_NO_BUFFERING是它显着改变了 API 行为。CancelIO不再起作用,至少在取消 IO的意义上没有。对于未缓冲的正在进行的请求,CancelIO将简单地阻塞,直到所有请求都完成。律师可能会争辩说,该功能不能因疏忽其职责而承担责任,因为当它返回时已经没有更多的飞行请求了,所以在某种程度上它已经完成了所要求的——但我对“取消”的理解有点不同。
使用缓冲的重叠 IO,CancelIO将简单地切断绳索,所有进行中的操作都会立即终止,正如人们所期望的那样。

另一个有趣的事情是,在所有请求都完成或失败之前,该进程是无法终止的。如果操作系统正在对该地址空间进行 DMA,这种做法是有道理的,但它仍然是一个令人惊叹的“功能”。

0 投票
1 回答
982 浏览

c++ - 重叠套接字 IO 中的错误处理

如果使用重叠的套接字 IO 和 IOCP,任何人都可以建议一种可靠的方法来处理系统错误吗?

MSDN 在这方面的描述比较繁琐。它说对于GetQueuedCompletionStatus返回代码 FALSE 应该有一个后续GetLastError调用来获取失败操作的错误代码。但是,我们知道对于 WSA 函数,应该调用它WSAGetLastErrorGetLastError在套接字错误时返回 0)。所以问题的第一部分是——它在实践中是如何工作的?

另一个问题是如果完成数据包由GetQueuedCompletionStatusEx. MSDN 只描述了这个调用本身的错误处理,没有提到获取单个失败操作的错误代码。

提前感谢所有回复和评论。

0 投票
3 回答
4234 浏览

c++ - WaitCommEvent 在第二次通过时失败无效参数

我的应用程序使用带有重叠事件的串行 I/O。出于某种原因,::WaitCommEvent在第二次通过循环时始终失败ERROR_INVALID_PARAMETER。如果有人可以解释我需要做的不同的事情,将不胜感激。我的串口初始化/打开代码和线程函数如下。需要注意的是,init/open 代码是在线程函数启动执行的,这就是调用::WaitForSingleObjectfor 的内容。

此外,我想知道类似的东西::WaitForSingleObject( pobjSerialPort->m_hSerialPort, INFINITE );是否可以作为确定串行端口何时打开的非阻塞方式有效。

串口初始化:

串行端口通信事件线程:

处理通讯事件功能

处理接收到的数据通信事件函数

接收线程函数

0 投票
1 回答
120 浏览

c++ - 在调试器中时 Winsock2 数据丢失

我将 Winsock2 与重叠 I/O 结合使用。这意味着我用 WSAOVERLAPPED 结构调用 WSARecv,然后我用 WSAWaitForMultipleEvents 等待数据。

我做了一个奇怪的观察,当我用调试器停止它时,我似乎丢失了发送到我的应用程序的任何数据。我认为这些数据会堆积在操作系统的某个地方,然后在下一次调用 WSARecv 时传递。

我的假设是错误的吗?

0 投票
2 回答
3610 浏览

c - 同步写入使用 FILE_FLAG_OVERLAPPED 打开的文件

我打开了一个文件

然后将文件句柄用于异步读取操作:

这行得通。但是,我现在想做一个同步写入。WriteFile文件指出

如果 hFile 是使用 FILE_FLAG_OVERLAPPED 打开的,则以下条件生效:
• lpOverlapped 参数必须指向一个有效且唯一的 OVERLAPPED 结构,否则该函数可能会错误地报告写操作已完成。

lpOverlapepd省略参数时,ERROR_INVALID_PARAMETER由 . 返回GetLastError()。打开两个句柄,一个用于读取,一个用于写入也不起作用,因为第二个句柄会产生ERROR_ACCESS_DENIED错误。

如何打开文件进行异步读取和同步写入?我不想不必要地增加代码复杂性。

0 投票
3 回答
2597 浏览

c++ - Winsock:重叠的 AcceptEx 表示新连接,而没有客户端连接

在我的程序中,我使用 的重叠版本AcceptEx()来接受新的连接。在接受新连接后,程序会发起另一个重叠调用以AcceptEx()接受更多连接。这工作正常,我可以成功地将多个客户端连接到服务器。

但是,如果我只连接一个客户端并让服务器应用程序在此套接字上调用 WSARecv(重叠), AcceptEx()则会神奇地接受一个新的“幽灵”连接(第一个客户端什么都不做)。当然,当我调用WSARecv它时 - 它给出了一个错误。

该程序为所有重叠调用合并了一个I/O 完成端口。

我不知道假连接来自哪里。但这似乎是我无法找到的代码中的错误。

我可以明确排除的错误原因:1.我使用的重叠结构和铸造参数正确。2. IOCP 包装类

以下是相关代码(在我看来) - 如果您需要更多,请告诉我:)

编辑:写了一个工作得很好的测试服务器

0 投票
1 回答
1069 浏览

c++ - 为什么对 recv 的重叠调用会返回 ERROR_NO_MORE_ITEMS(259)?

我用 I/O-Completion 端口和 winsock 套接字做了一些测试。我遇到过,有时在我从连接接收数据然后在该套接字上再次相邻调用 WSARecv 后,它会立即返回错误 259 (ERROR_NO_MORE_ITEMS)。

我想知道为什么系统会使用此错误标记重叠事务,而不是保持 recv 调用阻塞/等待传入数据。

你知道这是什么意思吗?

我很高兴听到你的想法。

编辑:代码

减少错误检查...

Recv-member-function 是 WSARecv-call 的简单包装器,它创建 WSABUF 和接收缓冲区本身(需要由用户通过 freewsabuf 清理 - 只是提一下)...

0 投票
2 回答
2271 浏览

winapi - 具有重叠 I/O 的 TCP 连接

是否可以使用重叠 I/O 发起 TCP 连接请求,并在 Windows 中连接完成之前取消它?我需要至少支持 Windows XP SP2。