From 5080f81770a593aff4451625bd025777fb7fe7d8 Mon Sep 17 00:00:00 2001 From: Shizuo Fujita Date: Wed, 8 Jan 2025 14:29:18 +0900 Subject: [PATCH] in_tail: fix slice length to reduce memory usage (#4760) **Which issue(s) this PR fixes**: Fixes # **What this PR does / why we need it**: `String#slice` will allocate redundant heap area internally if an incorrect length is specified. This PR might reduce the memory usage with `in_tail` plugin. * verify code ```ruby require 'bundler/inline' gemfile do source 'https://rubygems.org' gem 'benchmark-memory' end str = "a" * 10_000_000 split_point = 9_999_900 Benchmark.memory do |x| x.report("1") { str.slice(split_point, str.length) } x.report("2") { str.slice(split_point, str.length - split_point) } x.report("3") { str.slice(split_point..str.length) } end ``` * result ``` Calculating ------------------------------------- 1 10.000M memsize ( 10.000M retained) 2.000 objects ( 1.000 retained) 2.000 strings ( 1.000 retained) 2 40.000 memsize ( 0.000 retained) 1.000 objects ( 0.000 retained) 1.000 strings ( 0.000 retained) 3 80.000 memsize ( 0.000 retained) 2.000 objects ( 0.000 retained) 1.000 strings ( 0.000 retained) ``` The all cases will generate same String object. However, `1` case will use 10 MB heap area with above code. **Docs Changes**: **Release Note**: Signed-off-by: Shizuo Fujita --- lib/fluent/plugin/in_tail.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index 852f2723bd..703d9d01c1 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -1056,8 +1056,9 @@ def read_lines(lines) # Using freeze and slice is faster than slice! # See https://github.com/fluent/fluentd/pull/2527 @buffer.freeze - rbuf = @buffer.slice(0, idx + 1) - @buffer = @buffer.slice(idx + 1, @buffer.size) + slice_position = idx + 1 + rbuf = @buffer.slice(0, slice_position) + @buffer = @buffer.slice(slice_position, @buffer.size - slice_position) idx = @buffer.index(@eol) is_long_line = @max_line_size && (