|
import os |
|
import socket |
|
import time |
|
import struct |
|
from multiprocessing import Process |
|
|
|
socket_path = "/tmp/ipc_benchmark_socket" |
|
|
|
def run_server(): |
|
if os.path.exists(socket_path): |
|
os.remove(socket_path) |
|
server = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) |
|
server.bind(socket_path) |
|
|
|
# Set the buffer size just large enough for our message |
|
server.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 128 * 1024) |
|
|
|
# Wait for a message |
|
latencies = [] |
|
for i in range(10): |
|
data, _ = server.recvfrom(128 * 1024) # Buffer size for the payload and the timestamp |
|
received_time = time.time_ns() |
|
|
|
# Extract and print latency |
|
sent_time = struct.unpack("Q", data[:8])[0] # Extract the first 8 bytes for the timestamp |
|
latency_ns = received_time - sent_time |
|
|
|
# convert ns to ms |
|
latency_ms = latency_ns / 1000000 |
|
latencies.append(latency_ms) |
|
|
|
mean_latency = sum(latencies) / len(latencies) |
|
range_latency = max(latencies) - min(latencies) |
|
print(f"IPC Latency for under 128kB message: {mean_latency:.2f} ms +/- {range_latency/2:.2f}ms") |
|
|
|
server.close() |
|
|
|
def run_client(): |
|
# We allow some time for the server to start up and set its socket options |
|
time.sleep(0.1) |
|
client = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) |
|
|
|
# Match the server's set buffer size |
|
client.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 128 * 1024) |
|
|
|
try: |
|
# Create a payload that uses the maximum size |
|
payload_size = 128 * 1024 - 8 # 212992 (max message size) - 8 (size of timestamp) |
|
payload = b'a' * payload_size # Prepare the payload |
|
for i in range(10): |
|
sent_time = time.time_ns() |
|
message = struct.pack("Q", sent_time) + payload # Prefix with the timestamp |
|
client.sendto(message, socket_path) |
|
finally: |
|
client.close() |
|
|
|
if __name__ == "__main__": |
|
# Create and start server process |
|
server_process = Process(target=run_server) |
|
server_process.start() |
|
|
|
# Run client in the main process |
|
run_client() |
|
|
|
# Wait for the server process to finish |
|
server_process.join() |
|
|
|
# Clean up |
|
if os.path.exists(socket_path): |
|
os.remove(socket_path) |