Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 增加FileSystemWatcher.InternalBufferSize真的那么昂贵吗?_C#_.net_Performance_Filesystemwatcher - Fatal编程技术网

C# 增加FileSystemWatcher.InternalBufferSize真的那么昂贵吗?

C# 增加FileSystemWatcher.InternalBufferSize真的那么昂贵吗?,c#,.net,performance,filesystemwatcher,C#,.net,Performance,Filesystemwatcher,我正在使用FileSystemWatcher来监视文件夹中的更改,但只要我在短时间内进行了数百次以上的修改,我就会错过其中一些修改,因为内部缓冲区溢出。因此,我想增加InternalBufferSize(我知道这并不能真正解决问题,但它会降低问题发生的可能性),但我看到以下警告: 然而,增加缓冲区大小是昂贵的,因为它来自 无法交换到磁盘的非分页内存,因此请保留 缓冲区尽可能小 所以我的问题是:这真的重要吗?今天的大多数计算机至少有1GB的RAM,所以在我看来,如果我将缓冲区大小设置为1MB(而不

我正在使用
FileSystemWatcher
来监视文件夹中的更改,但只要我在短时间内进行了数百次以上的修改,我就会错过其中一些修改,因为内部缓冲区溢出。因此,我想增加
InternalBufferSize
(我知道这并不能真正解决问题,但它会降低问题发生的可能性),但我看到以下警告:

然而,增加缓冲区大小是昂贵的,因为它来自 无法交换到磁盘的非分页内存,因此请保留 缓冲区尽可能小


所以我的问题是:这真的重要吗?今天的大多数计算机至少有1GB的RAM,所以在我看来,如果我将缓冲区大小设置为1MB(而不是默认的8KB),1MB是否不能交换到磁盘上就无关紧要了。还是我遗漏了什么?我对诸如分页/非分页内存之类的低级内容了解不多,因此我不确定会产生什么影响…

非分页内存的大小有限(更新:现代版本的Windows没有以前版本那样严格的限制,内存量现在是一个灵活的值,取决于Windows可用的总体RAM)并且对于内核模式居民(设备驱动程序、操作系统本身)非常重要。在没有严格控制的情况下使用它会很快导致系统不稳定,更糟糕的是,您无法找到导致这种不稳定的原因

此外,正如评论所指出的,重要的不是缓冲区大小,而是从缓冲区中删除数据的速度


在大多数情况下,文件系统过滤器驱动程序比FileSystemWatcher做得更好。其好处是,您可以拥有所需的任何日志缓冲区(因为您可以在所需的任何内存中创建它,而不受非分页内存的限制),而且您还可以在事件发生时处理事件,而不是在事件发生后处理事件。此外,您可以使用比FileSystemWatcher更精细的粒度过滤请求

考虑一个消费者-生产者设计来读取FileSystemWatcher事件

如果您有一些不需要处理的FileSystemWatcher事件,请快速将其排除。

或者,如果某些进程比其他进程更快,则有一个单独的集合来保持总计数

分配缓冲区的内存当然是宝贵的资源。Windows无法很好地处理耗尽内存池的问题,驱动程序将开始随机出现故障。池的大小是动态设置的(但可以更改),并取决于可用RAM的数量

FSW要求的默认缓冲区大小为8192字节。在现代机器上不多。基础winapi函数不允许您请求超过64KB的内存。一个条目是缓冲区是12字节加上文件路径的长度乘以2。因此,更糟糕的情况是8192/(12+260*2)=在缓冲区耗尽之前发送15个通知。这在大多数情况下都应该可以正常工作,除非您监视整个驱动器或正在监视的目录中有非常高的磁盘流量。在这种情况下,要求更大的缓冲是公平的。没有黄金公式,请确保实现FileSystemWatcher.Error事件,这样您就知道存在缓冲区问题


在大多数实际情况下,您需要仔细处理FSW事件。当进程仍锁定文件时,将引发这些错误。因此,像打开或复制文件这样的操作很麻烦。处理方法是将通知放在线程安全队列中,并使用另一个线程尝试获取文件的锁,必要时可以重复。这样的队列现在自动也是快速清空缓冲区的一种非常好的方法。您现在唯一需要注意的是,队列不会超出合理的比例,从而导致程序因OOM而崩溃。

文档还说“您可以将缓冲区设置为4KB或更大,但不能超过64KB。”如果事件发生的速度快于您处理它们的速度,增加缓冲区大小只会延迟不可避免的事情。@StuartDunkeld,是的,但我认为这只是一个建议。代码中没有任何东西可以实际执行它,如果设置的值大于64KB,它就会工作。@SteveWellens,是的,我在我的问题中也这么说过。然而,这将使不可避免的事情变得不太可能…@ThomasLevesque-我不知道这是否对你有帮助,但当我监视一个目录中的传入文件时,我关闭了监视程序,处理目录中的所有文件,直到它为空,然后重新打开监视程序。谢谢你的回答。我读过关于文件系统过滤器驱动程序的文章,但我不想走这条路,至少现在不行。尝试更快地从缓冲区中删除事件可能是我最好的选择。我将尝试一下!谢谢你的详细回答。在大多数情况下,我并不真的需要一个大的缓冲区,但我注意到,如果用户将一个大目录复制到我正在监视的目录中,就会出现缓冲区溢出,这会使我错过一些事件。尽可能快地清空缓冲区似乎是一个好的解决方案。目前我在事件处理程序中有一个
,这可能是我清空缓冲区速度不够快的原因;我会尽量在没有锁的情况下做,以提高性能。小心,没有锁是不容易的。这些事件是在线程池线程上引发的,因此几乎总是需要锁定。使用ConcurrentQueue或类似的工具可以工作吗?我想它不用锁,是吗?我可以将事件排队,然后在不同的线程中处理它们。是的。它使用锁,你看不到它们。它针对最小的锁定开销进行了优化。