
I was reading Tao Liu's post regarding enums with space for localization to save time and I just had to run a test if this really was faster then defining a lookup table?
On my computer
-------------------------------------- ... FsharpEnumToString vs. CSharpEnumDictionaryLookup FSharpToString Iterations: 10000000; Average: 0,287 ticks; Total: 14374450,000 ticks; CSharpLookup Iterations: 10000000; Average: 0,134 ticks; Total: 6688315,000 ticks;
So, a simple dictionary lookup is still faster then ToString of a F# enum.
So I'll guess my team will keep the localization as data files / database table that is loaded at runtime into a variable. This way we can outsource the translations to other teams and specialists while keeping the code clean. A misspelled enum member by a tired developer does not result in a hotfix of an application with new builds etc, just a data file update in runtime.
The code used to perform this test:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using fsharp.techdump;
namespace techdump.console.Tests
{
public class FsharpEnumToStringVsLookup
{
private Dictionary<CSharpEnum, string> _lookup = new Dictionary<CSharpEnum, string>
{
{ CSharpEnum.Registration, "Registration" },
{ CSharpEnum.UnderReview, "Under Review" },
{ CSharpEnum.Approval, "Approval" },
{ CSharpEnum.Release, "Release" },
{ CSharpEnum.PostRelase, "Post Release" }
};
private enum CSharpEnum
{
Registration = 0,
UnderReview = 1,
Approval = 2,
Release = 3,
PostRelase = 4,
}
public void Execute()
{
Log("--------------------------------------");
Log("... FsharpEnumToString vs. CSharpEnumDictionaryLookup");
ExecuteTest(10_000_000);
}
private void ExecuteTest(int iterations)
{
string s = string.Empty;
try
{
var index = new List<int> { 0, 1, 2, 3, 4 };
var fsharpToStringTimings = new RunningAverage();
var csharpLookupTimings = new RunningAverage();
for (int i = 0; i < iterations; i++)
{
for (int dataIndex = 0; dataIndex < index.Count; dataIndex++)
{
var item = index[dataIndex];
var fsharpEnumMember = (Techdump.FsharpEnum)item;
fsharpToStringTimings.Add(TimeAction(() =>
{
s = item.ToString();
}));
if (!string.IsNullOrEmpty(s))
s = string.Empty;
var csharpEnumMember = (CSharpEnum)item;
csharpLookupTimings.Add(TimeAction(() =>
{
s = _lookup[csharpEnumMember];
}));
if (!string.IsNullOrEmpty(s))
s = string.Empty;
}
}
Log($"FSharpToString\tIterations:\t{iterations}\tAverage:\t{fsharpToStringTimings.Average:0.000}\tticks\tTotal:\t{fsharpToStringTimings.Total:0.000}\tticks");
Log($"CSharpLookup\tIterations:\t{iterations}\tAverage:\t{csharpLookupTimings.Average:0.000}\tticks\tTotal:\t{csharpLookupTimings.Total:0.000}\tticks");
}
catch (Exception ex)
{
Log($"Fail\tDataCount\t2\tIterations:\t{iterations}\tFailed\t{ex.Message}");
}
}
private float TimeAction(Action action)
{
var sw = Stopwatch.StartNew();
action();
sw.Stop();
return sw.ElapsedTicks;
}
private void Log(string s)
{
Console.WriteLine(s);
File.AppendAllText(@"c:\temp\enumToStringTest.txt", $"{s}{Environment.NewLine}");
}
}
}
FSharp Enum defined as follows:
namespace fsharp.techdump
module Techdump =
type public FsharpEnum =
Registration = 0
| ``Under Review``=1
| Approval = 2
| Release = 3
| ``Post Release`` = 4
And the RunningAverage class from a previous post.

No comments:
Post a Comment