[m-rev.] for review: Avoid memory allocation for common string to int conversions.

Peter Wang novalazy at gmail.com
Mon Jun 20 14:07:55 AEST 2016


It might only be worth doing this for decimal and hexadecimal.
Octal and binary are not really very common.
---

library/string.m:
	Make base_string_to_int pass a constant higher order term
	to string.foldl_between for common bases 10, 16, 8, 2.
---
 library/string.m | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/library/string.m b/library/string.m
index 023ff29..55ef8b3 100644
--- a/library/string.m
+++ b/library/string.m
@@ -5173,12 +5173,12 @@ base_string_to_int(Base, String, Int) :-
     End = count_code_units(String),
     ( if Char = ('-') then
         End > 1,
-        foldl_between(accumulate_negative_int(Base), String, 1, End, 0, Int)
+        foldl_between(base_negative_accumulator(Base), String, 1, End, 0, Int)
     else if Char = ('+') then
         End > 1,
-        foldl_between(accumulate_int(Base), String, 1, End, 0, Int)
+        foldl_between(base_accumulator(Base), String, 1, End, 0, Int)
     else
-        foldl_between(accumulate_int(Base), String, 0, End, 0, Int)
+        foldl_between(base_accumulator(Base), String, 0, End, 0, Int)
     ).
 
 det_base_string_to_int(Base, S) = N :-
@@ -5188,6 +5188,23 @@ det_base_string_to_int(Base, S) = N :-
         unexpected($pred, "conversion failed")
     ).
 
+:- func base_accumulator(int) = pred(char, int, int).
+:- mode base_accumulator(in) = out(pred(in, in, out) is semidet) is det.
+
+base_accumulator(Base) = Pred :-
+    % Avoid allocating a closure for the common bases.
+    ( if Base = 10 then
+        Pred = accumulate_int(10)
+    else if Base = 16 then
+        Pred = accumulate_int(16)
+    else if Base = 8 then
+        Pred = accumulate_int(8)
+    else if Base = 2 then
+        Pred = accumulate_int(2)
+    else
+        Pred = accumulate_int(Base)
+    ).
+
 :- pred accumulate_int(int::in, char::in, int::in, int::out) is semidet.
 
 accumulate_int(Base, Char, N0, N) :-
@@ -5197,6 +5214,24 @@ accumulate_int(Base, Char, N0, N) :-
     % XXX depends on undefined behaviour
     N0 =< N.
 
+:- func base_negative_accumulator(int) = pred(char, int, int).
+:- mode base_negative_accumulator(in) = out(pred(in, in, out) is semidet)
+    is det.
+
+base_negative_accumulator(Base) = Pred :-
+    % Avoid allocating a closure for the common bases.
+    ( if Base = 10 then
+        Pred = accumulate_negative_int(10)
+    else if Base = 16 then
+        Pred = accumulate_negative_int(16)
+    else if Base = 8 then
+        Pred = accumulate_negative_int(8)
+    else if Base = 2 then
+        Pred = accumulate_negative_int(2)
+    else
+        Pred = accumulate_negative_int(Base)
+    ).
+
 :- pred accumulate_negative_int(int::in, char::in,
     int::in, int::out) is semidet.
 
-- 
2.6.4



More information about the reviews mailing list