From d5e81346c955a4f54cb9efa47070ff8dad6d93fe Mon Sep 17 00:00:00 2001 From: Vladimir Kochnev Date: Thu, 4 Jul 2024 17:23:35 +0300 Subject: [PATCH] Avoid dynamic parse method dispatch for faster access --- benchmark/convert_nil.yaml | 2 ++ benchmark/parse.yaml | 2 ++ benchmark/parse_liberal_parsing.yaml | 2 ++ benchmark/parse_quote_char_nil.yaml | 2 ++ benchmark/parse_strip.yaml | 2 ++ benchmark/read.yaml | 2 ++ benchmark/shift.yaml | 2 ++ benchmark/write.yaml | 2 ++ lib/csv/parser.rb | 23 ++++++++++------------- 9 files changed, 26 insertions(+), 13 deletions(-) diff --git a/benchmark/convert_nil.yaml b/benchmark/convert_nil.yaml index f32c6f10..76613806 100644 --- a/benchmark/convert_nil.yaml +++ b/benchmark/convert_nil.yaml @@ -4,6 +4,8 @@ contexts: csv: 3.0.1 - gems: csv: 3.0.2 + - gems: + csv: 3.3.0 - name: "master" prelude: | $LOAD_PATH.unshift(File.expand_path("lib")) diff --git a/benchmark/parse.yaml b/benchmark/parse.yaml index 25ccaf24..4289995f 100644 --- a/benchmark/parse.yaml +++ b/benchmark/parse.yaml @@ -4,6 +4,8 @@ contexts: csv: 3.0.1 - gems: csv: 3.0.2 + - gems: + csv: 3.3.0 - name: "master" prelude: | $LOAD_PATH.unshift(File.expand_path("lib")) diff --git a/benchmark/parse_liberal_parsing.yaml b/benchmark/parse_liberal_parsing.yaml index dcbf5985..41307e11 100644 --- a/benchmark/parse_liberal_parsing.yaml +++ b/benchmark/parse_liberal_parsing.yaml @@ -2,6 +2,8 @@ loop_count: 100 contexts: - gems: csv: 3.0.2 + - gems: + csv: 3.3.0 - name: "master" prelude: | $LOAD_PATH.unshift(File.expand_path("lib")) diff --git a/benchmark/parse_quote_char_nil.yaml b/benchmark/parse_quote_char_nil.yaml index f92fd33b..f9cb8283 100644 --- a/benchmark/parse_quote_char_nil.yaml +++ b/benchmark/parse_quote_char_nil.yaml @@ -1,5 +1,7 @@ loop_count: 100 contexts: + - gems: + csv: 3.3.0 - name: "master" prelude: | $LOAD_PATH.unshift(File.expand_path("lib")) diff --git a/benchmark/parse_strip.yaml b/benchmark/parse_strip.yaml index a0230fd1..fe9dbeaa 100644 --- a/benchmark/parse_strip.yaml +++ b/benchmark/parse_strip.yaml @@ -1,5 +1,7 @@ loop_count: 100 contexts: + - gems: + csv: 3.3.0 - name: "master" prelude: | $LOAD_PATH.unshift(File.expand_path("lib")) diff --git a/benchmark/read.yaml b/benchmark/read.yaml index b06dbe16..15fc26f5 100644 --- a/benchmark/read.yaml +++ b/benchmark/read.yaml @@ -4,6 +4,8 @@ contexts: csv: 3.0.1 - gems: csv: 3.0.2 + - gems: + csv: 3.3.0 - name: "master" prelude: | $LOAD_PATH.unshift(File.expand_path("lib")) diff --git a/benchmark/shift.yaml b/benchmark/shift.yaml index eb6fd80e..8011a4fa 100644 --- a/benchmark/shift.yaml +++ b/benchmark/shift.yaml @@ -4,6 +4,8 @@ contexts: csv: 3.0.1 - gems: csv: 3.0.2 + - gems: + csv: 3.3.0 - name: "master" prelude: | $LOAD_PATH.unshift(File.expand_path("lib")) diff --git a/benchmark/write.yaml b/benchmark/write.yaml index 5b7d1943..019927c2 100644 --- a/benchmark/write.yaml +++ b/benchmark/write.yaml @@ -4,6 +4,8 @@ contexts: csv: 3.0.1 - gems: csv: 3.0.2 + - gems: + csv: 3.3.0 - name: "master" prelude: | $LOAD_PATH.unshift(File.expand_path("lib")) diff --git a/lib/csv/parser.rb b/lib/csv/parser.rb index d7fcd10e..eda820b7 100644 --- a/lib/csv/parser.rb +++ b/lib/csv/parser.rb @@ -409,13 +409,7 @@ def parse(&block) begin @scanner ||= build_scanner - if quote_character.nil? - parse_no_quote(&block) - elsif @need_robust_parsing - parse_quotable_robust(&block) - else - parse_quotable_loose(&block) - end + __send__(@parse_method, &block) rescue InvalidEncoding if @scanner ignore_broken_line @@ -459,7 +453,6 @@ def prepare end def prepare_variable - @need_robust_parsing = false @encoding = @options[:encoding] liberal_parsing = @options[:liberal_parsing] if liberal_parsing @@ -472,7 +465,6 @@ def prepare_variable @double_quote_outside_quote = false @backslash_quote = false end - @need_robust_parsing = true else @liberal_parsing = false @backslash_quote = false @@ -554,7 +546,6 @@ def prepare_strip @rstrip_value = Regexp.new(@escaped_strip + "+\\z".encode(@encoding)) end - @need_robust_parsing = true elsif @strip strip_values = " \t\f\v" @escaped_strip = strip_values.encode(@encoding) @@ -562,7 +553,6 @@ def prepare_strip @strip_value = Regexp.new("[#{strip_values}]+".encode(@encoding)) @rstrip_value = Regexp.new("[#{strip_values}]+\\z".encode(@encoding)) end - @need_robust_parsing = true end end @@ -808,6 +798,13 @@ def adjust_headers(headers, quoted_fields) def prepare_parser @may_quoted = may_quoted? + if @quote_character.nil? + @parse_method = :parse_no_quote + elsif @liberal_parsing or @strip + @parse_method = :parse_quotable_robust + else + @parse_method = :parse_quotable_loose + end end def may_quoted? @@ -987,7 +984,7 @@ def parse_quotable_loose(&block) quoted_fields = [] elsif line.include?(@cr) or line.include?(@lf) @scanner.keep_back - @need_robust_parsing = true + @parse_method = :parse_quotable_robust return parse_quotable_robust(&block) else row = line.split(@split_column_separator, -1) @@ -1011,7 +1008,7 @@ def parse_quotable_loose(&block) row[i] = column[1..-2] else @scanner.keep_back - @need_robust_parsing = true + @parse_method = :parse_quotable_robust return parse_quotable_robust(&block) end validate_field_size(row[i])