Skip to content

Commit

Permalink
Merge branch 'snaumenko-st-writer-performance-1'
Browse files Browse the repository at this point in the history
  • Loading branch information
JoshClose committed Apr 25, 2024
2 parents 9da7834 + f6ba629 commit 4c5fe74
Show file tree
Hide file tree
Showing 14 changed files with 187 additions and 207 deletions.
42 changes: 36 additions & 6 deletions src/CsvHelper/CsvReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,8 @@ public virtual T GetRecord<T>()
T record;
try
{
record = recordManager.Value.Create<T>();
var read = recordManager.Value.GetReadDelegate<T>(typeof(T));
record = read();
}
catch (Exception ex)
{
Expand Down Expand Up @@ -805,7 +806,8 @@ public virtual object GetRecord(Type type)
object record;
try
{
record = recordManager.Value.Create(type);
var read = recordManager.Value.GetReadDelegate<object>(type);
record = read();
}
catch (Exception ex)
{
Expand Down Expand Up @@ -856,12 +858,19 @@ public virtual IEnumerable<T> GetRecords<T>()
ValidateHeader<T>();
}

Func<T> read = null;

while (Read())
{
T record;
try
{
record = recordManager.Value.Create<T>();
if (read == null)
{
read = recordManager.Value.GetReadDelegate<T>(typeof(T));
}

record = read();
}
catch (Exception ex)
{
Expand Down Expand Up @@ -930,12 +939,19 @@ public virtual IEnumerable<object> GetRecords(Type type)
ValidateHeader(type);
}

Func<object> read = null;

while (Read())
{
object record;
try
{
record = recordManager.Value.Create(type);
if (read == null)
{
read = recordManager.Value.GetReadDelegate<object>(type);
}

record = read();
}
catch (Exception ex)
{
Expand Down Expand Up @@ -1045,13 +1061,20 @@ public virtual IEnumerable<T> EnumerateRecords<T>(T record)
ValidateHeader<T>();
}

Func<T> read = null;

while (await ReadAsync().ConfigureAwait(false))
{
cancellationToken.ThrowIfCancellationRequested();
T record;
try
{
record = recordManager.Value.Create<T>();
if (read == null)
{
read = recordManager.Value.GetReadDelegate<T>(typeof(T));
}

record = read();
}
catch (Exception ex)
{
Expand Down Expand Up @@ -1120,13 +1143,20 @@ public virtual async IAsyncEnumerable<object> GetRecordsAsync(Type type, [Enumer
ValidateHeader(type);
}

Func<object> read = null;

while (await ReadAsync().ConfigureAwait(false))
{
cancellationToken.ThrowIfCancellationRequested();
object record;
try
{
record = recordManager.Value.Create(type);
if (read == null)
{
read = recordManager.Value.GetReadDelegate<object>(type);
}

record = read();
}
catch (Exception ex)
{
Expand Down
65 changes: 56 additions & 9 deletions src/CsvHelper/CsvWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,9 @@ public virtual void WriteRecord<T>(T record)
{
try
{
recordManager.Value.Write(record);
var recordTypeInfo = GetTypeInfoForRecord(record);
var write = recordManager.Value.GetWriteDelegate<T>(recordTypeInfo);
write(record);
}
catch (TargetInvocationException ex)
{
Expand Down Expand Up @@ -362,6 +364,9 @@ public virtual void WriteRecords(IEnumerable records)
NextRecord();
}

Action<object> write = null;
RecordTypeInfo writeType = default;

foreach (var record in records)
{
if (record == null)
Expand All @@ -371,7 +376,13 @@ public virtual void WriteRecords(IEnumerable records)
continue;
}

WriteRecord(record);
if (write == null || writeType.RecordType != record.GetType())
{
writeType = GetTypeInfoForRecord(record);
write = recordManager.Value.GetWriteDelegate<object>(writeType);
}

write(record);
NextRecord();
}
}
Expand All @@ -393,9 +404,18 @@ public virtual void WriteRecords<T>(IEnumerable<T> records)
NextRecord();
}

Action<T> write = null;
RecordTypeInfo writeType = default;

foreach (var record in records)
{
WriteRecord(record);
if (write == null || (record != null && writeType.RecordType != typeof(T)))
{
writeType = GetTypeInfoForRecord(record);
write = recordManager.Value.GetWriteDelegate<T>(writeType);
}

write(record);
NextRecord();
}
}
Expand All @@ -420,11 +440,20 @@ public virtual async Task WriteRecordsAsync(IEnumerable records, CancellationTok
await NextRecordAsync().ConfigureAwait(false);
}

Action<object> write = null;
RecordTypeInfo writeType = default;

foreach (var record in records)
{
cancellationToken.ThrowIfCancellationRequested();

WriteRecord(record);
if (write == null || (record != null && writeType.RecordType != record.GetType()))
{
writeType = GetTypeInfoForRecord(record);
write = recordManager.Value.GetWriteDelegate<object>(writeType);
}

write(record);
await NextRecordAsync().ConfigureAwait(false);
}
}
Expand All @@ -449,11 +478,20 @@ public virtual async Task WriteRecordsAsync<T>(IEnumerable<T> records, Cancellat
await NextRecordAsync().ConfigureAwait(false);
}

Action<T> write = null;
RecordTypeInfo writeType = default;

foreach (var record in records)
{
cancellationToken.ThrowIfCancellationRequested();

WriteRecord(record);
if (write == null || (record != null && writeType.RecordType != typeof(T)))
{
writeType = GetTypeInfoForRecord(record);
write = recordManager.Value.GetWriteDelegate<T>(writeType);
}

write(record);
await NextRecordAsync().ConfigureAwait(false);
}
}
Expand All @@ -478,11 +516,20 @@ public virtual async Task WriteRecordsAsync<T>(IAsyncEnumerable<T> records, Canc
await NextRecordAsync().ConfigureAwait(false);
}

Action<T> write = null;
RecordTypeInfo writeType = default;

await foreach (var record in records.ConfigureAwait(false))
{
cancellationToken.ThrowIfCancellationRequested();

WriteRecord(record);
if (write == null || (record != null && writeType.RecordType != typeof(T)))
{
writeType = GetTypeInfoForRecord(record);
write = recordManager.Value.GetWriteDelegate<T>(writeType);
}

write(record);
await NextRecordAsync().ConfigureAwait(false);
}
}
Expand Down Expand Up @@ -576,15 +623,15 @@ public virtual bool CanWrite(MemberMap memberMap)
/// <typeparam name="T">The type of the record.</typeparam>
/// <param name="record">The record to determine the type of.</param>
/// <returns>The System.Type for the record.</returns>
public virtual Type GetTypeForRecord<T>(T record)
public virtual RecordTypeInfo GetTypeInfoForRecord<T>(T record)
{
var type = typeof(T);
if (type == typeof(object))
{
type = record.GetType();
return new RecordTypeInfo(record.GetType(), true);
}

return type;
return new RecordTypeInfo(type, false);
}

/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions src/CsvHelper/Expressions/DynamicRecordWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public DynamicRecordWriter(CsvWriter writer) : base(writer) { }
/// that will write the given record using the current writer row.
/// </summary>
/// <typeparam name="T">The record type.</typeparam>
/// <param name="record">The record.</param>
protected override Action<T> CreateWriteDelegate<T>(T record)
/// <param name="type">The type for the record.</param>
protected override Action<T> CreateWriteDelegate<T>(Type type)
{
// http://stackoverflow.com/a/14011692/68499

Expand Down Expand Up @@ -72,4 +72,4 @@ private object GetValue(string name, IDynamicMetaObjectProvider target)
return callSite.Target(callSite, target);
}
}
}
}
49 changes: 0 additions & 49 deletions src/CsvHelper/Expressions/ExpandoObjectRecordWriter.cs

