हमारे पास एक छोटी विधि है जो पार्स .csv फ़ाइल को लुकअप करने के लिए है:
ILookup<string, DgvItems> ParseCsv( string fileName )
{
var file = File.ReadAllLines( fileName );
return file.Skip( 1 ).Select( line => new DgvItems( line ) ).ToLookup( item => item.StocksID );
}
और DgvItems की परिभाषा:
public class DgvItems
{
public string DealDate { get; }
public string StocksID { get; }
public string StockName { get; }
public string SecBrokerID { get; }
public string SecBrokerName { get; }
public double Price { get; }
public int BuyQty { get; }
public int CellQty { get; }
public DgvItems( string line )
{
var split = line.Split( ',' );
DealDate = split[0];
StocksID = split[1];
StockName = split[2];
SecBrokerID = split[3];
SecBrokerName = split[4];
Price = double.Parse( split[5] );
BuyQty = int.Parse( split[6] );
CellQty = int.Parse( split[7] );
}
}
और हमने पाया कि यदि हम इस तरह ToArray()
से पहले एक अतिरिक्त जोड़ते हैं ToLookup()
:
static ILookup<string, DgvItems> ParseCsv( string fileName )
{
var file = File.ReadAllLines( fileName );
return file.Skip( 1 ).Select( line => new DgvItems( line ) ).ToArray().ToLookup( item => item.StocksID );
}
उत्तरार्द्ध काफी तेज है। विशेष रूप से, 1.4 मिलियन लाइनों के साथ परीक्षण फ़ाइल का उपयोग करते समय, पूर्व में लगभग 4.3 सेकंड लगते हैं और बाद में लगभग 3 सेकंड लगते हैं।
मुझे उम्मीद है ToArray()
कि अतिरिक्त समय लेना चाहिए ताकि बाद थोड़ा धीमा हो। यह वास्तव में तेज क्यों है?
अतिरिक्त जानकारी:
हमें यह समस्या मिली क्योंकि एक और तरीका है जो समान .csv फ़ाइल को अलग-अलग प्रारूप में रखता है और इसमें लगभग 3 सेकंड लगते हैं इसलिए हमें लगता है कि यह एक ही चीज़ को 3 सेकंड में करने में सक्षम होना चाहिए।
मूल डेटा प्रकार है
Dictionary<string, List<DgvItems>>
और मूल कोड linq का उपयोग नहीं किया है और परिणाम समान है।
बेंचमार्कडॉटनेट टेस्ट क्लास:
public class TestClass
{
private readonly string[] Lines;
public TestClass()
{
Lines = File.ReadAllLines( @"D:\20110315_Random.csv" );
}
[Benchmark]
public ILookup<string, DgvItems> First()
{
return Lines.Skip( 1 ).Select( line => new DgvItems( line ) ).ToArray().ToLookup( item => item.StocksID );
}
[Benchmark]
public ILookup<string, DgvItems> Second()
{
return Lines.Skip( 1 ).Select( line => new DgvItems( line ) ).ToLookup( item => item.StocksID );
}
}
परिणाम:
| Method | Mean | Error | StdDev |
|------- |--------:|---------:|---------:|
| First | 2.530 s | 0.0190 s | 0.0178 s |
| Second | 3.620 s | 0.0217 s | 0.0203 s |
मैंने मूल कोड के आधार पर एक और परीक्षण किया। लगता है कि समस्या Linq पर नहीं है।
public class TestClass
{
private readonly string[] Lines;
public TestClass()
{
Lines = File.ReadAllLines( @"D:\20110315_Random.csv" );
}
[Benchmark]
public Dictionary<string, List<DgvItems>> First()
{
List<DgvItems> itemList = new List<DgvItems>();
for ( int i = 1; i < Lines.Length; i++ )
{
itemList.Add( new DgvItems( Lines[i] ) );
}
Dictionary<string, List<DgvItems>> dictionary = new Dictionary<string, List<DgvItems>>();
foreach( var item in itemList )
{
if( dictionary.TryGetValue( item.StocksID, out var list ) )
{
list.Add( item );
}
else
{
dictionary.Add( item.StocksID, new List<DgvItems>() { item } );
}
}
return dictionary;
}
[Benchmark]
public Dictionary<string, List<DgvItems>> Second()
{
Dictionary<string, List<DgvItems>> dictionary = new Dictionary<string, List<DgvItems>>();
for ( int i = 1; i < Lines.Length; i++ )
{
var item = new DgvItems( Lines[i] );
if ( dictionary.TryGetValue( item.StocksID, out var list ) )
{
list.Add( item );
}
else
{
dictionary.Add( item.StocksID, new List<DgvItems>() { item } );
}
}
return dictionary;
}
}
परिणाम:
| Method | Mean | Error | StdDev |
|------- |--------:|---------:|---------:|
| First | 2.470 s | 0.0218 s | 0.0182 s |
| Second | 3.481 s | 0.0260 s | 0.0231 s |
.ToArray()
कॉल के बिना , कॉल करने .Select( line => new DgvItems( line ) )
से पहले एक IEnumerable रिटर्न करने के लिए ToLookup( item => item.StocksID )
। और एक विशेष तत्व को देखना ऐरे की तुलना में IEnumerable का उपयोग करना बदतर है। संभवतः एक सरणी में बदलने के लिए और ienumerable का उपयोग करके लुकअप करने के लिए तेज़ी से।
var file = File.ReadLines( fileName );
- के ReadLines
बजाय ReadAllLines
और आप कोड शायद तेज हो जाएगा
BenchmarkDotnet
वास्तविक पूर्ण माप के लिए उपयोग करना चाहिए । इसके अलावा, उस वास्तविक कोड को आज़माएं और अलग करें जिसे आप मापना चाहते हैं और परीक्षण में IO को शामिल नहीं करते हैं।