td-agentのprofiling - wyukawa’s blog
に書いたようにfluent-plugin-uri_decoderが重いということまではわかりました。
じゃあどうすっかという話なのですが、内部で議論がありRuby 2.4 + CGI.unescape + fluentd filterでいけばいいんじゃね?ということになりやってみました。
sonots先生も言ってるし背中を押されました。
便利そう(ステマ)というのと、URI.decode は obsolete ですね、というのと CGI.unescape なら新しめの ruby で高速化されてるはず、というのと / “td-agentのprofiling - w…” https://t.co/t6R2sTgvWR
— そのっつ (Naotoshi Seo) (@sonots) 2017年6月8日
Ruby 2.4 + CGI.unescapeでの高速化の元ネタはこの辺ぽい。
https://github.com/ruby/ruby/commit/d463c492bc983b0ac1f6e760695b3739767dd668#diff-94952cbdbe387aefd1bb19c8a4684a33
https://github.com/ruby/ruby/pull/1250
あとfluent-plugin-uri_decoderはoutput pluginなのですが、filterにほうがいいでしょうと。
でも
https://github.com/yasuoza/fluent-plugin-uri_decoder/pull/5
はfluentd 0.14ベース
別プラグインの
https://github.com/MerlinDMC/fluent-plugin-filter-urldecode
もfluentd 0.14ベース
ということで
https://github.com/yasuoza/fluent-plugin-uri_decoder
をforkしてpatchしたものを使いました。
https://github.com/wyukawa/fluent-plugin-uri_decoder/commit/c1348009df58734d22943973686d7fb12a58e268
結果として日中時間帯の非ピーク時でCPU使用率が約55%から約25%ぐらいまで下がりました。
秒間1000msgぐらいのはずなのでそれでもちょっと高い気はしますが、だいぶ改善されました。
Ruby 2.4 + CGI.unescape + fluentd filter後のstackprofはこんな感じです。
$ stackprof /tmp/fluent-stackprof.dump_fluentd --text
==================================
Mode: cpu(1000)
Samples: 15383 (0.06% miss rate)
GC: 1133 (7.37%)
==================================
TOTAL (pct) SAMPLES (pct) FRAME
5553 (36.1%) 1881 (12.2%) Fluent::TextParser::LabeledTSVParser#parse
3711 (24.1%) 1856 (12.1%) Fluent::URIDecoderFilter#filter
14213 (92.4%) 1215 (7.9%) Coolio::Loop#run
2166 (14.1%) 857 (5.6%) Fluent::TextParser::ValuesParser#values_map
825 (5.4%) 825 (5.4%) Fluent::ParserFilter#handle_parsed
800 (5.2%) 800 (5.2%) Yajl::Parser.parse
1538 (10.0%) 778 (5.1%) Fluent::GeoIP#geolocate
12791 (83.2%) 721 (4.7%) Fluent::NewTailInput::TailWatcher::IOHandler#on_notify
3040 (19.8%) 675 (4.4%) Fluent::GeoIP#add_geoip_field
1302 (8.5%) 653 (4.2%) Fluent::GeoIP#create_placeholder
541 (3.5%) 541 (3.5%) Fluent::NewTailInput::FilePositionEntry#update_pos
995 (6.5%) 436 (2.8%) Fluent::EventStream#to_msgpack_stream
319 (2.1%) 319 (2.1%) Fluent::TextParser::ValuesParser#convert_value_to_nil
292 (1.9%) 292 (1.9%) Fluent::MultiEventStream#initialize
277 (1.8%) 277 (1.8%) Fluent::NewTailInput::TailWatcher::RotateHandler#on_notify
354 (2.3%) 253 (1.6%) Fluent::TextParser::TypeConverter#convert_type
169 (1.1%) 169 (1.1%) Fluent::EngineClass::DummyMessagePackFactory#packer
4811 (31.3%) 165 (1.1%) Fluent::ParserFilter#filter_stream
288 (1.9%) 146 (0.9%) Fluent::GeoIP#get_address
128 (0.8%) 128 (0.8%) Fluent::MemoryBufferChunk#<<
3822 (24.8%) 116 (0.8%) Fluent::NewTailInput#convert_line_to_event
917 (6.0%) 109 (0.7%) Fluent::TextParser::ValuesParser#convert_field_type!
101 (0.7%) 101 (0.7%) block in <module:TypeConverter>
91 (0.6%) 91 (0.6%) MonitorMixin#mon_enter
90 (0.6%) 90 (0.6%) Fluent::MultiEventStream#add
95 (0.6%) 88 (0.6%) Fluent::TextParser::TimeParser#parse
13113 (85.2%) 85 (0.6%) Fluent::MultiEventStream#each
1741 (11.3%) 80 (0.5%) Fluent::TextParser::JSONParser#parse
72 (0.5%) 72 (0.5%) Fluent::GeoIP#json?
57 (0.4%) 57 (0.4%) Fluent::EventRouter::MatchCache#get