插座问题

时间:2012-04-30 04:07:52

标签: multithreading performance sockets thread-safety zero-copy

有几个插槽问题,并且找不到肯定的是或否,所以如果它是转发,请提前道歉:)平台是Linux 2.6.30,C ++应用程序。网络仍然很新,速度很快。

  1. 套接字API线程是否安全?例如,如果我在不使用互斥锁的情况下从多个线程发送,或者我必须使用自己的互斥锁来确保这一点吗?

  2. 最好是轮询/选择检查我的发送是否会阻止然后执行发送,而不仅仅是执行发送并让发送API内部排队处理发送?如果线程无论如何都要阻塞(如果我不使用超时,那就是),我真的不明白为什么需要一个轮询后跟一个发送。

  3. Linux中默认套接字是零拷贝,还是涉及到拷贝?如果有副本(不是根据API,而是根据粒度),是否存在大小限制?如果答案是内核确实进行了复制,是否有零拷贝套接字?

  4. 如果我必须在两台机器之间进行通信,我会假设多个套接字比单个套接字更好地利用带宽。这是一个正确的假设吗?什么是在两台常规Linux机器之间使用完整BW的最佳方法?

  5. 5.Whats您最喜欢的工具,用于测量接口上的当前带宽使用情况?这可能只是一个偏好,我看了iptraf等,但想看看其他人使用和最喜欢的东西。

2 个答案:

答案 0 :(得分:3)

  1. 套接字API在每个套接字上绝对是线程安全的...即只要任何给定的套接字只被一个线程访问,其他线程可以同时访问其他套接字而没有任何问题。让多个线程同时访问同一个套接字可能是也可能不是“线程安全的”(对于线程安全的某些定义)但是在任何情况下都不建议这样做,因为结果行为不容易预测。 (例如,两个线程在同一个套接字上大约同时调用recv(),哪个线程将从传入的TCP流中获取哪些字节?上帝只知道)

  2. 如果您正在使用阻塞I / O,那么在调用send()之前使用poll / select()进行检查并不是非常有用,因为即使select()表示您在传出缓冲区中有空间,无论如何可能会阻止send()内部。 (例如,如果缓冲区中有32个字节的空间,然后尝试发送64个字节,则send()将阻塞)。 select()和poll()与非阻塞I / O一起使用更为有用。

  3. 我不太确定Linux套接字中的零拷贝状态,但是Wikipedia article似乎暗示如果使用sendfile(),sendfile64,Linux只会进行零拷贝()或splice()调用。鉴于现代CPU,我怀疑它是多么重要 - 除了最高性能的程序之外,所有程序都有足够的CPU周期来复制网络数据;它是网络接口本身的速度,将成为瓶颈。

  4. 多个套接字不会比单个套接字提供更好的带宽利用率;如果您足够快地将数据泵入网络连接,单个插槽可以轻松地使网络连接饱和。特别是多个TCP连接通常会比单个TCP连接带来更差的带宽利用率,因为每个TCP连接都会产生自己的传输开销,更糟糕的是,多个TCP连接将争夺带宽,并且在某些时候开始导致彼此丢弃数据包他们将通过降低发送率来减少拥塞,从而做出回应。

  5. 我无法为Linux回答这个问题;在MacOS / X活动监视器下将显示网络带宽使用情况。

答案 1 :(得分:1)

Jeremy的观点#3有点不准确。随着多个高速网络接口和大量数据的移动,零拷贝变得更加重要。在内存中复制缓冲区所花费的时间会影响吞吐量和延迟。异步IO和分散/聚集支持对于高速网络系统至关重要。