首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Linux多线程增强文件打开()

Linux多线程增强文件打开()
EN

Stack Overflow用户
提问于 2010-07-28 17:36:55
回答 1查看 1.3K关注 0票数 4

我正致力于在一个高性能、高容量的数据引擎上优化性能,最终为最终用户提供web体验。具体来说,委托给我的部分主要是描述多线程文件IO和数据到本地缓存的内存映射。在编写测试应用程序以隔离时序高极时,已经暴露出几个问题。代码被最小化为只执行系统文件打开(open(O_RDONLY))调用。我希望这个查询的结果能够帮助我们理解基本的低级别系统过程,以便能够理解一个完整的预测(至少是关系)时间模型。建议总是受欢迎的。我们似乎遇到了一个时间障碍,并希望了解行为,并确定是否可以打破这个障碍。

测试程序:

pthreads;

  • loads

  • 是用C编写的,使用gnu编译器编译,如下所示;

  • 被编写得最少,以便将发现的问题隔离到单个系统文件“open()”中;

  • 可配置为同时启动请求的数目为8K的文本文件--一个包含1000个文本文件的列表;

  • 创建线程(简单地),而不修改属性;

  • 每个线程从预先确定的文件列表中对下一个可用文件执行多个顺序的文件open()调用,直到文件列表耗尽为止,这样一个线程应该打开所有1000个文件,理论上2个线程应该打开500个文件(到目前为止还没有证明);

)。

我们已经运行了多次测试,参数化地改变了线程数、文件大小以及文件是位于本地服务器还是远程服务器上。出现了几个问题。

观察结果(打开远程文件):

第一次caching);

  • Running文件打开时间较高(如预期的那样,由于文件),该测试应用程序只需一个线程即可加载所有远程文件,耗时X秒;在机器上运行线程数介于1到#可用CPU数量之间的应用程序似乎会导致与CPU数量成正比的时间(使用线程计数># seconds).
  1. Running的应用程序会导致运行时间似乎与使用#CPU线程所需时间大致相同的运行时间(例如,这种巧合或系统限制,或what?).
  2. Running多个并发进程)。(相同测试应用程序的25个并发实例的时间与不同服务器上选定的线程count.
  3. Running应用程序的进程数近似线性,显示类似的结果

观察结果(打开居住在当地的档案):

expected);

  • With增加线程计数时,在4-5个活动线程上出现一个较低的定时拐点,然后再次增加,直到线程数等于CPU计数为止,然后将again;

  • Running多个并发进程(相同的测试)调整为接近线性的时间,与恒定线程计数的进程数(与上面#5相同的结果相同)。

另外,我们注意到本地打开.01 ms,顺序网络打开在1ms时慢了100倍。打开网络文件,我们得到了8倍的线性吞吐量增加了8个线程,但9+线程什么也不做。在8个以上的同时请求之后,网络打开的呼叫似乎被阻塞了。我们期望的是初始延迟等于网络往返,然后与本地吞吐量大致相同。也许在本地和远程系统上有额外的互斥锁,需要花费100倍的时间。可能有一些内部队列的远程调用只能容纳8。

预期的结果和问题将通过测试或这样的论坛的答案来回答:

运行多个线程将导致相同的工作在更短的时间内完成;observed?

  • How

  • 是否有最佳线程数;

  • 是否与可用的CPU数量之间存在关系?

  • 是否有其他系统原因: 8-10文件限制是time-slice;

  • Does,系统调用“open()”在多线程process?

  • Each线程中是否获得其上下文切换的time-slice;

  • Does--打开()调用块,然后等待文件打开/加载到文件缓存?或者调用允许在操作处于progress?

  • When时发生上下文切换-- open()完成,调度程序是否重新确定线程的优先顺序以便更早执行,还是线程必须等待其轮回循环;

  • 将1000个文件所在的挂载卷设置为只读或读/写使difference?

  • When open()被调用为一个完整的路径,路径stat()中的每个元素是否都已被调用?在文件树列表中打开()一个公共目录,然后通过相对路径打开该公共目录下的文件更有意义吗?

开发测试设置:

代码语言:javascript
运行
复制
Red Hat Enterprise Linux Server release 5.4 (Tikanga)

8-CPUS, each with characteristics as shown below:

processor       : 0
vendor_id       : GenuineIntel
cpu family      : 6
model           : 23
model name      : Intel(R) Xeon(R) CPU           X5460  @ 3.16GHz
stepping        : 6
cpu MHz         : 1992.000
cache size      : 6144 KB
physical id     : 0
siblings        : 4
core id         : 1
cpu cores       : 4
apicid          : 1
fpu             : yes
fpu_exception   : yes
cpuid level     : 10
wp              : yes
flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall lm constant_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 lahf_lm
bogomips        : 6317.47
clflush size    : 64
cache_alignment : 64
address sizes   : 38 bits physical, 48 bits virtual
power management:

GNU C compiler, version:
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46)
EN

回答 1

Stack Overflow用户

发布于 2010-07-28 17:57:02

不确定这是否是你的问题之一,但它可能是有用的。

让我印象深刻的是,在一个SATA磁盘上优化数千个随机读取时,在没有额外线程的情况下,在linux中执行非阻塞I/O并不容易。

在块设备上发出非阻塞的read() (目前)是不可能的;也就是说,它将阻塞磁盘所需的5 ms寻址时间(5 ms是永恒的,3 GHz)。将O_NONBLOCK指定为open()只具有向后兼容性的目的,与CD刻录机或其他东西兼容(这是一个相当模糊的问题)。通常,open()不会阻塞或缓存任何东西,主要是为了获得一个文件的句柄,以便稍后执行一些数据I/O操作。

就我的目的而言,mmap()似乎使我尽可能接近磁盘的内核处理。使用madvise()mincore(),我能够充分利用磁盘的NCQ功能,通过改变未执行请求的队列深度就可以证明这一点,这与发出10k读取所用的总时间成反比。

由于64位内存寻址,使用mmap()将整个磁盘映射到内存是完全没有问题的。(在32位平台上,需要使用mmap64()映射所需磁盘的各个部分)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3355697

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档