共有メモリを用いたストリームの実験#
共有メモリは UDP などの通信プロトコルに比べて速いと聞くため、 共有メモリを用いた軽いストリームを実装して性能を確認した。
共有メモリを用いたストリーム#
今回、共有メモリを用いて以下のようなリングバッファによるストリームを cpp-shm-stream リポジトリ に用意した。
light_stream
: アトミック演算による wait free なリングバッファのストリームblocking_stream
: アトミック演算を主に用いつつ、 データの待機処理がビジーループなしで行えるように実装したリングバッファのストリーム
どちらも、リングバッファ用に
書き込み側のインデックス
読み込み側のインデックス
バッファのサイズ
バッファ
を共有メモリ上に共有する。
2 つのインデックスについてはアトミック演算を行うため、
共有メモリ上でもアトミック演算を行うことができる
Boost.Atomic ライブラリ
の boost::atomics::ipc_atomic
クラスを用いた。
比較の対象とした通信方法#
以下を対象に、通信時間の比較を行った。
共有メモリを用いたストリーム
UDP
UDP による通信の実装には Asio ライブラリを用いた。
IPv4 と IPv6 の UDP の両方を対象とした。
環境#
実験を行った環境は以下の通り。
CPU:Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
メモリ:16 GB
OS:Ubuntu 22.04
レイテンシの測定#
各通信方法とデータサイズ(32 byte, 1 KB, 32 kB, 1 MB)ごとに 10000 回往復の通信をし、データを送受信するのにかかる時間を箱ひげ図でプロットした。
Show code cell content
import typing
import msgpack
import pandas
def parse_data(filepath: str) -> pandas.DataFrame:
with open(filepath, mode="rb") as file:
raw_data = msgpack.load(file)
df: typing.Optional[pandas.DataFrame] = None
for measurement in raw_data["measurements"]:
if measurement["measurer_name"] != "Processing Time":
continue
protocol = measurement["case_name"]
data_size = measurement["params"]["size"]
time_list = measurement["durations"]["values"][0]
cur_df = pandas.DataFrame(
{
"protocol": [protocol] * len(time_list),
"data_size": [data_size] * len(time_list),
"time": time_list,
}
)
if df is None:
df = cur_df
else:
df = pandas.concat([df, cur_df])
assert df is not None
return df
Show code cell source
import pandas
import plotly.express as px
import plotly.graph_objects as go
bench_results = parse_data("shm_stream_result_20230414/ping_pong.data")
fig = px.box(
bench_results,
x="data_size",
y="time",
color="protocol",
log_y=True,
points=False,
labels = {
"data_size": "データサイズ [byte]",
"time": "レイテンシ [sec]",
"protocol": "通信方法",
},
title="レイテンシの測定結果",
)
fig.show(renderer="notebook_connected")
送信時間の測定#
各通信方法とデータサイズ(32 byte, 1 KB, 32 kB, 1 MB)ごとに 10000 回データを送信し、データの送信処理にかかる時間を箱ひげ図でプロットした。
Show code cell source
bench_results = parse_data("shm_stream_result_20230414/send_messages.data")
fig = px.box(
bench_results,
x="data_size",
y="time",
color="protocol",
log_y=True,
points=False,
labels = {
"data_size": "データサイズ [byte]",
"time": "送信時間 [sec]",
"protocol": "通信方法",
},
title="送信時間の測定結果",
)
fig.show(renderer="notebook_connected")
比較#
共有メモリを用いた通信はどちらも UDP より速くなっている。
IPv4 と IPv6 の UDP の両方を試したが、 IPv4 と IPv6 では特に差が見受けられなかった。
共有メモリを用いた通信 2 種類では、 アトミック演算のみを使用した
light_stream
の方が速い。light_stream
ではデータの待機処理にビジーループを用いているため比較的負荷はかかるが、 代わりに速度は速くなった。
ソースコードなど#
実験は
cpp-shm-stream リポジトリ
のコミット
fa8c023d51fcf9ac9f398a11c7e548fc0539255a
上で Release ビルドを行い、
以下のコマンドを実行することで行った。
./build/Release/bin/bench_send_messages --msgpack send_messages.data --samples 10000
python3 ./tests/bench/ping_pong/bench.py build/Release/