Skip to content

Commit

Permalink
Added same performance optimizations to reader.
Browse files Browse the repository at this point in the history
Cleanup.
  • Loading branch information
JoshClose committed Apr 25, 2024
1 parent 183d47b commit f6ba629
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 245 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 async IAsyncEnumerable<T> GetRecordsAsync<T>([EnumeratorCancellat
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
64 changes: 33 additions & 31 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.GetWriterAction<T>(GetTypeInfoForRecord(record))(record);
var recordTypeInfo = GetTypeInfoForRecord(record);
var write = recordManager.Value.GetWriteDelegate<T>(recordTypeInfo);
write(record);
}
catch (TargetInvocationException ex)
{
Expand Down Expand Up @@ -362,8 +364,8 @@ public virtual void WriteRecords(IEnumerable records)
NextRecord();
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

writerAction(record);
write(record);
await NextRecordAsync().ConfigureAwait(false);
}
}
Expand Down
49 changes: 0 additions & 49 deletions src/CsvHelper/Expressions/ExpandoObjectRecordWriter.cs

This file was deleted.

50 changes: 2 additions & 48 deletions src/CsvHelper/Expressions/RecordCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,65 +35,19 @@ public RecordCreator(CsvReader reader)
ExpressionManager = new ExpressionManager(reader);
}

/// <summary>
/// Create a record of the given type using the current row.
/// </summary>
/// <typeparam name="T">The record type.</typeparam>
public T Create<T>()
{
try
{
return ((Func<T>)GetCreateRecordDelegate(typeof(T))).Invoke();
}
catch (TargetInvocationException ex)
{
if (ex.InnerException != null)
{
throw ex.InnerException;
}
else
{
throw;
}
}
}

/// <summary>
/// Create a record of the given type using the current row.
/// </summary>
/// <param name="recordType">The record type.</param>
public object Create(Type recordType)
{
try
{
return GetCreateRecordDelegate(recordType).DynamicInvoke();
}
catch (TargetInvocationException ex)
{
if (ex.InnerException != null)
{
throw ex.InnerException;
}
else
{
throw;
}
}
}

/// <summary>
/// Gets the delegate to create a record for the given record type.
/// If the delegate doesn't exist, one will be created and cached.
/// </summary>
/// <param name="recordType">The record type.</param>
protected virtual Delegate GetCreateRecordDelegate(Type recordType)
public virtual Func<T> GetCreateRecordDelegate<T>(Type recordType)
{
if (!createRecordFuncs.TryGetValue(recordType, out Delegate func))
{
createRecordFuncs[recordType] = func = CreateCreateRecordDelegate(recordType);
}

return func;
return (Func<T>)func;
}

/// <summary>
Expand Down
Loading

0 comments on commit f6ba629

Please sign in to comment.