fluent-plugin-uri_decoderをpatchしてCPU使用率を下げた話
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