Skip to content

Instantly share code, notes, and snippets.

@discostu105
Created March 6, 2019 20:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save discostu105/69103b549a392182fbfa2b09d11cee2f to your computer and use it in GitHub Desktop.
Save discostu105/69103b549a392182fbfa2b09d11cee2f to your computer and use it in GitHub Desktop.
Parsing exercise
using BenchmarkDotNet.Attributes;
using System;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
namespace ConsoleApp4 {
//[ShortRunJob]
[MemoryDiagnoser]
public class Program {
static void Main(string[] args) {
BenchmarkDotNet.Running.BenchmarkRunner.Run<Program>();
BenchmarkDotNet.Running.BenchmarkRunner.Run<ParsingPerf>();
}
[Benchmark]
public void Original() {
string[] machineIdPart;
string[] employeeIdPart;
long machineId;
long employeeId;
//Input String
var description = "machineId: 276744, engineId: 59440, employeeId: 4619825";
var infoList = description.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var info in infoList) {
if (info.TrimStart().StartsWith("machineId", StringComparison.OrdinalIgnoreCase)) {
machineIdPart = info.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
if (machineIdPart.Count() > 1) {
long.TryParse(machineIdPart[1].Trim(), out machineId);
}
}
if (info.TrimStart().StartsWith("employeeId", StringComparison.OrdinalIgnoreCase)) {
employeeIdPart = info.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
if (employeeIdPart.Count() > 1) {
long.TryParse(employeeIdPart[1].Trim(), out employeeId);
}
}
}
}
[Benchmark]
public void Answer() {
long machineId = 0;
long employeeId = 0;
var description = "machineId: 276744, engineId: 59440, employeeId: 4619825";
ReadOnlySpan<char> descriptionSpan = description.AsSpan();
var nameValueBlockStartIndex = 0;
while (nameValueBlockStartIndex < description.Length) {
var blockEndIndex = description.IndexOf(',', nameValueBlockStartIndex);
if (blockEndIndex == -1) {
blockEndIndex = description.Length;
}
var namePartEndIndex = description.IndexOf(':', nameValueBlockStartIndex);
var namePartLength = namePartEndIndex - nameValueBlockStartIndex;
var namePart = descriptionSpan.Slice(nameValueBlockStartIndex, namePartLength);
var valuePartStartIndex = namePartEndIndex + 1;
var valuePartLength = blockEndIndex - valuePartStartIndex + 1;
var valuePart = descriptionSpan.Slice(valuePartStartIndex, valuePartLength - 1);
while (namePart[0] == ' ') {
namePart = namePart.Slice(1);
}
if (namePart.Equals("machineId", StringComparison.OrdinalIgnoreCase)) {
Int64.TryParse(valuePart, out machineId);
} else if (namePart.Equals("employeeId", StringComparison.OrdinalIgnoreCase)) {
Int64.TryParse(valuePart, out employeeId);
}
nameValueBlockStartIndex = blockEndIndex + 1;
}
}
[Benchmark]
public void MyAnswerFastParser() {
long machineId = 0;
long employeeId = 0;
var description = "machineId: 276744, engineId: 59440, employeeId: 4619825";
var span = description.AsSpan();
while (span.Length > 0) {
var entry = span.SplitNext(',');
var key = entry.SplitNext(':').TrimStart(' ');
var value = entry.TrimStart(' ');
if (key.Equals("machineId", StringComparison.Ordinal)) {
machineId = ParsingPerf.LongParseFast(value);
}
if (key.Equals("employeeId", StringComparison.Ordinal)) {
employeeId = ParsingPerf.LongParseFast(value);
}
}
}
[Benchmark]
public void MyAnswer() {
long machineId = 0;
long employeeId = 0;
var description = "machineId: 276744, engineId: 59440, employeeId: 4619825";
var span = description.AsSpan();
while (span.Length > 0) {
var entry = span.SplitNext(',');
var key = entry.SplitNext(':').TrimStart(' ');
var value = entry.TrimStart(' ');
if (key.Equals("machineId", StringComparison.Ordinal)) {
long.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out machineId);
}
if (key.Equals("employeeId", StringComparison.Ordinal)) {
long.TryParse(value, NumberStyles.None, CultureInfo.InvariantCulture, out employeeId);
}
}
}
}
public static class Extensions {
public static ReadOnlySpan<char> SplitNext(this ref ReadOnlySpan<char> span, char seperator) {
int pos = span.IndexOf(seperator);
if (pos > -1) {
var part = span.Slice(0, pos);
span = span.Slice(pos + 1);
return part;
} else {
var part = span;
span = span.Slice(span.Length);
return part;
}
}
}
//[ShortRunJob]
[MemoryDiagnoser]
public class ParsingPerf {
private static readonly string s = "4619825";
private static long result;
private static ulong uresult;
[Benchmark]
public void Parse() {
result = long.Parse(s);
}
[Benchmark]
public void TryParse() {
long.TryParse(s, out result);
}
[Benchmark]
public void TryParseInvariantCulture() {
long.TryParse(s, NumberStyles.None, CultureInfo.InvariantCulture, out result);
}
[Benchmark]
public void TryParseInvariantCultureUnsighed() {
ulong.TryParse(s, NumberStyles.None, CultureInfo.InvariantCulture, out uresult);
}
[Benchmark]
public void ParseFast() {
result = LongParseFast(s);
}
public static long LongParseFast(ReadOnlySpan<char> value) {
long result = 0;
for (int i = 0; i < value.Length; i++) {
result = 10 * result + (value[i] - 48);
}
return result;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment