aboutsummaryrefslogtreecommitdiffstats
path: root/community/ruby-eventmachine/improve-line_protocol-speed.patch
diff options
context:
space:
mode:
Diffstat (limited to 'community/ruby-eventmachine/improve-line_protocol-speed.patch')
-rw-r--r--community/ruby-eventmachine/improve-line_protocol-speed.patch70
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
+