Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Globalization;
using System.IO;
using BenchmarkDotNet.Attributes;

namespace CsvHelper.Benchmarks;

[MemoryDiagnoser]
public class BenchmarkEnumerateRecordsSingleInstance
{
private const int entryCount = 2000;
private readonly MemoryStream stream = new();

public class SimpleWithValueType
{
public int Id { get; set; }
public bool Flag1 { get; set; }
public bool Flag2 { get; set; }
}

[GlobalSetup]
public void GlobalSetupSimple()
{
using var streamWriter = new StreamWriter(this.stream, null, -1, true);
using var writer = new CsvWriter(streamWriter, CultureInfo.InvariantCulture, true);
var random = new Random(43); // Different seed for variety

writer.WriteHeader(typeof(SimpleWithValueType));
writer.NextRecord();
for (int i = 0; i < entryCount; ++i)
{
writer.WriteRecord(new SimpleWithValueType()
{
Id = random.Next(),
Flag1 = random.Next(2) == 0,
Flag2 = random.Next(2) == 0
});
writer.NextRecord();
}
}

[GlobalCleanup]
public void GlobalCleanupSimple()
{
this.stream.Dispose();
}

[Benchmark]
public void EnumerateRecordsSingleInstance()
{
this.stream.Position = 0;
using var streamReader = new StreamReader(this.stream, null, true, -1, true);
using var csv = new CsvReader(streamReader, CultureInfo.InvariantCulture, true);
var instance = new SimpleWithValueType();
foreach (var record in csv.EnumerateRecords(instance))
{
_ = record;
}
}
}
8 changes: 4 additions & 4 deletions performance/CsvHelper.Benchmarks/BenchmarkMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace CsvHelper.Benchmarks;

internal class BenchmarkMain
{
static void Main(string[] args)
{
_ = BenchmarkRunner.Run<BenchmarkEnumerateRecords>();
}
static void Main(string[] args)
{
_ = BenchmarkSwitcher.FromAssembly(System.Reflection.Assembly.GetExecutingAssembly()).Run(args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.15.0" />
<PackageReference Include="Microsoft.VisualStudio.DiagnosticsHub.BenchmarkDotNetDiagnosers" Version="18.0.36421.1" />
</ItemGroup>

<ItemGroup>
Expand Down
95 changes: 49 additions & 46 deletions src/CsvHelper/TypeConversion/BooleanConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,59 +12,62 @@ namespace CsvHelper.TypeConversion;
/// </summary>
public class BooleanConverter : DefaultTypeConverter
{
/// <inheritdoc/>
public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
{
if (bool.TryParse(text, out var b))
{
return b;
}
private static readonly object BoxedTrue = true;
private static readonly object BoxedFalse = false;

if (short.TryParse(text, out var sh))
{
if (sh == 0)
{
return false;
}
if (sh == 1)
{
return true;
}
}
/// <inheritdoc/>
public override object? ConvertFromString(string? text, IReaderRow row, MemberMapData memberMapData)
{
if (bool.TryParse(text, out var b))
{
return b ? BoxedTrue : BoxedFalse;
}

var t = (text ?? string.Empty).Trim();
foreach (var trueValue in memberMapData.TypeConverterOptions.BooleanTrueValues)
{
if (memberMapData.TypeConverterOptions.CultureInfo!.CompareInfo.Compare(trueValue, t, CompareOptions.IgnoreCase) == 0)
{
return true;
}
}
if (short.TryParse(text, out var sh))
{
if (sh == 0)
{
return BoxedFalse;
}
if (sh == 1)
{
return BoxedTrue;
}
}

foreach (var falseValue in memberMapData.TypeConverterOptions.BooleanFalseValues)
{
if (memberMapData.TypeConverterOptions.CultureInfo!.CompareInfo.Compare(falseValue, t, CompareOptions.IgnoreCase) == 0)
{
return false;
}
}
var t = (text ?? string.Empty).Trim();
foreach (var trueValue in memberMapData.TypeConverterOptions.BooleanTrueValues)
{
if (memberMapData.TypeConverterOptions.CultureInfo!.CompareInfo.Compare(trueValue, t, CompareOptions.IgnoreCase) == 0)
{
return BoxedTrue;
}
}

return base.ConvertFromString(text, row, memberMapData);
}
foreach (var falseValue in memberMapData.TypeConverterOptions.BooleanFalseValues)
{
if (memberMapData.TypeConverterOptions.CultureInfo!.CompareInfo.Compare(falseValue, t, CompareOptions.IgnoreCase) == 0)
{
return BoxedFalse;
}
}

/// <inheritdoc/>
public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
{
return base.ConvertFromString(text, row, memberMapData);
}

/// <inheritdoc/>
public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
{
var b = value as bool?;
if (b == true && memberMapData.TypeConverterOptions.BooleanTrueValues.Count > 0)
{
return memberMapData.TypeConverterOptions.BooleanTrueValues.First();
}
{
return memberMapData.TypeConverterOptions.BooleanTrueValues.First();
}
else if (b == false && memberMapData.TypeConverterOptions.BooleanFalseValues.Count > 0)
{
return memberMapData.TypeConverterOptions.BooleanFalseValues.First();
}
{
return memberMapData.TypeConverterOptions.BooleanFalseValues.First();
}

return base.ConvertToString(value, row, memberMapData);
}
return base.ConvertToString(value, row, memberMapData);
}
}
Loading