fluent-plugin-uri_decoderをpatchしてCPU使用率を下げた話

td-agentのprofiling - wyukawa’s blog
に書いたようにfluent-plugin-uri_decoderが重いということまではわかりました。

じゃあどうすっかという話なのですが、内部で議論がありRuby 2.4 + CGI.unescape + fluentd filterでいけばいいんじゃね?ということになりやってみました。


sonots先生も言ってるし背中を押されました。


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