2011-08-23 17 views
6

Próbuję przeprowadzić migrację programu C# do C++. Program C# odczytuje wiersz tekstu o rozmiarach 1 ~ 5 gb po linii i wykonuje analizę każdej linii. Kod C# jest jak poniżej.C++ wydajność odczytu pliku tekstowego

using (var f = File.OpenRead(fname)) 
using (var reader = new StreamReader(f)) 
    while (!reader.EndOfStream) { 
     var line = reader.ReadLine(); 
     // do some analysis 
    } 

Dla danego pliku 1,6 gb z 7 milionami linii, ten kod zajmuje około 18 sekund.

C++ kod I napisali pierwszy migracji jest jak poniżej

ifstream f(fname); 
string line;  
while (getline(f, line)) { 
    // do some analysis 
} 

C++ kod powyżej zajmuje około 420 sekund. Drugi napisany przeze mnie kod C++ jest jak poniżej.

ifstream f(fname); 
char line[2000]; 
while (f.getline(line, 2000)) { 
    // do some analysis 
} 

C++ powyżej zajmuje około 85 sekund.

Ostatni kod, który próbowałem, to kod c, jak poniżej.

FILE *file = fopen (fname, "r"); 
char line[2000]; 
while (fgets(line, 2000, file) != NULL) { 
    // do some analysis 
} 
fclose (file); 

Powyższy kod c zajmuje około 33 sekund.

Oba ostatnie 2 kody, które parsują linie na char [] zamiast łańcucha, potrzebują około 30 sekund więcej, aby przekształcić char [] na ciąg.

Czy istnieje sposób na polepszenie wydajności kodu c/C++ w celu odczytania pliku tekstowego wiersz po wierszu, aby dopasować wydajność C#? (Dodano: Używam Windows 7 64-bitowy OS z VC++ 10,0, x64)

+0

Twoje pytanie jest podobne do tego wątku http://stackoverflow.com/questions/7102087/how-to-enhance-the-speed-of-my-c-program-in-reading-delimited-text-files/ 7102179 # 7102179 –

+1

Interesujące pytanie brzmi: jak to robi C#? Dzięki temu dowiesz się, jakie optymalizacje wykorzystali i prawdopodobnie zaproponujesz kilka. – ssube

Odpowiedz

9

Jednym z najlepszych sposobów na zwiększenie wydajności odczytu pliku jest użycie pamięci mapowane plików (mmap() W systemie UNIX CreateFileMapping() etc w systemie Windows). Wtedy twój plik pojawia się w pamięci jako jeden płaski fragment bajtów i możesz go odczytać znacznie szybciej niż buforowanie wejść/wyjść.

W przypadku pliku większego niż gigabajt należy użyć 64-bitowego systemu operacyjnego (z procesem 64-bitowym). Zrobiłem to, aby przetworzyć plik 30 GB w Pythonie z doskonałymi wynikami.

0

Proponuję dwie rzeczy:

Zastosowanie f.rdbuf()->pubsetbuf(...) aby ustawić większy bufor odczytu. Zauważyłem kilka naprawdę znaczących wzrostów wydajności strumienia przy większych rozmiarach bufora.

Zamiast getline(...) użyj read(...), aby odczytać większe bloki danych i przeanalizuj je ręcznie.

0

Kompilacja z optymalizacjami. C++ ma dość teoretyczny narzut, że optymalizator zostanie usunięty. Na przykład. wiele prostych metod ciągów zostanie zainicjowanych. Pewnie dlatego twoja wersja char[2000] jest szybsza.

Powiązane problemy