C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML
Tip: Looking in IL Disassembler, Remove calls into Substring. So these custom methods directly call Substring.
RemoveIL DisassemblerTruncate: If the source is longer than the max length, we call Substring to get the first N characters. This copies the string.
Truncate2: Use a nested Math.Min expression in a Substring call. In this method, the Substring method is always entered.
Math.Max, MinInfo: By always entering the Substring method, we may create string copies that are not needed.
C# program that truncates strings
using System;
class Program
{
static void Main()
{
Console.WriteLine(StringTool.Truncate("Carrot", 3));
Console.WriteLine(StringTool.Truncate2("Carrot", 3));
Console.WriteLine(StringTool.Truncate("Wagstaff", 20));
Console.WriteLine(StringTool.Truncate2("Wagstaff", 20));
}
}
/// <summary>
/// Custom string utility methods.
/// </summary>
public static class StringTool
{
/// <summary>
/// Get a substring of the first N characters.
/// </summary>
public static string Truncate(string source, int length)
{
if (source.Length > length)
{
source = source.Substring(0, length);
}
return source;
}
/// <summary>
/// Get a substring of the first N characters. [Slow]
/// </summary>
public static string Truncate2(string source, int length)
{
return source.Substring(0, Math.Min(length, source.Length));
}
}
Output
Car
Car
Wagstaff
Wagstaff
Version 1: This code calls Truncate, which uses an if-statement to avoid calling Substring if the truncation does not need to occur.
BenchmarkVersion 2: This code always uses substring, but uses Math.Min to ensure we do not take a substring that is too long.
Result: Truncate, which avoids calling Substring(), is faster. It avoids a string method call in the benchmark.
C# program that benchmarks Truncate, Truncate2
using System;
using System.Diagnostics;
class Program
{
public static class StringTool
{
public static string Truncate(string source, int length)
{
if (source.Length > length)
{
source = source.Substring(0, length);
}
return source;
}
public static string Truncate2(string source, int length)
{
return source.Substring(0, Math.Min(length, source.Length));
}
}
const int _max = 100000000;
static void Main()
{
var s1 = Stopwatch.StartNew();
// Version 1: use Truncate.
for (int i = 0; i < _max; i++)
{
string a = StringTool.Truncate("Carrot", 3);
string b = StringTool.Truncate("Carrot", 10);
}
s1.Stop();
// Version 2: use Truncate2.
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
string a = StringTool.Truncate2("Carrot", 3);
string b = StringTool.Truncate2("Carrot", 10);
}
s2.Stop();
Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
}
}
Output
14.18 ns Truncate
15.28 ns Truncate2