Skip to content

Commit 520d137

Browse files
authored
replace regex to escape special chars with simple binary comprehension (#121)
Running regex (especially three times in a row) is much more expensive that a binary comprehension. This makes little difference for small data sets, for anything beyond a few hundred items it becomes measurable. Data sets beyond a few thousand items are completely unusable without this change.
1 parent 69f4439 commit 520d137

File tree

2 files changed

+35
-17
lines changed

2 files changed

+35
-17
lines changed

src/formats/prometheus_text_format.erl

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,6 @@
4040
%% Macros
4141
%%====================================================================
4242

43-
-define(ESCAPE_LVALUE(Value),
44-
sub(sub(sub(Value, "\\", "\\\\\\\\"), "\n", "\\\\n"), "\"", "\\\\\"")).
45-
4643
%%====================================================================
4744
%% Format API
4845
%%====================================================================
@@ -156,33 +153,54 @@ labels_string(Labels) ->
156153
emit_series(Fd, Name, Labels, undefined) ->
157154
LString = labels_string(Labels),
158155
file:write(Fd, [Name, LString, " NaN\n"]);
156+
emit_series(Fd, Name, Labels, Value) when is_integer(Value) ->
157+
LString = labels_string(Labels),
158+
file:write(Fd, [Name, LString, " ", integer_to_list(Value) , "\n"]);
159159
emit_series(Fd, Name, Labels, Value) ->
160160
LString = labels_string(Labels),
161161
file:write(Fd, [Name, LString, " ", io_lib:format("~p", [Value]) , "\n"]).
162162

163163
%% @private
164164
escape_metric_help(Help) ->
165-
sub(sub(Help, "\\", "\\\\\\\\"), "\n", "\\\\n").
165+
escape_string(fun escape_help_char/1, Help).
166166

167-
bound_to_label_value(Bound) when is_number(Bound) ->
168-
io_lib:format("~p", [Bound]);
167+
%% @private
168+
escape_help_char($\\ = X) ->
169+
<<X, X>>;
170+
escape_help_char($\n) ->
171+
<<$\\, $n>>;
172+
escape_help_char(X) ->
173+
<<X>>.
174+
175+
bound_to_label_value(Bound) when is_integer(Bound) ->
176+
integer_to_list(Bound);
177+
bound_to_label_value(Bound) when is_float(Bound) ->
178+
float_to_list(Bound);
169179
bound_to_label_value(infinity) ->
170180
"+Inf".
171181

172-
-spec escape_label_value(binary() | iolist() | undefined) -> string().
182+
-spec escape_label_value(binary() | iolist() | undefined) -> binary().
173183
%% @private
174-
escape_label_value(LValue) when is_list(LValue)->
175-
?ESCAPE_LVALUE(LValue);
176-
escape_label_value(LValue) when is_binary(LValue) ->
177-
?ESCAPE_LVALUE(LValue);
184+
escape_label_value(LValue) when is_list(LValue); is_binary(LValue) ->
185+
escape_string(fun escape_label_char/1, LValue);
178186
escape_label_value(Value) ->
179187
erlang:error({wtf, Value}).
180188

189+
%% @private
190+
escape_label_char($\\ = X) ->
191+
<<X, X>>;
192+
escape_label_char($\n) ->
193+
<<$\\, $n>>;
194+
escape_label_char($" = X) ->
195+
<<$\\, X>>;
196+
escape_label_char(X) ->
197+
<<X>>.
181198

182-
-spec sub(iodata(), string(), string()) -> string().
183-
sub(Str, Old, New) ->
184-
RegExp = "\\Q" ++ Old ++ "\\E",
185-
re:replace(Str, RegExp, New, [global, {return, list}]).
199+
%% @private
200+
escape_string(Fun, Str) when is_binary(Str) ->
201+
<< <<(Fun(X))/binary>> || <<X:8>> <= Str >>;
202+
escape_string(Fun, Str) ->
203+
escape_string(Fun, iolist_to_binary(Str)).
186204

187205
%%
188206
%% %CopyrightBegin%

test/eunit/format/prometheus_text_format_tests.erl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ create_untyped(Name, Help) ->
2121
prometheus_model_helpers:create_mf(Name, Help, untyped, ?MODULE, undefined).
2222

2323
escape_metric_help_test() ->
24-
?assertEqual("qwe\\\\qwe\\nqwe",
24+
?assertEqual(<<"qwe\\\\qwe\\nqwe">>,
2525
prometheus_text_format:escape_metric_help("qwe\\qwe\nqwe")).
2626

2727
escape_label_value_test()->
28-
?assertEqual("qwe\\\\qwe\\nq\\\"we\\\"qwe",
28+
?assertEqual(<<"qwe\\\\qwe\\nq\\\"we\\\"qwe">>,
2929
prometheus_text_format:escape_label_value("qwe\\qwe\nq\"we\"qwe")).
3030

3131
prometheus_format_test_() ->

0 commit comments

Comments
 (0)