0

I am working with a an array of 5 character strings. And joining the items into one large string. x is the array and looks like this:

val x : System.String [] =
  [|"W0SPFR"; "1BUDJY"; "1L1RJV"; "ITBPFA"; "QVUS7N"; "CJ6ZMQ"; "V3HUQ5";
    "694L4U"; "8RYWPF"; "YGWS8U"; "3KEKA9"; "1C9L6Q"; "OXCGSF"; "GF0CUQ";
    "YR41AF"; "4D4U0G"; "1U94T1"; "VUVJI0"; "CTYQL3"; "310XVU"; ...|]

My initial attempt was this:

let y = x |> Array.reduce (fun x y -> x+"-"+y)

Unfortunately this turned out to be slow, even for moderately sized arrays (10,000 elements). I'm looking to scale this up to millions.

Real: 00:00:00.483, CPU: 00:00:00.577, GC gen0: 167, gen1: 6, gen2: 5

My second attempt was better:

open System.Text  

let buf = new System.Text.StringBuilder()
let z = x |> Array.fold (fun (buf:StringBuilder) x -> buf.Append(x+"-")) buf |> string
z.[0..(z |> Seq.length)-2] = y

Question1:

Is StringBuilder the fastest way to build this large string?
I'm also open to parallelizing it.

Question2:

Because I use fold in the second attempt, a - is being joined to the last item, hence I'm getiing rid of it with z.[0..(z |> Seq.length)-2].
Is there a more elegant way?

Guy Coder
  • 22,011
  • 6
  • 54
  • 113
s952163
  • 6,134
  • 4
  • 21
  • 44
  • 2
    String concatenation is *always* slower than using StringBuilder since it allocates another temporary string. What you are trying to do though, is a plain String.Join(). There's no reason to reinvent this functionality (which btw uses StrinbBuilder) – Panagiotis Kanavos Apr 20 '16 at 11:50
  • 2
    Yes, String.Join in this case will perform better. See: http://stackoverflow.com/questions/585860/string-join-vs-stringbuilder-which-is-faster – Petr Apr 20 '16 at 11:51
  • 1
    If you check [the source of String.Join](http://referencesource.microsoft.com/#mscorlib/system/string.cs,204) you'll see that it uses an internal method for fast allocation and precalculates the buffer size of the StringBuilder, so it doesn't have to reallocate the buffer. That's hard to beat from a performance standpoint – Panagiotis Kanavos Apr 20 '16 at 11:53
  • 2
    https://ericlippert.com/2012/12/17/performance-rant – Mark Seemann Apr 20 '16 at 12:13
  • 1
    As it was mentioned in the other comment, you should probably use [String.Join](https://msdn.microsoft.com/en-us/library/57a79xd0(v=vs.110).aspx) method. AD1: StringBuilder will always be faster if you concatenate a couple of strings; if you know the length of a result you can specify StringBuilder's capacity using appropriate [constructor](https://msdn.microsoft.com/en-us/library/h1h0a5sy(v=vs.110).aspx) AD2: you can use [Array.reduce](https://msdn.microsoft.com/en-us/library/ee340509.aspx) to avoid the last append Additional note: your code creates unnecessary strings in: x+"-" – Tomasz Maczyński Apr 20 '16 at 12:30
  • I totally forgot about String.Join. Thx. Will test. @TomaszMaczyński I thought reduce will not allow using stringbuilder buffer and string. What do you mean by unnecessary strings? – s952163 Apr 20 '16 at 13:33
  • 1
    @s952163 ad1) you are right, I've oversimplified it. ad2) buf.Append(x+"-") creates one unnecesary string, you can use buf.Append(x).Append("-") instead – Tomasz Maczyński Apr 20 '16 at 13:52
  • @TomaszMaczyński Got it! And Very much appreciated. How would've thought that joining strings is such a deep subject.... – s952163 Apr 20 '16 at 14:07

0 Answers0