2013-01-18 7 views
0

사용자 지정 로그 파일을 분석하는 방법을 찾고 있습니다.몇 GBs 데이터의 구문 분석 및 분석

저는 LINQ와 C# .NET을 사용하여 구현했습니다. 500MB 크기의 로그 파일에서만 작동합니다.

로그 파일의 각 행

는 MetricsList가 채워집니다

List<Metrics> MetricsList = new List<Metrics>(); 

public class Metrics 
{ 
    public DateTime Date { get; set; } 
    public string Metrics1 { get; set; } 
    public string Metrics2 { get; set; } 
       : 
       : 
    public string Metrics9 { get; set; } 
} 

처럼 보이는 객체에서 이루어집니다. 유용한 분석을 제공하기 위해 MetricsList에서 다양한 LINQ 쿼리가 실행됩니다. 메트릭 개체에는 300 바이트가 필요합니다. 500MB 로그 파일에는 약 4 백만 줄의 메모리가있어 MetricsList의 크기만으로도 1GB 이상의 프로그램 메모리를 소비합니다.

내 요구 사항은 크기가 최대 2GB 인 파일을 구문 분석하고 분석하여 4GB의 메모리를 사용하는 것처럼 보입니다.

Windows, Microsoft 기술 및 모든 오픈 소스 라이브러리를 사용하는 더 나은 방법이나 대안.

+3

데이터를 스트리밍해야 할 가능성이 높습니다. 한 번에 하나의 메트릭 (또는 메트릭 덩어리)을 읽은 다음 메모리에서 삭제하고 다음으로 이동하십시오. –

+0

라인을 어떻게 읽으십니까? 'Streamreader' 또는'File.ReadLines'를 사용하여 모두 대신 하나의 라인을 읽을 수 있습니다 (foo.File.ReadAllLines'). 또한 ['MemoryMappedFile'-class] (http://msdn.microsoft.com/en-us/library/system.io.memorymappedfiles.memorymappedfile.aspx)를 살펴보십시오. _Memory-mapped 파일은 메모리를 동시에 관리 할 수 ​​있고 프로그래머가 탐색 할 필요없이 파일에 대한 완전 무작위 액세스를 허용하기 때문에 매우 큰 파일로 작업 할 수있게합니다. 메모리 매핑 된 파일은 여러 프로세스간에 공유 할 수도 있습니다. –

+0

"Windows 및 Microsoft 기술 사용에 제한이 있습니다"라는 이유 때문에 제한 사항이 나타나는 이유는 무엇입니까? 다른 기술은 무엇입니까? –

답변

1

SQlite를 사용하여 비슷한 작업을 수행했습니다. System.Data.SQLite NuGet을 설치하십시오 (옵션 : Dapper NuGet을 매우 효율적인 마이크로 ORM으로 사용했습니다). 그런 다음 쿼리를 수행하고 보고서를 생성하는 데 아주 좋은 도구가 있습니다. 당신이 좋아하지 않을 수있는 유일한 방법은 LINQ 대신 SQL을 작성해야한다는 것입니다 (SQLite에도 LINQ가 있지만 사용하지는 않았지만).

이렇게하면 메모리 소비도 사라집니다.

1

일반적으로 메모리가 충분하지 않은 한 파일을 저장하는 대신 파일을 구문 분석 할 때 데이터를 처리합니다. 나는 단순히 더 많은 메모리를 설치하고 아마도 64 비트로 솔루션을 설정할 것입니다 ...

그러나 이것이 옵션이 아니라면 항상 약간의 메모리 사용을 최적화 할 수 있습니다. .NET은 문자열을 char []로 저장합니다. char는 기본적으로 2 바이트의 short입니다. Encoding.UTF8.GetBytes를 사용하여 char []로 저장하지 않고 byte []로 저장하면 많은 메모리를 쉽게 절약 할 수 있습니다.

또한 각 문자열 또는 바이트 []는 64 비트 환경에서 24 바이트 (개체 자체는 16 개, 포인터는 8 개)를 사용합니다. 작은 줄이 많은 경우 더할 수 있습니다. 문자열로 저장하는 대신 단일 바이트 []를 저장하고 getters에서 구문 분석을 수행 할 수도 있습니다.

내 충고를 결론 지으면서 : 더 많은 메모리를 구입하거나 읽거나 필요에 따라 데이터를 처리하십시오.

은 [업데이트 + 1]

그냥 당신이 목록을 사용하는 것으로 나타났습니다. 가장 쉬운 방법은 IEnumerable로 파일을 읽고 그것에 Linq를 사용하는 것입니다. 먼저 목록에 넣지 마십시오. 예컨대 :

public IEnumerable<Metric> ReadFile() 
{ 
    string s; 
    while ((s=myFileReader.ReadLine())!=null) 
    { 
     yield return Parse(s); 
    } 
} 

int someAnalysis = ReadFile().Sum((a)=>(a.Metric1.Length)); // or whatever you do 

[업데이트 + 2]

오, 내가 당신을 위해 또 다른 트릭을 가지고있다. 파일 읽기는 상대적으로 힘들 기 때문에 성능이 저하 될 수 있습니다. 그래서 위의 IEnumeration 트릭을 사용하는 대신 압축 된 스트림을 사용하여 메모리에 모든 데이터를 저장 한 다음 파일 대신 처리 중에 사용합니다.

내가 이상한 해결책에 대해 심각하게 생각하는지 궁금한 사람들에게 : 검색 기술과 데이터베이스를 구축 할 때 자주 사용되는 기술입니다. (빠른) 메모리를 많이 사용한다는 것은 단순히) 디스크 IO. 또한 로그 파일은 아마도 매우 잘 압축 될 것입니다.

따라서 memorystream 상단에 파일 & & 플랫 스트림을 읽습니다. 그런 다음 위에 언급 한 방식으로 Linq를 읽으십시오 (다시, memorystream의 맨 위에 flatestream).