.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 );
}
후자는 상당히 빠릅니다. 보다 구체적으로, 140 만 줄의 테스트 파일을 사용할 경우 전자는 약 4.3 초가 소요되고 후자는 약 3 초가 소요됩니다.
나는 ToArray()
시간이 좀 더 걸리므로 후자는 조금 느려 야합니다. 실제로 왜 더 빠릅니까?
추가 정보:
동일한 .csv 파일을 다른 형식으로 구문 분석하는 데 다른 방법이 있으며 약 3 초가 걸리므 로이 문제는 3 초 안에 동일한 작업을 수행 할 수 있다고 생각하기 때문에이 문제가 발견되었습니다.
원래 데이터 형식은
Dictionary<string, List<DgvItems>>
원래 코드에서 linq를 사용하지 않았으며 결과는 비슷합니다.
BenchmarkDotNet 테스트 클래스 :
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 |
2
테스트 코드 / 측정이 의심됩니다. 시간을 계산하는 코드를 게시하십시오
—
Erno
내 생각에는을
—
kimbaudi
.ToArray()
호출 하지 않고 호출하기 .Select( line => new DgvItems( line ) )
전에 IEnumerable 을 반환한다고 가정 ToLookup( item => item.StocksID )
합니다. 그리고 배열보다 IEnumerable을 사용하면 특정 요소를 찾는 것이 더 나쁩니다. 아마도 ienumerable을 사용하는 것보다 배열로 변환하고 조회를 수행하는 것이 더 빠릅니다.
사이드 참고 : 넣어
—
드미트리 Bychenko
var file = File.ReadLines( fileName );
- ReadLines
대신 ReadAllLines
당신은 코드 아마 빨라집니다
BenchmarkDotnet
실제 성능 측정에 사용해야 합니다. 또한 측정하려는 실제 코드를 격리하고 테스트에 IO를 포함시키지 마십시오.
왜 이것이 공감대를 얻었는지 모르겠습니다. 좋은 질문이라고 생각합니다.
—
Rufus L