SFML pożera procesor


(kijek) #1

Witam. Nie jestem do końca pewien, czy to odpowiedni dział, ale problem dotyczy biblioteki graficznej, więc...

Ale zacznijmy od początku. No więc szukałem jakiejś alternatywy dla Allegro i natknąłem się na SFML. Po krótkiej lekturze informacji na jej temat, zabrałem się do pisania pierwszego programu. Kompilacja przebiegła sprawnie, pozostało już tylko odpalić program. I tutaj byłem bardzo zdziwiony. O ile bez włączonego programu w SFML zużycie procesora wynosiło około 40% na każdy rdzeń, to po włączeniu pierwszy rdzeń jest wykorzystywany w stu procentach, a drugi w osiemdziesięciu. Moje pytanie brzmi więc, czy jest to normalne dla tej biblioteki, czy może po prostu ja mam coś nie tak.

Kod:

#include 


int main()

{

	sf::Window Okno(sf::VideoMode(800, 600, 32), "Hello!");


	while(Okno.IsOpened())

	{

		sf::Event Zdarzenie;


		while(Okno.GetEvent(Zdarzenie))

		{

			if(Zdarzenie.Type == sf::Event::Closed)

			{

				Okno.Close();

			}

		}


		Okno.Display();

	}


	return EXIT_SUCCESS;

}

Wersja GCC: 4.5.2

Wersja SFML: 1.6

System: Ubuntu 11.04


(Ryan) #2

Struktura kodu powoduje, że masz ciasną pętlę - while z GetEvent się wykonuje tylko jak coś się dzieje, więc zasadniczo masz "nieskończoną" pętlę while, w której non stop wołasz Okno.Display(). Jeśli CPU nie czeka wtedy na GPU, to Display() wykonuje się bardzo szybko i cykl się powtarza. To trochę tak, jakbyś odpalił sobie program "int main(){while(1);}". :slight_smile: Zmierz ile razy na sekundę wywołujesz Okno.Display(), pewnie setki. A wystarczy wołać je co 33ms dla 30FPS albo co 16-17ms dla 60FPS. Prawdopodobnie już samo czekanie na vsync (UseVerticalSync(true)) powinno Ci pomóc. Jeśli chcesz mieć zablokowaną częstotliwość odświeżania, to poszukaj odpowiedniego tutka na http://www.sfml-dev.org/


(kijek) #3

Niestety, UseVerticalSync(true); pomimo iż zmniejszyło ilość wykonań pętli na sekundę, nie zmniejszyło obciążenia procesora. Jednak sf::Sleep(0.033); wydaje się załatwiać sprawę. Dzięki :slight_smile:


(Ryan) #4

To nie do końca to, co powinieneś zrobić. :wink: Nie masz mieć 33ms przerwy między wywołaniami Display, a renderowanie co 33ms. :slight_smile: Zatem czekać powinieneś "33ms - czas_wykonania_display".


(Fiołek) #5

Tak szczerze powiedziawszy, to ten czas powinien być mniejszy niż "33ms - czas_wykonania_display" - nie możemy mieć pewności, że Sleep będzie wystarczająco dokładne(a raczej możemy być pewni, że nie będzie - skok, powrót, obsługa przez system też zajmie dodatkowy czas, do tego Sleep może nie mieć wystarczającej rozdzielczości).

SFML został stworzony do gier, a gry nie muszą się przejmować, czy zużywają "cały procesor" czy też nie. W ostateczności możesz użyć Sleep(0) by oddać systemowi czas, który przeznaczył na wątek. Do poczytania.

EDIT: tak teraz przyuważyłem... Lerhes na forum Warsztatu radzi Ci poszukać na innych tematów na forum - popieram go. Na pewno znajdziesz tam dość konstruktywną i dość długą konwersację na ten temat, niekoniecznie będzie identyczna z tym, czego szukać, ale wnioski, które będziesz mógł wyciągnąć, znajdą zastosowanie w tym, co robisz.


(Ryan) #6

Gry powinny się przejmować tym, czy zużywają cały procesor. Jeśli nie muszą, to po co miałyby to robić? Poza tym nigdzie nie sugerowałem używania Sleepa a odczekiwanie do końca czasu klatki. Czy będzie to zrealizowane sleepem czy w inny sposób - bez większego znaczenia w amatorskim kodzie. Szczególnie, że zależnie od platformy "dobre" rozwiązanie oznacza różne podejście.