您的位置:首页 > 其它

erlang序列化工具性能对比(erlang protobuf和term_to_binary对比)

2017-12-18 23:53 567 查看
公司内部最近做了一个性能测试,发现逻辑处理服务的加解包速度不行,于是做了简单的benchmark,比对了公司用的protobuf库和term_to_binary的性能差异。想看看性能如何。

测试的protobuf是basho的erlang_protobuffs ,挺旧的了,而且已经不再维护。

先贴测试结果,本测试在我的mac上,用fusion虚拟的1核2g的ubuntu12.04,erlang16R3,跑的结果还是蛮惊人的。

(elogic@johnzeng-virtual-machine)1> logic_worker:test_util().
Protobuffer encoding 1000000 cost time is :9.698853 , that's 103104.97540276154 msg per second
Protobuffer decoding 1000000 cost time is :16.459741 , that's 60754.29740966154 msg per second
binary_to_term 1000000 terms cost time is :1.75269 , that's 570551.5521854977 msg per second
term_to_binary 1000000 terms cost time is :0.017986000000000002 , that's 55598799.06594017 msg per second
mqtt decoding 1000000 bianry cost time is :1.5215139999999998 , that's 657240.0911197664 msg per second
mqtt encoding 1000000 bianry cost time is :1.3142470000000002 , that's 760891.9784484955 msg per second


这个代码非常简单,就是针对同一个protobuf的binary数据,跑100w次,测量时间,然后计算平均ops。可以看到protobuf的组包速度,比解包速度要快很多。超不多是0.8倍的差异。但是更加惊人的是term_to_binary的性能,是protobuf的20倍速度。公司已经决定后面要换用term_to_binary了23333。

后面一个是mqtt的包序列化和反序列化,这个如果不感兴趣可以不管。

最后附上代码。由于结构体属于公司内部文件,不能po上来,但是大概意思大家知道就行了。这个文章后面会陆续补上其他序列化工具的性能分析。

test_util() ->
test_util(1000000).
test_util(Time) ->
Package = <<8,132,194,194,224,10,16,219,14,24,0,32,0,42,9,108,111,99,97,108,104,111,115,116,48,19,56,128,170,250,188,164,143,206,146,43,66,23,48,48,48,48,48,48,51,51,50,56,45,48,48,48,48,48,48,48,54,48,52,50,53,74,32,48,30,0,16,121,98,116,101,115,116,95,116,111,111,108,95,116,101,115,116,72,101,108,108,111,87,111,114,108,100,52,50,82,24,53,54,97,48,97,56,56,99,52,52,48,55,97,51,99,100,48,50,56,97,99,50,102,101,114,6,49,50,51,52,53,54>>,
BeforeTest = erlang:now(),

DecodeResult = test_util_decode(Package, Time),

AfterTest = erlang:now(),

Diff = timer:now_diff(AfterTest, BeforeTest) / 1000 / 1000,

Average = Time / (Diff),

EncodeResult  = test_util_encode(DecodeResult, Time),

AfterEncodeTest = erlang:now(),

Diff1 = timer:now_diff(AfterEncodeTest, AfterTest) / 1000 / 1000,

Average1 = Time / (Diff1),

EncodeToTermResult  = test_util_encode_term(DecodeResult, Time),

AfterEncodeTest1 = erlang:now(),

Diff2 = timer:now_diff(AfterEncodeTest1, AfterEncodeTest) / 1000 / 1000,

Average2 = Time / (Diff2),

DecodeFromTermResult  = test_util_decode_term(EncodeToTermResult, Time),

AfterEncodeTest2 = erlang:now(),

Diff3 = timer:now_diff(AfterEncodeTest2, AfterEncodeTest1) / 1000 / 1000,

Average3 = Time / (Diff3),

MqttFrame = DecodeFromTermResult#internalpackage.mqtt_package,
ProtocolVersion = DecodeFromTermResult#internalpackage.protocol_version,

Frame = test_util_parse_mqtt_frame(MqttFrame, ProtocolVersion, Time),

AfterParseTest1 = erlang:now(),

Diff4 = timer:now_diff(AfterParseTest1, AfterEncodeTest2) / 1000 / 1000,

Average4 = Time / (Diff4),

RetFrame = test_util_parse_to_mqtt_frame(Frame, ProtocolVersion, Time),

AfterParseTest2 = erlang:now(),

Diff5 = timer:now_diff(AfterParseTest2, AfterParseTest1) / 1000 / 1000,

Average5 = Time / (Diff5),

io:format("Protobuffer encoding ~p cost time is :~p , that's ~p msg per second ~n", [Time, Diff1, Average1]),
io:format("Protobuffer decoding ~p cost time is :~p , that's ~p msg per second ~n", [Time, Diff, Average]),
io:format("binary_to_term ~p terms cost time is :~p , that's ~p msg per second ~n", [Time, Diff3, Average3]),
io:format("term_to_binary ~p terms cost time is :~p , that's ~p msg per second ~n", [Time, Diff2, Average2]),
io:format("mqtt decoding ~p bianry cost time is :~p , that's ~p msg per second ~n", [Time, Diff4, Average4]),
io:format("mqtt encoding ~p bianry cost time is :~p , that's ~p msg per second ~n", [Time, Diff5, Average5]).

test_util_parse_to_mqtt_frame(Package, Ver, 0) ->
emqtt_frame:serialise(Package, Ver);
test_util_parse_to_mqtt_frame(Package, Ver, Time) ->
emqtt_frame:serialise(Package, Ver),
test_util_parse_to_mqtt_frame(Package, Ver, Time - 1).

test_util_parse_mqtt_frame(Package, Ver, 0) ->
mqtt_package:parse_frame_simple(Package, Ver);
test_util_parse_mqtt_frame(Package, Ver, Time) ->
mqtt_package:parse_frame_simple(Package, Ver),
test_util_parse_mqtt_frame(Package, Ver, Time - 1).

test_util_encode_term(Package, 0) ->
term_to_binary(Package);
test_util_encode_term(Package, LeftTime) ->
term_to_binary(Package),
test_util_encode_term(Package, LeftTime - 1).

test_util_decode_term(Package, 0) ->
binary_to_term(Package);
test_util_decode_term(Package, LeftTime) ->
binary_to_term(Package),
test_util_decode_term(Package, LeftTime - 1).

test_util_encode(Package, 0) ->
InternalPackageRecord = internal_package_pb:encode_internalpackage(Package);
test_util_encode(Package, LeftTime) ->
InternalPackageRecord = internal_package_pb:encode_internalpackage(Package),
test_util_encode(Package, LeftTime - 1).

test_util_decode(Package, 0) ->
InternalPackageRecord = internal_package_pb:decode_internalpackage(Package);
test_util_decode(Package, LeftTime) ->
InternalPackageRecord = internal_package_pb:decode_internalpackage(Package),
test_util_decode(Package, LeftTime - 1).
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息