diff options
Diffstat (limited to 'community/ruby-eventmachine/improve-line_protocol-speed.patch')
-rw-r--r-- | community/ruby-eventmachine/improve-line_protocol-speed.patch | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/community/ruby-eventmachine/improve-line_protocol-speed.patch b/community/ruby-eventmachine/improve-line_protocol-speed.patch new file mode 100644 index 00000000000..638302c91e4 --- /dev/null +++ b/community/ruby-eventmachine/improve-line_protocol-speed.patch @@ -0,0 +1,70 @@ +Patch-Source: https://github.com/eventmachine/eventmachine/commit/10fb0c47c9a030b716dacd4a8df7e34b2445169b.patch +-- +From 10fb0c47c9a030b716dacd4a8df7e34b2445169b Mon Sep 17 00:00:00 2001 +From: Michel Boaventura <michel.boaventura@gmail.com> +Date: Tue, 20 Aug 2019 17:29:05 -0300 +Subject: [PATCH] Improve line_protocol speed (#894) + +I'm having problems with current line_protocol implementation, causing up to 60% of my overall run time to be spent slicing the message buffer. I've change it to use ``String#each_line`` instead of ``slice`` which proves to be 200x faster: + +```Ruby +require 'benchmark' + +def new_version(size) + buffer = Array.new(size, 'foo 123').join("\n") + + buffer.each_line do |line| + if line[-1] == "\n" + else + buffer = line + end + end +end + +def original(size) + buffer = Array.new(size, 'foo 123').join("\n") + + while buffer.slice!(/(.*?)\r?\n/) do + end +end + +Benchmark.bmbm do |x| + x.report('original') { original(100_000) } + x.report('new_version') { new_version(100_000) } +end +``` +``` +Rehearsal ----------------------------------------------- +original 4.891919 0.103960 4.995879 ( 4.993582) +new_version 0.026254 0.000005 0.026259 ( 0.026250) +-------------------------------------- total: 5.022138sec + + user system total real +original 4.922760 0.031001 4.953761 ( 4.951560) +new_version 0.026114 0.000000 0.026114 ( 0.026103) +``` + +The only downside is that ``each_line`` always returns the last part of the string, so ``"foo\nbar".each_line`` will yield both ``foo`` and ``bar``. To fix this I just use the fact that ``each_line`` actually returns the line terminators so, if I returns me a string without a new line I know the buffer has ended and the last "line" is the content of the new buffer. +--- + lib/em/protocols/line_protocol.rb | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/lib/em/protocols/line_protocol.rb b/lib/em/protocols/line_protocol.rb +index dfddae8c0..0bdef93a3 100644 +--- a/lib/em/protocols/line_protocol.rb ++++ b/lib/em/protocols/line_protocol.rb +@@ -15,8 +15,12 @@ module LineProtocol + def receive_data data + (@buf ||= '') << data + +- while @buf.slice!(/(.*?)\r?\n/) +- receive_line($1) ++ @buf.each_line do |line| ++ if line[-1] == "\n" ++ receive_line(line.chomp) ++ else ++ @buf = line ++ end + end + end + |