Wskazówki dotyczące poprawiania kodu wrażliwego na czas
Pisanie kodu szybki wymaga opis wszystkich aspektów aplikacji i sposób interakcji z systemem.W tym temacie sugeruje alternatywy dla niektórych bardziej widocznych technik kodowania pomaga upewnić się, że czas krytyczne fragmenty kodu pomyślnie wykonać.
Aby podsumować, poprawy krytycznym kodu wymaga, aby użytkownik:
Wiedzieć, które części programu muszą być szybkie.
Sprawdzaj, wielkości i szybkości kodu.
Znasz koszt nowych funkcji.
Znasz minimalna pracy wymaganej do wykonania zadania.
Aby zebrać informacje dotyczące wydajności kodu, można użyć Monitora wydajności (perfmon.exe).
Sekcje w tym artykule
Chybień w pamięci podręcznej i błędów stron
Sortowanie i wyszukiwanie
MFC oraz bibliotek klas
Udostępnione biblioteki
Stert
Wątki
Zestaw roboczy mały
Chybień w pamięci podręcznej i błędów stron
Pominięte trafień w pamięci podręcznej, na obu wewnętrznego i zewnętrznego pamięci podręcznej, a także błędów stron (przejść do pomocniczego magazynu dla danych i instrukcje programu) zmniejszyć wydajność programu.
Trafienie pamięci podręcznej Procesora może kosztów programu zegar cykle 10 – 20.Zewnętrzna pamięć podręczna trafień może kosztów cykle zegara 20 — 40.Błąd strony można kosztów cykle zegara milion (zakładając, że procesor obsługujący 500 milionów instrukcje/sekundę i godzina milisekunda 2 dla błąd strony).Dlatego też jest w najlepszy odsetek wykonywania programu pisanie kodu, który spowoduje zmniejszenie liczby trafień w pamięci podręcznej pominiętych i błędów stron.
Jedną z przyczyn powolne programy jest wykonać więcej błędów stron lub utracić pamięci podręcznej częściej niż jest to konieczne.Aby tego uniknąć, należy używać struktury danych z dobrą miejscowości odwołania, co oznacza grupowanie elementów pokrewnych.Czasami struktury danych, która wygląda wspaniałe okaże się horrible z powodu niska miejscowości odwołania, a czasami odwrotnej ma wartość true.Oto dwa przykłady:
Przydzielany dynamicznie połączonej listy można zmniejszyć wydajność programu, ponieważ podczas wyszukiwania dla elementu lub na końcu przechodzenie przez listę, każdego łącza pominięto może utracić pamięci podręcznej lub spowodować błąd strony.Implementacja listy, tablice proste w oparciu o faktycznie może być szybciej, z powodu lepsze buforowanie i mniejszą liczbę błędów stron nawet — biorąc pod uwagę, że tablica trudniej wraz ze wzrostem jej, nadal może być szybciej.
Tabele zbędnych danych użycia dynamicznie przydzielane połączonej listy może spowodować obniżenie wydajności.Przez rozszerzenie, tabele zbędnych danych używać list połączonych dynamicznie przydzielone do przechowywania ich zawartość może wykonywać znacznie niższa.W rzeczywistości końcowa analiza liniowy prosty wyszukiwanie za pomocą tablicy może mieć w rzeczywistości szybciej (w zależności od okoliczności).Tabele na podstawie tablicy wartości skrótu (tzw "zamkniętej tworzenia skrótów") jest implementacją często pomijane często mający wyższego poziomu wydajności.
Sortowanie i wyszukiwanie
Sortowanie jest założenia czasochłonne w porównaniu z wielu typowych operacji.To najlepszy sposób, aby uniknąć niepotrzebnych spowolnienie w celu uniknięcia sortowanie w czasie krytyczne.Może mieć możliwość:
Wstrzymuje sortowanie czasu wydajności — niekrytyczny.
Sortowanie danych w czasie wcześniejszego, wydajności — niekrytyczny.
Sortowanie tylko część danych, które naprawdę potrzebuje sortowania.
Czasami można tworzyć listy posortowane.Należy zachować ostrożność, ponieważ do wstawienia danych posortowane należy może wymagać bardziej skomplikowane struktury danych z lokalizacji niska odwołania, prowadzących do chybień w pamięci podręcznej i błędów stron.Nie ma żadnych metody, która działa w każdym przypadku.Spróbuj kilka sposobów i zmierzyć różnice.
Oto niektóre ogólne porady dotyczące sortowania:
Użyj podstawowego sortowania, aby zminimalizować usterki.
Wszelkie prace, które można wykonać wcześniej uproszczeniu sortowanie jest zastanowić.Jeśli jednorazowe przebiegu nad danych ułatwia porównanie i zmniejsza sortowanie od O (n dziennika n) do O(n), będzie prawie na pewno wrócisz naprzód.
Zastanowić miejscowości odwołania algorytm sortowania i przypuszczasz, działanie na dane.
Dostępne są mniej alternatyw wyszukuje niż sortowanie.Jeśli wyszukiwanie jest krytycznym, binary wyszukiwania tabeli wyszukiwania lub skrót prawie zawsze najlepiej jest, ale podobnie jak w przypadku sortowania, miejscowości musi należy pamiętać.Liniowy wyszukiwania za pośrednictwem małych tablicy można szybciej niż binary wyszukiwania za pośrednictwem struktury danych z wiele wskaźników powodujący błędów stron lub przechowywania chybień w pamięci podręcznej.
MFC oraz bibliotek klas
Microsoft Foundation Classes (MFC) może znacznie upraszczają pisania kodu.Podczas pisania kodu krytycznym, należy pamiętać o obciążenie związane z niektórych klas.Należy sprawdzić, czy kod MFC wykorzystania przez krytycznym kod, aby sprawdzić, czy spełnia wymagań dotyczących wydajności.Poniższa lista zawiera klas MFC i funkcje, które należy zwrócić uwagę:
CStringBiblioteka czasu C przydzielić pamięci dla wywołuje MFC CString dynamicznie.Ogólnie rzecz biorąc CString jest tak wydajna, jak inny ciąg dynamicznie przydzielane.Podobnie jak w przypadku dowolny ciąg dynamicznie przydzielone, cechuje się przeciążenia alokacji dynamicznego i wersji.Często prosty char tablicy na stosie może obsługiwać te same funkcje i jest szybsza.Nie używam CString do przechowywania stałych ciąg.Użyj const char * zamiast niego.Każde działanie, które można wykonywać za pomocą CString obiekt ma pewną redundancję.Przy użyciu biblioteki czasu wykonywania ciąg funkcji może być szybciej.
CArrayElement CArray zapewnia elastyczność nie regularne tablicy, że program może nie być konieczne który.Jeśli znasz określonych limitów tablicy globalne tablicy stałych można użyć zamiast tego.Jeśli użyjesz CArray, użyj CArray::SetSize do ustanawiania jego rozmiar i określić liczbę elementów, według których rozrasta, gdy konieczne jest ponowne przydzielenie.W przeciwnym razie Dodawanie elementów może powodować tablica często ponownie przydzielona i kopiować, który jest nieefektywne i może fragment pamięci.Również należy pamiętać, że jeśli element zostanie wstawiony do tablicy, CArray przesuwa kolejnych elementów w pamięci i może być konieczne zwiększania tablicy.Działania te mogą powodować chybień w pamięci podręcznej i błędów stron.Jeśli patrzysz za pośrednictwem kodu, który używa MFC, możesz zobaczyć, że może zapisywać bardziej specyficznym dla swojego scenariusza w celu zwiększenia wydajności.Ponieważ CArray jest szablon, na przykład można określić CArray specjalizacji dla określonego typu.
CList CList jest podwójnie połączonej listy, dzięki czemu można wstawienie elementu przy head, uchwyt, a na znanym pozycji (POSITION) na liście.Wyszukiwanie elementu przez wartość lub nieprawidłowy indeks wymaga kolejnych wyszukiwania, jednak może być powolne, jeśli lista jest długa.Jeśli Twój kod nie wymaga podwójnie połączonej listy warto rozważenia za pomocą CList.Przy użyciu pojedynczo połączonej listy zapisuje przeciążenia aktualizowanie dodatkowe wskaźnik dla wszystkich operacji, a także pamięci dla tego wskaźnika.Więcej pamięci nie jest doskonałe, ale jest inna możliwość chybień w pamięci podręcznej lub błędów stron.
IsKindOfTa funkcja może wygenerować wiele wywołań i dostęp do dużej ilości pamięci w obszarach danych różnych prowadzące do nieprawidłowych miejscowości odwołania.Jest to przydatne w przypadku kompilację debugowania (w wywołaniu potwierdzenia, na przykład), ale należy unikać używania go w wersji kompilacji.
PreTranslateMessageUżyj PreTranslateMessage po określonego drzewa systemu windows wymaga różnych klawiszy skrótów lub podczas obsługi komunikatu należy wstawić do pompowania komunikatów.PreTranslateMessageZmienia MFC wysyłania wiadomości.Jeśli użytkownik musi zostać zastąpiona w PreTranslateMessage, więc tylko na poziomie konieczne.Na przykład, nie jest konieczne do zastąpienia CMainFrame::PreTranslateMessage Jeśli chcesz tylko wtedy, gdy wiadomości, przechodząc do obiektów podrzędnych określonego widoku.Zastąp PreTranslateMessage widoku zamiast klasy.
Nie stanowi obejścia ścieżki normalnego wysyłania za pomocą PreTranslateMessage do obsługi wszystkie wiadomości wysłane do dowolnego okna.Użyj procedury okna i map MFC wiadomości do tego celu.
OnIdleZdarzenia bezczynności może wystąpić w czasie nie będzie, takich jak między WM_KEYDOWN i WM_KEYUP zdarzenia.Zegary mogą być bardziej wydajnej metody do wyzwolenia kodu.Wymusza OnIdle do wywoływania regularnie przez generowanie wiadomości false lub zawsze zwraca TRUE z zastąpienia z OnIdle, który umożliwić swojego wątku uśpienia.Ponownie czasomierz lub oddzielnym wątku może być bardziej odpowiednie.
Udostępnione biblioteki
Pożądane jest ponowne użycie kodu.Jednak jeśli chcesz użyć innego użytkownika kodu, należy upewnij się, że wiesz dokładnie co robi w przypadkach, gdzie wydajności jest krytyczne dla użytkownika.Najlepszy sposób, aby poznać to jest krokowe wykonywanie kodu źródłowego lub pomiaru przy użyciu narzędzi, takich jak PView lub monitora wydajności.
Stert
Za pomocą wielu stert na własne ryzyko.Dodatkowe stert utworzone za pomocą HeapCreate i HeapAlloc pozwalają zarządzać, a następnie usuwa zbiór pokrewnych alokacji.Nie Zatwierdź zbyt dużej ilości pamięci.Jeśli używasz wielu stert, należy zwrócić szczególną uwagę na ilość pamięci, który jest początkowo zatwierdzone.
Zamiast wielu stert można za pomocą funkcji pomocnika interfejs między kodu i stosu domyślny.Funkcje pomocników ułatwienia strategie alokacji niestandardowych, które można zwiększyć wydajność aplikacji.Na przykład często wykonywać małych alokacji, warto lokalizowanie tych przydziałów do części stosu domyślny.Można przydzielić dużych bloków pamięci i następnie użyć funkcji pomocnika do podrzędnej z tego bloku.Jeśli tak, nie ma dodatkowych stert z pamięci, ponieważ przydział wystawała z stosu domyślny.
W niektórych przypadkach jednak przy użyciu stosu domyślny można zmniejszyć miejscowości odwołania.Użyć podglądu procesu, Spy ++ lub monitora wydajności do pomiaru skutki przenoszenie obiektów stosu stosu.
Miary swoje stert, więc może konta dla każdej alokacji na stosu.Użyj czasu wykonywania C debugowanie procedury stosu do punktu kontrolnego i zrzut swojego stosu.Można odczytać dane wyjściowe do programu arkusza kalkulacyjnego, takich jak program Microsoft Excel i tabel przestawnych umożliwia wyświetlanie wyników.Należy zauważyć, łączną liczbę, rozmiar i stopień rozproszenia alokacji.Porównaj te o rozmiarze zestawów roboczych.Również wyświetlać klastrowanie o rozmiarze związane z obiektów.
Można także użyć liczniki wydajności do monitorowania wykorzystania pamięci.
Wątki
Dla zadania w tle efektywne bezczynności obsługi zdarzeń może być szybsza niż przy użyciu wątków.Łatwiej zrozumieć miejscowości odwołania w programie jednowątkowy.
Regułą jest używanie wątku, tylko wtedy, gdy powiadomienie systemu operacyjnego, które można zablokować na w katalogu głównym pracy tła.Najlepszym rozwiązaniem w takim przypadku jest wątek, ponieważ jest niemożliwe do blokowania głównym wątku na zdarzenie.
Wątki również powodować problemy z komunikacją.Można zarządzać łącze komunikacji między wątki, z listą wiadomości lub przydzielanie i używanie pamięci współużytkowanej.Zarządzanie łącze komunikacyjne zwykle wymaga synchronizacji, aby uniknąć Sytuacje wyścigu i zakleszczenie problemów.Taki poziom złożoności można łatwo przekształcić usterki i problemów z wydajnością.
Aby uzyskać więcej informacji, zobacz przetwarzania pętlę bezczynności (%) i Multithreading.
Zestaw roboczy mały
Mniejszych zestawów roboczych oznacza lepszą miejscowości odwołania, mniejszą liczbę błędów stron i więcej trafień w pamięci podręcznej.Zestaw roboczy procesu jest najbliższego Metryka przez system operacyjny bezpośrednio do pomiaru miejscowości odwołania.
Aby ustawić górny i dolny limit zestawu roboczego, należy użyć SetProcessWorkingSetSize.
Aby uzyskać górny i dolny limit zestawu roboczego, należy użyć GetProcessWorkingSetSize.
Aby wyświetlić rozmiar zestawu roboczego, należy użyć Spy ++.