This file was deleted.

6 changes: 2 additions & 4 deletions src/CsvHelper/Expressions/ObjectRecordWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ public ObjectRecordWriter(CsvWriter writer) : base(writer) { }
/// that will write the given record using the current writer row.
/// </summary>
/// <typeparam name="T">The record type.</typeparam>
/// <param name="record">The record.</param>
protected override Action<T> CreateWriteDelegate<T>(T record)
/// <param name="type">The type for the record.</param>
protected override Action<T> CreateWriteDelegate<T>(Type type)
{
var type = Writer.GetTypeForRecord(record);

if (Writer.Context.Maps[type] == null)
{
Writer.Context.Maps.Add(Writer.Context.AutoMap(type));
Expand Down
6 changes: 2 additions & 4 deletions src/CsvHelper/Expressions/PrimitiveRecordWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ public PrimitiveRecordWriter(CsvWriter writer) : base(writer) { }
/// that will write the given record using the current writer row.
/// </summary>
/// <typeparam name="T">The record type.</typeparam>
/// <param name="record">The record.</param>
protected override Action<T> CreateWriteDelegate<T>(T record)
/// <param name="type">The type for the record.</param>
protected override Action<T> CreateWriteDelegate<T>(Type type)
{
var type = Writer.GetTypeForRecord(record);

var recordParameter = Expression.Parameter(typeof(T), "record");

Expression fieldExpression = Expression.Convert(recordParameter, typeof(object));
Expand Down
Loading

0 comments on commit 4c5fe74

Please sign in to comment.