[转帖]How fast are Unix domain sockets?

how,fast,are,unix,domain,sockets · 浏览次数 : 0

小编点评

## Summary of the Unix domain socket performance comparison: **Key points:** * Both IP and Unix domain socket implementations are using TCP (socket.SOCK_STREAM). * The Unix socket implementation significantly outperforms the IP one, sending and receiving more than twice the number of messages, over the course of a second. * This difference is attributed to the bypass of the entire IP stack by the Unix socket, eliminating header calculations, checksums, and other overhead. * This performance benefit becomes even more significant when dealing with big data transfers. **Additional details:** * The benchmark used (10159 and 22067 messages) represents a relatively small data size. * These numbers might vary depending on the specific workload and other system factors. * The impact of Unix sockets on latency and transfer times depends on the application and workload involved. **Potential implications:** * Unix domain sockets can potentially be used to improve the performance of reverse proxies and other applications communicating within the same machine. * This could lead to a noticeable reduction in latency and improved responsiveness. * However, it's important to consider other factors like network latency and application performance when evaluating this approach. **Further questions to consider:** * How does the performance difference compare to other transport protocols like UDP? * How does the performance compare when transferring big chunks of data? * What are the real-world scenarios where using Unix domain sockets could be advantageous?

正文

https://blog.myhro.info/2017/01/how-fast-are-unix-domain-sockets

 

Warning: this is my first post written in English, after over five years writing only in Portuguese. After reading many technical articles written in English by non-native speakers, I’ve wondered: imagine how much information I would be missing if they wrote those posts in French or Russian. Following their examples, this blog can also reach a much wider audience as well.

It probably happened more than once, when you ask your team about how a reverse proxy should talk to the application backend server. “Unix sockets. They are faster.”, they’ll say. But how much faster this communication will be? And why a Unix domain socket is faster than an IP socket when multiple processes are talking to each other in the same machine? Before answering those questions, we should figure what Unix sockets really are.

Unix sockets are a form of inter-process communication (IPC) that allows data exchange between processes in the same machine. They are special files, in the sense that they exist in a file system like a regular file (hence, have an inode and metadata like ownership and permissions associated to it), but will be read and written using recv() and send() syscalls instead of read() and write(). When binding and connecting to a Unix socket, we’ll be using file paths instead of IP addresses and ports.

In order to determine how fast a Unix socket is compared to an IP socket, two proofs of concept (POCs) will be used. They were written in Python, due to being small and easy to understand. Their implementation details will be clarified when needed.

IP POC

ip_server.py

#!/usr/bin/env python

import socket

server_addr = '127.0.0.1'
server_port = 5000

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((server_addr, server_port))
sock.listen(0)

print 'Server ready.'

while True:
    conn, _ = sock.accept()
    conn.send('Hello there!')
    conn.close()

ip_client.py

#!/usr/bin/env python

import socket
import time

server_addr = '127.0.0.1'
server_port = 5000

duration = 1
end = time.time() + duration
msgs = 0

print 'Receiving messages...'

while time.time() < end:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((server_addr, server_port))
    data = sock.recv(32)
    msgs += 1
    sock.close()

print 'Received {} messages in {} second(s).'.format(msgs, duration)

Unix domain socket POC

uds_server.py

#!/usr/bin/env python

import os
import socket

server_addr = '/tmp/uds_server.sock'

if os.path.exists(server_addr):
    os.unlink(server_addr)

sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
sock.bind(server_addr)
sock.listen(0)

print 'Server ready.'

while True:
    conn, _ = sock.accept()
    conn.send('Hello there!')
    conn.close()

uds_client.py

#!/usr/bin/env python

import socket
import time

server_addr = '/tmp/uds_server.sock'

duration = 1
end = time.time() + duration
msgs = 0

print 'Receiving messages...'

while time.time() < end:
    sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
    sock.connect(server_addr)
    data = sock.recv(32)
    msgs += 1
    sock.close()

print 'Received {} messages in {} second(s).'.format(msgs, duration)

As we can see by those code snippets, both implementations are close to each other as possible. The differences between them are:

  • Their address family: socket.AF_INET (IP) and socket.AF_UNIX (Unix sockets).
  • To bind a process using socket.AF_UNIX, the socket file should be removed and created again if it already exists.
  • When using socket.AF_INET, the socket.SO_REUSEADDR flag have to be set in order to avoid socket.error: [Errno 98] Address already in use errors that may occur even when the socket is properly closed. This option tells the kernel to reuse the same port if there are connections in the TIME_WAIT state.

Both POCs were executed on a Core i3 laptop running Ubuntu 16.04 (Xenial) with stock kernel. There is no output at every loop iteration to avoid the huge performance penalty of writing to a screen. Let’s take a look at their performances.

