我有20个文本文件存储在硬盘中,每个文件包含数百万个关于教育机构的信息。假设我有一个方法可以循环和处理迭代文本文件。这是做工作的最佳方式为每个文本文件(Factory.startnew())启动每个线程或为每个文本文件启动每个进程(process.start())
修改 我有8GB内存,8核服务器,所以想在线程或进程中处理它们。目前我正在使用进程,我现在没有找到任何瓶颈。但是我处于使用线程或进程的困境
答案 0 :(得分:4)
硬盘的读取速度很可能是这里的瓶颈。
因此,根据您需要对数据执行的处理,使用多个线程可能会或可能不会很有趣(我当然不会使用进程)。
然而,最重要的是确保没有多个线程同时访问同一个物理磁盘,因为这会因为不断切换和寻求而导致速度减慢hdd-heads。
我最近已经做了一些测试,在某些情况下(取决于硬盘和/或PC),操作系统负责它并没有产生很大的影响,但是在另一个组合上,减速可以看到正常速度的1/10。
因此,如果使用多个线程(只有在数据处理时间超过hdd的读取时才需要!),请确保在某个地方有锁,以防止多个线程同时从磁盘读取。 / p>
您可能还想查看内存映射文件。
修改强>:
如果你正在使用缓冲区,你可以启动一个线程来连续填充缓冲区,而另一个线程处理数据。
edit2 (回答Micky):
“最好,更快,占用更少内存的进程或线程?”
正如我所说,我不会使用进程(由于额外的开销)。这会留下线程,或者根本没有线程 - 这取决于需要对数据执行的处理量。如果直接从内存缓冲区读取数据(而不是使用readline
之类的东西,例如所有投注都将关闭),则一个或多个。两个线程可能是最好的选择(如果数据处理速度足够快 - 需要进行测试和计时)。
至于速度和内存使用:最佳选项(对我来说)将是内存映射文件(文件以仅转发模式打开)。这不仅可以利用操作系统磁盘缓存的效率,还可以直接访问内核内存 - 而在使用(用户)缓冲区时,内存必须从内核复制到用户空间,这需要时间和使用额外的记忆。
IOCP :好的,但取决于线程会询问的内容。例如,如果10个线程每次要求100kB(在不同的文件上),则需要10 x 10ms的搜索时间,而读取100Kb则需要不到1ms。未来请求的访问时间取决于IOCP如何处理缓存,这可能与使用内存映射相同,但我不认为在这种情况下IOCP会更快。
使用IOCP,可能也会在用户空间中复制/填充缓冲区(通常可能更难处理)。但我必须说,在写我的答案时,我正在考虑使用C / C ++(使用直接访问内存缓冲区),但后来才看到它是C#。虽然原则保持不变,但C#中可能有一种简单的方法可以使用IOCP进行异步I / O.
关于速度测试和同时避免读取:我已经在大文件上进行了超过50个线程的测试(通过内存映射) - 如果正确完成,则不会丢失读取速度。另一方面,当只是触发一些线程并让它们随机访问硬盘时(即使在大块中),在某些情况下总读取速度可能降至10% - 有时根本不会。相同的PC,其他硬盘,其他结果。