2012-04-25 42 views
8

Używam wywołania funkcji fwrite() do zapisu danych do potoku w systemie Linux.Zrozumienie zachowania buforowania fwrite()

Wcześniej fwrite() był nazywany małych ilości danych (średnio 20 bajtów) wielokrotnie buforujący pozostawiono do fwrite(). strace w procesie pokazało, że zapisywano 4096 bajtów danych jednocześnie.

Okazało się, że ten proces pisania był wąskim gardłem w moim programie. Zdecydowałem się więc na buforowanie danych w moim kodzie do bloków 64KB, a następnie napisanie całego bloku na raz za pomocą fwrite(). Użyłem setvbuf(), aby ustawić wskaźnik FILE * na "Bez buforowania".

Poprawa wydajności nie była tak znacząca, jak się spodziewałem.

Co ważniejsze, wyjście strace pokazało, że dane wciąż były zapisywane 4096 bajtów na raz. Czy ktoś może mi wyjaśnić to zachowanie? Jeśli wywołuję fwrite() z 64 KB danych, dlaczego zapisuje się tylko 4096 bajtów na raz?

Czy istnieje alternatywa dla fwrite() zapisywania danych w rurze za pomocą wskaźnika FILE *?

+0

Czy możesz pokazać nam kod? – tuxuday

+1

@Shailesh_Tainwala: Być może piszesz kod w języku C++, ale jest to raczej pytanie c niż C++. 'fwrite()' jest funkcją c, a nie C++. Dodałem tag c do Twojego pytania, dzięki czemu możesz zdobyć szerszą publiczność. –

Odpowiedz

8

4096 pochodzi z maszyn Linuksowych, które stanowią podłoże dla rurociągów. Występują dwa miejsca. Jedna to przepustowość rurociągu. Pojemność to jedna strona systemowa na starszych wersjach systemu Linux, która wynosi 4096 bajtów na 32-bitowym komputerze i386. (W nowszych wersjach systemu Linux pojemność wynosi 64 KB.)

Innym miejscem, w którym napotkasz problem o wielkości 4096 bajtów, jest zdefiniowana stała liczba gwarantowanych bajtów. W systemie Linux jest to 4096 bajtów. Znaczenie tego ograniczenia zależy od tego, czy ustawiono potok do blokowania, czy nie. Wykonaj man -S7 pipe, aby uzyskać wszystkie szczegóły.

Jeśli próbujesz wymieniać ogromne ilości danych z dużą szybkością, możesz rozważyć ponowne użycie rur. Jesteś na Linuksie, więc pamięcią wspólną jest opcja. Za pomocą potoków można przesyłać stosunkowo niewielkie ilości danych jako mechanizm sygnalizacyjny.

+0

Inną możliwą opcją opartą wyłącznie na systemie Linux byłoby użycie metody open() i splice() zamiast fwrite(). –

4

Jeśli chcesz zmienić zachowanie buforowania, należy to zrobić zaraz po fopen (lub przed każdym I/O, do standardowych uchwytów plików stdin, stdout, stderr). Nie chcesz również wyłączać buforowania i próbować samodzielnie zarządzać buforem; raczej określ swój bufor 64K na setvbuf, aby mógł być używany prawidłowo.

Jeśli naprawdę chcesz zarządzać buforowaniem ręcznie, nie używaj stdio; użyj wywołań niższego poziomu: open, write i close.