Skip to content

Commit f6ba629

Browse files
committed
Added same performance optimizations to reader.
Cleanup.
1 parent 183d47b commit f6ba629

11 files changed

Lines changed: 125 additions & 245 deletions

src/CsvHelper/CsvReader.cs

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,8 @@ public virtual T GetRecord<T>()
745745
T record;
746746
try
747747
{
748-
record = recordManager.Value.Create<T>();
748+
var read = recordManager.Value.GetReadDelegate<T>(typeof(T));
749+
record = read();
749750
}
750751
catch (Exception ex)
751752
{
@@ -805,7 +806,8 @@ public virtual object GetRecord(Type type)
805806
object record;
806807
try
807808
{
808-
record = recordManager.Value.Create(type);
809+
var read = recordManager.Value.GetReadDelegate<object>(type);
810+
record = read();
809811
}
810812
catch (Exception ex)
811813
{
@@ -856,12 +858,19 @@ public virtual IEnumerable<T> GetRecords<T>()
856858
ValidateHeader<T>();
857859
}
858860

861+
Func<T> read = null;
862+
859863
while (Read())
860864
{
861865
T record;
862866
try
863867
{
864-
record = recordManager.Value.Create<T>();
868+
if (read == null)
869+
{
870+
read = recordManager.Value.GetReadDelegate<T>(typeof(T));
871+
}
872+
873+
record = read();
865874
}
866875
catch (Exception ex)
867876
{
@@ -930,12 +939,19 @@ public virtual IEnumerable<object> GetRecords(Type type)
930939
ValidateHeader(type);
931940
}
932941

942+
Func<object> read = null;
943+
933944
while (Read())
934945
{
935946
object record;
936947
try
937948
{
938-
record = recordManager.Value.Create(type);
949+
if (read == null)
950+
{
951+
read = recordManager.Value.GetReadDelegate<object>(type);
952+
}
953+
954+
record = read();
939955
}
940956
catch (Exception ex)
941957
{
@@ -1045,13 +1061,20 @@ public virtual IEnumerable<T> EnumerateRecords<T>(T record)
10451061
ValidateHeader<T>();
10461062
}
10471063

1064+
Func<T> read = null;
1065+
10481066
while (await ReadAsync().ConfigureAwait(false))
10491067
{
10501068
cancellationToken.ThrowIfCancellationRequested();
10511069
T record;
10521070
try
10531071
{
1054-
record = recordManager.Value.Create<T>();
1072+
if (read == null)
1073+
{
1074+
read = recordManager.Value.GetReadDelegate<T>(typeof(T));
1075+
}
1076+
1077+
record = read();
10551078
}
10561079
catch (Exception ex)
10571080
{
@@ -1120,13 +1143,20 @@ public virtual async IAsyncEnumerable<object> GetRecordsAsync(Type type, [Enumer
11201143
ValidateHeader(type);
11211144
}
11221145

1146+
Func<object> read = null;
1147+
11231148
while (await ReadAsync().ConfigureAwait(false))
11241149
{
11251150
cancellationToken.ThrowIfCancellationRequested();
11261151
object record;
11271152
try
11281153
{
1129-
record = recordManager.Value.Create(type);
1154+
if (read == null)
1155+
{
1156+
read = recordManager.Value.GetReadDelegate<object>(type);
1157+
}
1158+
1159+
record = read();
11301160
}
11311161
catch (Exception ex)
11321162
{

src/CsvHelper/CsvWriter.cs

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,9 @@ public virtual void WriteRecord<T>(T record)
331331
{
332332
try
333333
{
334-
recordManager.Value.GetWriterAction<T>(GetTypeInfoForRecord(record))(record);
334+
var recordTypeInfo = GetTypeInfoForRecord(record);
335+
var write = recordManager.Value.GetWriteDelegate<T>(recordTypeInfo);
336+
write(record);
335337
}
336338
catch (TargetInvocationException ex)
337339
{
@@ -362,8 +364,8 @@ public virtual void WriteRecords(IEnumerable records)
362364
NextRecord();
363365
}
364366

365-
Action<object> writerAction = null;
366-
RecordTypeInfo writerActionType = default;
367+
Action<object> write = null;
368+
RecordTypeInfo writeType = default;
367369

368370
foreach (var record in records)
369371
{
@@ -374,13 +376,13 @@ public virtual void WriteRecords(IEnumerable records)
374376
continue;
375377
}
376378

377-
if (writerAction == null || writerActionType.RecordType != record.GetType())
379+
if (write == null || writeType.RecordType != record.GetType())
378380
{
379-
writerActionType = GetTypeInfoForRecord(record);
380-
writerAction = recordManager.Value.GetWriterAction<object>(writerActionType);
381+
writeType = GetTypeInfoForRecord(record);
382+
write = recordManager.Value.GetWriteDelegate<object>(writeType);
381383
}
382384

383-
writerAction(record);
385+
write(record);
384386
NextRecord();
385387
}
386388
}
@@ -402,18 +404,18 @@ public virtual void WriteRecords<T>(IEnumerable<T> records)
402404
NextRecord();
403405
}
404406

405-
Action<T> writerAction = null;
406-
RecordTypeInfo writerActionType = default;
407+
Action<T> write = null;
408+
RecordTypeInfo writeType = default;
407409

408410
foreach (var record in records)
409411
{
410-
if (writerAction == null || (record != null && writerActionType.RecordType != record.GetType()))
412+
if (write == null || (record != null && writeType.RecordType != typeof(T)))
411413
{
412-
writerActionType = GetTypeInfoForRecord(record);
413-
writerAction = recordManager.Value.GetWriterAction<T>(writerActionType);
414+
writeType = GetTypeInfoForRecord(record);
415+
write = recordManager.Value.GetWriteDelegate<T>(writeType);
414416
}
415417

416-
writerAction(record);
418+
write(record);
417419
NextRecord();
418420
}
419421
}
@@ -438,20 +440,20 @@ public virtual async Task WriteRecordsAsync(IEnumerable records, CancellationTok
438440
await NextRecordAsync().ConfigureAwait(false);
439441
}
440442

441-
Action<object> writerAction = null;
442-
RecordTypeInfo writerActionType = default;
443+
Action<object> write = null;
444+
RecordTypeInfo writeType = default;
443445

444446
foreach (var record in records)
445447
{
446448
cancellationToken.ThrowIfCancellationRequested();
447449

448-
if (writerAction == null || (record != null && writerActionType.RecordType != record.GetType()))
450+
if (write == null || (record != null && writeType.RecordType != record.GetType()))
449451
{
450-
writerActionType = GetTypeInfoForRecord(record);
451-
writerAction = recordManager.Value.GetWriterAction<object>(writerActionType);
452+
writeType = GetTypeInfoForRecord(record);
453+
write = recordManager.Value.GetWriteDelegate<object>(writeType);
452454
}
453455

454-
writerAction(record);
456+
write(record);
455457
await NextRecordAsync().ConfigureAwait(false);
456458
}
457459
}
@@ -476,20 +478,20 @@ public virtual async Task WriteRecordsAsync<T>(IEnumerable<T> records, Cancellat
476478
await NextRecordAsync().ConfigureAwait(false);
477479
}
478480

479-
Action<T> writerAction = null;
480-
RecordTypeInfo writerActionType = default;
481+
Action<T> write = null;
482+
RecordTypeInfo writeType = default;
481483

482484
foreach (var record in records)
483485
{
484486
cancellationToken.ThrowIfCancellationRequested();
485487

486-
if (writerAction == null || (record != null && writerActionType.RecordType != record.GetType()))
488+
if (write == null || (record != null && writeType.RecordType != typeof(T)))
487489
{
488-
writerActionType = GetTypeInfoForRecord(record);
489-
writerAction = recordManager.Value.GetWriterAction<T>(writerActionType);
490+
writeType = GetTypeInfoForRecord(record);
491+
write = recordManager.Value.GetWriteDelegate<T>(writeType);
490492
}
491493

492-
writerAction(record);
494+
write(record);
493495
await NextRecordAsync().ConfigureAwait(false);
494496
}
495497
}
@@ -514,20 +516,20 @@ public virtual async Task WriteRecordsAsync<T>(IAsyncEnumerable<T> records, Canc
514516
await NextRecordAsync().ConfigureAwait(false);
515517
}
516518

517-
Action<T> writerAction = null;
518-
RecordTypeInfo writerActionType = default;
519+
Action<T> write = null;
520+
RecordTypeInfo writeType = default;
519521

520522
await foreach (var record in records.ConfigureAwait(false))
521523
{
522524
cancellationToken.ThrowIfCancellationRequested();
523525

524-
if (writerAction == null || (record != null && writerActionType.RecordType != record.GetType()))
526+
if (write == null || (record != null && writeType.RecordType != typeof(T)))
525527
{
526-
writerActionType = GetTypeInfoForRecord(record);
527-
writerAction = recordManager.Value.GetWriterAction<T>(writerActionType);
528+
writeType = GetTypeInfoForRecord(record);
529+
write = recordManager.Value.GetWriteDelegate<T>(writeType);
528530
}
529531

530-
writerAction(record);
532+
write(record);
531533
await NextRecordAsync().ConfigureAwait(false);
532534
}
533535
}

src/CsvHelper/Expressions/ExpandoObjectRecordWriter.cs

Lines changed: 0 additions & 49 deletions
This file was deleted.

src/CsvHelper/Expressions/RecordCreator.cs

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -35,65 +35,19 @@ public RecordCreator(CsvReader reader)
3535
ExpressionManager = new ExpressionManager(reader);
3636
}
3737

38-
/// <summary>
39-
/// Create a record of the given type using the current row.
40-
/// </summary>
41-
/// <typeparam name="T">The record type.</typeparam>
42-
public T Create<T>()
43-
{
44-
try
45-
{
46-
return ((Func<T>)GetCreateRecordDelegate(typeof(T))).Invoke();
47-
}
48-
catch (TargetInvocationException ex)
49-
{
50-
if (ex.InnerException != null)
51-
{
52-
throw ex.InnerException;
53-
}
54-
else
55-
{
56-
throw;
57-
}
58-
}
59-
}
60-
61-
/// <summary>
62-
/// Create a record of the given type using the current row.
63-
/// </summary>
64-
/// <param name="recordType">The record type.</param>
65-
public object Create(Type recordType)
66-
{
67-
try
68-
{
69-
return GetCreateRecordDelegate(recordType).DynamicInvoke();
70-
}
71-
catch (TargetInvocationException ex)
72-
{
73-
if (ex.InnerException != null)
74-
{
75-
throw ex.InnerException;
76-
}
77-
else
78-
{
79-
throw;
80-
}
81-
}
82-
}
83-
8438
/// <summary>
8539
/// Gets the delegate to create a record for the given record type.
8640
/// If the delegate doesn't exist, one will be created and cached.
8741
/// </summary>
8842
/// <param name="recordType">The record type.</param>
89-
protected virtual Delegate GetCreateRecordDelegate(Type recordType)
43+
public virtual Func<T> GetCreateRecordDelegate<T>(Type recordType)
9044
{
9145
if (!createRecordFuncs.TryGetValue(recordType, out Delegate func))
9246
{
9347
createRecordFuncs[recordType] = func = CreateCreateRecordDelegate(recordType);
9448
}
9549

96-
return func;
50+
return (Func<T>)func;
9751
}
9852

9953
/// <summary>

0 commit comments

Comments
 (0)