IP POC

First terminal:

$ python ip_server.py
Server ready.

Second terminal:

$ python ip_client.py
Receiving messages...
Received 10159 messages in 1 second(s).

Unix domain socket POC

First terminal:

$ python uds_server.py
Server ready.

Second terminal:

$ python uds_client.py
Receiving messages...
Received 22067 messages in 1 second(s).

The Unix socket implementation can send and receive more than twice the number of messages, over the course of a second, when compared to the IP one. During multiple runs, this proportion is consistent, varying around 10% for more or less on both of them. Now that we figured their performance differences, let’s find out why Unix sockets are so much faster.

It’s important to notice that both IP and Unix socket implementations are using TCP (socket.SOCK_STREAM), so the answer isn’t related to how TCP performs in comparison to another transport protocol like UDP, for instance (see update 1). What happens is that when Unix sockets are used, the entire IP stack from the operating system will be bypassed. There will be no headers being added, checksums being calculated (see update 2), encapsulation and decapsulation of packets being done nor routing being performed. Although those tasks are performed really fast by the OS, there is still a visible difference when doing benchmarks like this one.

There’s so much room for real-world comparisons besides this synthetic measurement demonstrated here. What will be the throughput differences when a reverse proxy like nginx is communicating to a Gunicorn backend server using IP or Unix sockets? Will it impact on latency as well? What about transfering big chunks of data, like huge binary files, instead of small messages? Can Unix sockets be used to avoid Docker network overhead when forwarding ports from the host to a container?

References:

Updates:

  1. John-Mark Gurney and Justin Cormack pointed out that SOCK_STREAM doesn’t mean TCP under Unix domain sockets. This makes sense, but I couldn’t find any reference affirming nor denying it.
  2. Justin Cormack also mentioned that there’s no checksumming on local interfaces by default. Looking at the source code of the Linux loopback driver, this seems to be present in kernel since version 2.6.12-r2.

与[转帖]How fast are Unix domain sockets?相似的内容:

[转帖]How fast are Unix domain sockets?

https://blog.myhro.info/2017/01/how-fast-are-unix-domain-sockets Jan 3, 2017 • Tiago Ilieve Warning: this is my first post written in English, after o

[转帖]How long does it take to make a context switch?

https://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html That's a interesting question I'm willing to spend some of my time on. So

[转帖]acme How to issue a cert

https://github.com/acmesh-official/acme.sh/wiki/How-to-issue-a-cert 1. Single domain: 1) Webroot mode: If you already have a web server running, you s

[转帖]让 CPU 告诉你硬盘和网络到底有多慢

https://cizixs.com/2017/01/03/how-slow-is-disk-and-network/ 简介 经常听到有人说磁盘很慢、网络很卡,这都是站在人类的感知维度去表述的,比如拷贝一个文件到硬盘需要几分钟到几十分钟,够我去吃个饭啦;而从网络下载一部电影,有时候需要几个小时,我都

[转帖][译] 如何基于 Cilium 和 eBPF 打造可感知微服务的 Linux(InfoQ, 2019)

http://arthurchiao.art/blog/how-to-make-linux-microservice-aware-with-cilium-zh/ 译者序 本文内容来自 2019 年的一个技术分享 How to Make Linux Microservice-Aware with Ci

[转帖][译] strace 是如何工作的(2016)

http://arthurchiao.art/blog/how-does-strace-work-zh/ 译者序 本文翻译自 2016 年的一篇英文博客 How Does strace Work 。如果能看懂英文,我建议你阅读原文,或者和本文对照看。 阅读本文之前,强烈建议先阅读这篇之前的文章: (

[转帖][译] ltrace 是如何工作的(2016)

http://arthurchiao.art/blog/how-does-ltrace-work-zh/ 译者序 本文翻译自 2016 年的一篇英文博客 How Does ltrace Work 。如果能看懂英文,我建议你阅读原文,或者和本文对照看。 阅读本文之前,强烈建议先阅读下面几篇之前的文章:

[转帖]Netflix 如何在 7 分钟内完成故障转移

https://www.oschina.net/translate/how-netflix-does-failovers-7-minutes-flat?print 在冬季2012年,Netflix公司遭受了 长时间断电 持续了七个小时,由于在美东地区的AWS弹性负载均衡服务的问题。(Netflix的

[转帖]Linux禁用CPU省电状态/Linux系统性能调优

https://www.jianshu.com/p/945168b47487 How to Disable CPU Power Saving States on a Redhat or Suse Linux System For RedHat Linux (release 7 and later)

[转帖]wmic命令介绍

https://www.jianshu.com/p/3e1a5a8fa23b How to Get Your System Serial Number PS C:\windows\system32> wmic bios get serialnumber SerialNumber SN-1 How t