Zarządzanie pamięcią pod Windowsem x64

Pracując przy projekcie, który bardzo mocno wykorzystuje obliczenia matematyczne, po raz pierwszy natknąłem się w praktyce na ograniczenia pamięciowe. W pierwszych wersjach systemu nie udało nam się tych ograniczeń zauważyć, gdyż operowaliśmy na małych próbkach danych rzędu 1000x20. Oczywiście należało sprawdzić działanie także dla większej próbki danych i wyskoczyło nam pierwsze z ograniczeń.

Początkowo prace deweloperskie przeprowadzane były na maszynie z systemem 32bitowym z pamięcią 4GB. Występuje tutaj zjawisko ograniczenia pamięci dla procesu do 2GB (ewentualnie do 3GB z odpowiednim przełącznikiem). Przez jakiś czas wystarczał nam obecny limit... Ale po co się ograniczać skoro procesory są 64bitowe? Tak więc po przeinstalowaniu systemu na Windows Server 2008 x64 nastąpiła przedwczesna radość z praktycznie zerowymi limitami (nie mam do dyspozycji serwera z 2TB pamięci RAM ;) ).

Pierwszym problem przy uruchamianiu aplikacji pojawił się z bibliotekami matematycznymi Intel Math Kernel Library, były jeszcze 32bitowe, ale nie sprawiło dużo kłopotów przerobienie jej na wersję 64bitową (aczkolwiek trzeba było trochę doczytać;P ).

W końcu z wielką radością w oczach aplikacja została odpalona i można było patrzeć jak rośnie słupek zajętości pamięci przez proces, urósł do około 4GB. No dobra, ale jakie tutaj są ograniczenia? Okazuje się, że najbliższym limitem jest ciągł obszar jaki można zaalokować. Próba zdefiniowania tablicy typu Byte o liczbie elementów większej niż 2^31 zakończyła się porażką (mniejszą bądź równą - należy wziąć jeszcze narzut platformy .NET - jak najbardziej udało się zaalokować). Dlaczego akurat tablica może mieć rozmiar tylko 2GB? No cóż, wina leży po stronie platformy .NET i środowiska CLR.

Następny krokiem była próba zaalokowania kilku tablic po 2GB każda. Niestety po 6 takich wyświetlił mi się wyjątek OutOfMemoryException (patrz rysunek)

Przyczyną braku pamięci zapewne była wielkość pliku wymiany, gdyż odpowiedni licznik pokazywał ładną liczbę 15999MB (rysunek). Zajętość co prawda wyniosła 14484MB, ale kolejne 2GB tutaj już się nie mieszczą ;)

Ostatecznie muszę stwierdzić, że o ile limit 2GB na wielkość ciągłej pamięci do zaalokowania może boleć (należałoby się zagłębić bardziej w jaki sposób można to obejść), to obszar pamięci dla jednego procesu jest jak na razie nie do zapełnienia dla mnie pożytecznymi danymi, a zawsze można jeszcze zwiększyć rozmiar pliku wymiany.

Warto przeczytać:

  1. BigArray<T>, getting around the 2GB array size limit
  2. Memory Limits for Windows Releases
  3. Zarządzanie pamięcią w 32 i 64-bitowych systemach Windows

Ns2 i Ns3

Ostatnio przypomniały mi się moje laboratoria z sieci komputerowych i telefonii IP. Polegały głównie na łączeniu komputerów, konfigurowania routingów, translacji adresów, podsłuchiwanie sieci. Czasem dostaliśmy również jakiś ciekawszy sprzęt do zabawy (w stylu router Cisco), ale teraz muszę przyznać, że to były straszne nudy.

Obecnie zostałem poniekąd "zmuszony" do zapoznania się z symulatorami sieci i ocenienia, które z nich spełnią odpowiednie wymagania. Kilka takowych się znalazło (m.in. opnet, omnet++),  ale ich wadami są jak zwykle albo trudnodostępność, albo fakt, że nie są już rozwijane od dłuższego czasu. W momencie, gdy dotarłem do ns2 (w sumie to od niego zacząłem tę przygodę:) ) muszę przyznać, że ktoś odwalił kawał dobrej roboty.

ns2 jest to projekt open-source stworzony przez badaczy dla badaczy. Rdzeń symulatora jest napisany w pełni obiektowo w C++, a skrypty eksperymentów (i nie tylko) można pisać w obiektowej wersji Tcl - OTcl. ns2 umożliwa symulowanie praktycznie każdej warstwy modelu OSI/ISO, począwszy od warstwy fizycznej, poprzez sieciową (wraz z włączeniem różnych protokołów routingu), aż po zachowanie się protokołów warstwy transportowej i aplikacji.

W celu przetestowania własnego protokołu (którejkolwiek z warstw) "wystarczy" go tylko zaimplementować w symulatorze. Ostatecznie nie jest to dosyć trudne, gdyż można wzorować się na już napisanych algorytmów.

Efektem działania symulatora jest plik tekstowy w którym zawarte są wszystkie niezbędne informacje na temat każdego z pakietów jaki w naszej wirtualnej sieci podróżował. Wystarczy teraz zaprząc jakiś parser (np. awk), coś do rysowania wykresów (np. gnuplot) i już możemy się cieszyć naszymi wynikami :)

Dodatkowo jeżeli chcielibyśmy wizualnie zobaczyć co się w naszej sieci dzieje można skorzystać z programu NAM (Network Animator) towarzyszącego ns2. Który na podstawie odpowiedniego pliku wynikowego z ns2 stworzy ładną animacje ruchu na poszczególnych połączeniach węzłów.

To tyle jeżeli chodzi o ns2. Chciałbym jeszcze wspomnieć o kolejnej wersji symulatora ns3, która jest w trakcie powstawiania. W przeciwieństwie do ns2, ns3 jest w całości napisana w C++ (ns2 korzysta również z OTcl) i jak na razie skrypty eksperymentów to są programy napisane w C++ (aktualnie powstają bindingi do pythona). Ciekawostką jeżeli chodzi o ns3 jest to, że wspiera on format plików pcap, dzięki czemu możemy bezproblemowo odczytać wyniki naszej symulacji albo poprzez tcpdump, albo wireshark <-- czyż to nie jest dużo wygodniejsze niż pliki tekstowe? :P

Więcej informacji można znaleźć na stronie symulatora:

  1. ns2 i nam
  2. ns3