A few days ago I was with Frank Taglianetti (no links here, he doesn’t have a blog yet), a PFE from my team that I met for the first time at that day while doing a Lab for one of our customers. By Lab I mean stress testing and troubleshooting a customer’s application in our laboratory.

 

At some point we were reviewing a snippet of C# code that was the culprit for the slow performance. After reviewing it we started asking ourselves what would be a better approach: String.Replace(), RegEx.Replace() or StringBuilder.Replace().

We didn’t care about case-sensitivity because the application had to replace special characters.

 

Then the fun began…

At that point, without doing any tests, we guessed about which would be the best and worst Replace() call.

 

Frank was able to come up with a theory to justify his guess for the worst performer, and it proved to be right!

 

Whenever I mention a co-worker, I like to add some words about him or her. During the Lab I was impressed with Frank (we use to call him Tag, based on his last name); he is a great developer and a great debugger, proving something I use to say, that these two skills walk together. Besides, the guy has a lot of experience! It’s always a pleasure to work with people like him because I always learn something new!

 

Back to the Lab…to find the fastest way to replace a character with another character from a large string, I decided to use PowerShell to test the three approaches.

 

Below I present the scripts and the results… They are by no means full stress tests; however, they are useful to give us a baseline when processing large text files. You may be surprised with the results. We were!

 

Note: The tests don’t consider the regular expression syntax that is part of the PowerShell language, since it cannot be reused from VB.Net or C#.

If you are curious about it, just create another function that uses –match and –imatch.

 

RegEx.Replace()

 

 

 

 

 

 

StringBuilder.Replace()

 

 

 

 

String.Replace()

 

 

 

 

 

Source code for RegEx.Replace:

 

 

#########################################################

## This is a sample test to measure the performance of StringBuilder.Replace against

## RegEx.Replace

##

## RegEx.Replace is case insensitive!

#########################################################

param(

      [string] $fileName = $(throw "Error! You must provide the method name.")

     )

   

set-psdebug -strict

 

$ErrorActionPreference = "stop"

 

trap {"Error message: $_"}

 

write-Host "Starting RegEx.Replace..." -foreground Green -background Black

 

# Attention! If you use [string] $text, the variable is not going to be a generic Object, but System.String.

# Doing that the performance improves a lot, although it was not enough to beat String.Replace.

 

# Get file content.

$str = get-Content $fileName

   

# For testing purposes, let's repeat the operation "n" times. ((?<value>(\n)))

for($i = 0; $i -le 200; $i++)

{

    [regex]::Replace($str, "`n", "");

   

}

 

write-Host "End!" -foreground Green -background Black

 

 

 

Source code for StringBuilder.Replace:

 

#########################################################

## This is a sample test to measure the performance of StringBuilder.Replace against

## RegEx.Replace

##

## According to MSDN: The strings to replace are checked on an ordinal basis; that is,

## the replacement is not culture-aware. If newValue is a null reference

## (Nothing in Visual Basic), all occurrences of oldValue are removed. This method is case-sensitive.

#########################################################

param(

      [string] $fileName = $(throw "Error! You must provide the method name.")

     )

   

set-psdebug -strict

 

$ErrorActionPreference = "stop"

 

trap {"Error message: $_"}

 

write-Host "Starting StringBuilder.Replace..." -foreground Green -background Black

 

$builder       = New-Object System.Text.StringBuilder

$fileContent   = New-Object System.Text.StringBuilder

$value         = ""

 

# Assign the content to our local variable.

[System.String] $str = get-Content $fileName

 

$fileContent.Append($str)

   

# For testing purposes, let's repeat the operation "n" times.

for($i = 0; $i -le 200; $i++)

{  

    $builder = $fileContent.Replace("`n", "")       

}

 

write-Host "End!" -foreground Green -background Black

 

 

 

Source code for String.Replace:

 

#########################################################

## This is a sample test to measure the performance of StringBuilder.Replace against

## RegEx.Replace and String.Replace

##

## According to MSDN: The strings to replace are checked on an ordinal basis; that is,

## the replacement is not culture-aware. If newValue is a null reference

## (Nothing in Visual Basic), all occurrences of oldValue are removed. This method is case-sensitive.

#########################################################

param(

      [string] $fileName = $(throw "Error! You must provide the method name.")

     )

   

set-psdebug -strict

 

$ErrorActionPreference = "stop"

 

trap {"Error message: $_"}

 

write-Host "Starting String.Replace..." -foreground Green -background Black

 

[System.String] $builder = ""

[System.String] $fileContent = ""

$value = ""

 

# Assign the content to our local variable.

$fileContent = get-Content $fileName

   

# For testing purposes, let's repeat the operation "n" times.

for($i = 0; $i -le 200; $i++)

{  

    $builder = $fileContent.Replace("`n", "")

}

 

write-Host "End!" -foreground Green -background Black

 

 

 

 

From MSDN we have:

 

http://msdn2.microsoft.com/en-us/library/aa289509.aspx

 

Here’s another article that comes to the same conclusion:

 

http://www.codeproject.com/KB/cs/StringBuilder_vs_String.aspx?fid=326464&df=90&mpp=25&noise=3&sort=Position&view=Quick&fr=26

 

Based on this simple test, RegEx.Replace() has the worst performance and the award goes to…drum roll, please… String.Replace()!