Skip to content

Commit 35aaad9

Browse files
abelbraaksmacartermp
authored andcommitted
String mapi ~2.5x perf improvement (v2) (#9482)
* Move `String.length` to the top of its module so that the `length` function is in scope * Using known length for mapping, and unrolling x2 to improve perf of String.mapi by 2.5x * Fix two unapparent errors in the unroll loop, fix nit on parens * Add String.mapi tests for all new unrolling corner cases, and some general ones * Add side-effect test, this would fail if sequentiality of String.mapi is broken * Remove "foo" from tests * Remove unrolling of loop in String.mapi Co-authored-by: Phillip Carter <pcarter@fastmail.com>
1 parent 8e276dd commit 35aaad9

1 file changed

Lines changed: 10 additions & 4 deletions

File tree

src/fsharp/FSharp.Core/string.fs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,19 @@ namespace Microsoft.FSharp.Core
7171

7272
[<CompiledName("MapIndexed")>]
7373
let mapi (mapping: int -> char -> char) (str:string) =
74-
if String.IsNullOrEmpty str then
74+
let len = length str
75+
if len = 0 then
7576
String.Empty
7677
else
77-
let res = StringBuilder str.Length
78+
let result = str.ToCharArray()
7879
let f = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(mapping)
79-
str |> iteri (fun i c -> res.Append(f.Invoke(i, c)) |> ignore)
80-
res.ToString()
80+
81+
let mutable i = 0
82+
while i < len do
83+
result.[i] <- f.Invoke(i, result.[i])
84+
i <- i + 1
85+
86+
new String(result)
8187

8288
[<CompiledName("Filter")>]
8389
let filter (predicate: char -> bool) (str:string) =

0 commit comments

Comments
 (0)