2013-09-03 10 views
7

że następujący problem:zero duża odwzorowanie pamięci w `madvise`

przydzielić sporą część pamięci (wielokrotne listwy) poprzez mmap z MAP_ANONYMOUS. Ten fragment zawiera dużą mapę mieszania, która musi być wyzerowana co jakiś czas. Nie całe mapowanie może być użyte w każdej rundzie (nie każda strona jest uszkodzona), więc memset nie jest dobrym pomysłem - trwa zbyt długo.

Jaka jest najlepsza strategia, aby szybko to zrobić?

Will

madvise(ptr, length, MADV_DONTNEED); 

gwarancja mi, że wszelkie późniejsze dostępy dostarczenie nowych pustych stron?

Na stronie Linux man madvise:

Ta rozmowa nie wpływa semantyki aplikacji (z wyjątkiem przypadku MADV_DONTNEED), ale może mieć wpływ na jego wydajność. Jądro może ignorować porady.

...

MADV_DONTNEED

Kolejne dostępy stron w tym zakresie będzie się uda, ale spowoduje zarówno w przeładunku zawartości pamięci z podstawowej odwzorowanym pliku (patrz mmap (2)) lub strony o zerowym wypełnieniu na żądanie w przypadku odwzorowań bez bazowego pliku.

...

Obecna implementacja Linux (2.4.0) postrzega to jako wywołanie systemowe więcej niż polecenia jako porady ...

Albo muszę munmap i przemapować region nowo?

To musi działać na Linuksie, a najlepiej mieć takie samo zachowanie w Mac OS X.

+0

Nie mam żadnego sposobu, aby to przetestować, ale FWIW, [OSX] (https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man2/madvise.2. html) strona man nie wspomina nic o 'madvise'd stronach zero. Wersja [posix] (http://pubs.opengroup.org/onlinepubs/009695399/functions/posix_madvise.html) też nie. Czy koszty są ogromne, aby zmnieszyć pamięć? – Collin

+0

@Collin To nie jest zbyt duża wydajność, ale musiałbym zawiesić moje wątki i jeśli to konieczne zaktualizować wskaźnik do nowego mapowania. To jest bardziej równoległy kod, który może pójść źle ... I jestem ciekawy, jak to połączenie naprawdę działa. –

Odpowiedz

7

Jest znacznie łatwiejsze rozwiązanie problemu, który jest dość przenośne:

mmap(ptr, length, PROT_READ|PROT_WRITE, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); 

Od MAP_FIXED wolno zawieść do dość dowolnych powodów implementacji specyficznych spada z powrotem do memset jeśli zwróci MAP_FAILED byłoby wskazane .

+0

Dziękuję, właśnie tego szukałem. Działa to nawet na moim OS X. –

+3

W przypadku, gdy nie jest to jasne, chodzi o ponowne "mmap()" z adresem MAP_FIXED wskazującym na część (lub całą) pamięci poprzednio-mmapped. Zgodnie z dokumentacją spowoduje to wyrzucenie poprzedniej strony, a nowe nowe strony zostaną zmapowane. –

+0

W jaki sposób ta lepsza wydajność jest mądra? Kernel wciąż musi zerować stronę. Tak więc byłoby gorzej niż memset w przestrzeni użytkownika, ponieważ jest narzut związany z wywołaniem systemowym, wykonywaniem logiki mmap, a następnie zerowaniem strony. (Chociaż OP jest prawdopodobnie zakończony pytaniem, nadal jestem ciekawy, myślę, że memset nadal będzie najlepszą rzeczą do zrobienia) –

1

Ten madvise zachowanie z pewnością nie jest standard, więc nie byłoby to przenośne.

Jeśli część, z której chcesz wyzerować, znajduje się na końcu mapy, możesz uciec z ftruncate.Trzeba wprowadzić jeden krok dalej:

  1. shm_open mieć „trwałe” deskryptor pliku z danymi
  2. ftruncate do potrzebnej wielkości
  3. mmap tego FD

Następnie zawsze mogłeś

  1. munmap
  2. ftruncate do czegoś krótkim
  3. ftruncate do rzeczywistej długości trzeba
  4. mmap ponownie

a następnie część, że „odwzorować” byłby zerowy zainicjowany.

Należy jednak pamiętać, że system musi zerować strony. To może być nieco bardziej wydajne niż wbudowane rzeczy, które kompilator produkuje dla memset, ale to nie jest pewne.

+0

Po prostu muszę zerować całe mapowanie, długość pozostaje taka sama. gdybym chciał przejść przez id munmap, po prostu wywołaj 'munmap',' mmap/MAP_ANONYMOUS'. Nie trzeba robić tego tak skomplikowanego. Naprawdę nie chcę przechodzić przez etap, w którym przestrzeń VM jest tymczasowo odwzorowywana, ale zerować ją, jeśli strony są brudne i najlepiej zwolnić fizyczną pamięć RAM, dopóki nie zostanie ponownie wykorzystana. –

+1

'munmap', po którym następuje' mmap' nie jest bezpieczne. Ma stan wyścigu; zakres zostanie natychmiast usunięty z mapy, a inny wątek może uzyskać mapowanie w regionie lub po prostu odpaść od próby uzyskania dostępu do regionu. Zobacz moją odpowiedź na bezpieczne podejście. –

+0

@R .., pytanie nie wspomina nici. Ale na pewno, jeśli zmienisz mapowanie pod nogami, musisz upewnić się, że żaden inny wątek nie ma do niego dostępu. Jeśli nie wynika to jasno z zastosowania, powinno to być zapewnione przez pewnego rodzaju blokowanie. Ale to wykracza daleko poza pytanie, jakie jest postawione.Twoje rozwiązanie ma tę wadę, że zależy od konkretnego zachowania. –

1

W systemie Linux można polegać na MADV_DONTNEED na anonimowym odwzorowaniu zerującym odwzorowanie. Nie jest to jednak przenośny - sam w sobie nie jest standaryzowany. posix_madvise() jest standaryzowany, ale POSIX_MADV_DONTNEED ma , a nie ma takie samo zachowanie, jak flaga Linuksa - zawsze ma charakter doradczy i nie wpływa na semantykę aplikacji.

Powiązane problemy