• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Funkcje typu Sleep usypiają na dłużej niż powinny

Aruba Cloud - Virtual Private Server VPS
0 głosów
303 wizyt
pytanie zadane 8 czerwca 2019 w C i C++ przez AuriattaDev Początkujący (390 p.)
zamknięte 8 czerwca 2019 przez AuriattaDev
Hej,
Gdy odpalam program na lapku, funkcja Sleep(1) spowalnia się na jakieś 50/100 ms.
Nie zawsze tak jest i niekiedy działa prawidłowo. Procesor i ram w obu przypadkach nie jest przeciążony.
Jest także podłączony do zasilania.
Na początku wydawało mi się że to wina jakiegoś frameworka, teraz to już w ogóle nie wiem.

Używałem dotychczas:
Sleep(1);
this_thread::sleep_for(chrono::nanoseconds(1000000));

Wie może czym może być spowodowany ten niecodzienny błąd?
 

PS: jest to nowy laptop z processorem i5-8250U i 16gb pamięci
komentarz zamknięcia: Problem rozwiązany

1 odpowiedź

+1 głos
odpowiedź 8 czerwca 2019 przez adrian17 Mentor (352,580 p.)
edycja 8 czerwca 2019 przez adrian17
 
Najlepsza

sleep_for()/Sleep()/sleep() to nie jest dokładny timer - mówi tylko "uśpij mnie na X czasu i wzbudź gdy będziesz mógł".

https://en.cppreference.com/w/cpp/thread/sleep_for

This function may block for longer than sleep_duration due to scheduling or resource contention delays.

https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-sleep

The system clock "ticks" at a constant rate. If dwMilliseconds is less than the resolution of the system clock, the thread may sleep for less than the specified length of time. If dwMilliseconds is greater than one tick but less than two, the wait can be anywhere between one and two ticks, and so on

Note that a ready thread is not guaranteed to run immediately. Consequently, the thread may not run until some time after the sleep interval elapses.

(zważ też, że jeśli próbujesz używać go cyklicznie jako "zegar", to do czasu "zegara" trzeba doliczyć czas działania Twojego programu)

komentarz 8 czerwca 2019 przez AuriattaDev Początkujący (390 p.)
Dzięki za info, jedyne co mi przychodzi do głowy to pusta pętla na bazie licznika systemowego. Choć obawiam się że to zeżre procek.
Czy może polecasz jakiś bardziej precyzyjny "Delay"?
komentarz 8 czerwca 2019 przez j23 Mędrzec (195,240 p.)
Może powiedz, po co Ci taki dokładny delay.
komentarz 8 czerwca 2019 przez AuriattaDev Początkujący (390 p.)

Gdy wypisuje na ekranie literki za pomocą cout.
By okno programu przesuwało się płynnie i za każdym razem tak samo:
 

for (int i = -(sizex / 3); i < -1; i += WindowPX_Offset)
    {
        MoveWindow(GetConsoleWindow(), i, 20, sizex / 4, sizey / 2, TRUE);

       //delay
    }


Bądź gdy program czeka na klawisz, by nie zżerało cpu:
 

while(true)
{
		if (GetAsyncKeyState(VK_LCONTROL) & 0x8000)
		{
			break
		}
//delay
}

^ ^

komentarz 8 czerwca 2019 przez j23 Mędrzec (195,240 p.)

Przecież w pierwszej pętli nie potrzeba aż takiej dokładności, +-20ms nie zrobi różnicy (AFAIK w Windowsie dokładność to jakieś 10ms). Zresztą możesz kompensować opóźnienia. W drugiej wystarczy Sleep(1).

komentarz 8 czerwca 2019 przez AuriattaDev Początkujący (390 p.)
U mnie dokładność czasu = szybkość, dlatego jest taka istotna.
Dla mnie ważne jest by czas delay był stały.
Raz się okazuje że efekt jest za wolny a po jakimś czasie za szybki.

W pętli "klawiszowej" chyba faktycznie wystarczy sleep.
komentarz 8 czerwca 2019 przez j23 Mędrzec (195,240 p.)

Dlatego kompensuje się takie opóźnienia. Na systemach takich jak Windows czy Linux nie uzyskasz dużych dokładności, bo systemowy planista musi rozdzielić czas procesora na kilkadziesiąt innych procesów, więc siłą rzeczy dokładność Sleep zależy od obciążenia CPU. Samo MoveWindow może się wykonywać za każdym razem w różnym czasie.

komentarz 8 czerwca 2019 przez AuriattaDev Początkujący (390 p.)
Pierwszy raz słyszę o kompensacji opóźnień.
Mógł byś podać odpowiednik w angielskim?
1
komentarz 8 czerwca 2019 przez adrian17 Mentor (352,580 p.)
edycja 8 czerwca 2019 przez adrian17
Możesz zmierzyć czas jaki faktycznie upłynął i na jego podstawie albo odpowiednio skrócić lub wydłużyć następnego sleepa, albo wziąć zmienny czas pod uwagę przy obliczaniu cokolwiek Twoja aplikacja liczy.
1
komentarz 8 czerwca 2019 przez j23 Mędrzec (195,240 p.)

Czyli mogłoby to wyglądać tak:

using namespace std::chrono_literals;

std::chrono::milliseconds interval = 100ms;

for (int i = -(sizex / 3); i < -1; i += WindowPX_Offset) {
	auto t1 = std::chrono::steady_clock::now();
	
	MoveWindow(GetConsoleWindow(), i, 20, sizex / 4, sizey / 2, TRUE);
	
	auto t2 = std::chrono::steady_clock::now();
	
	std::chrono::milliseconds sleep_time = interval - std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1);
	if (sleep_time.count() <= 0) continue;
	std::this_thread::sleep_for(sleep_time);
}

Samo sleep_for też możesz sprawdzać, czy się nie spóźniło i wtedy uwzględnić to w przesunięciu okna.

komentarz 8 czerwca 2019 przez AuriattaDev Początkujący (390 p.)
Aa rozumiem, faktycznie Adrian.

Czaje j23, potetuję, zobaczę jak to będzie z nanosekundami hah.

Rozwiązanie idealne, dzięki chłopaki : )

Podobne pytania

0 głosów
1 odpowiedź 281 wizyt
pytanie zadane 27 marca 2016 w C i C++ przez niezalogowany
0 głosów
1 odpowiedź 284 wizyt
0 głosów
1 odpowiedź 172 wizyt
pytanie zadane 17 kwietnia 2018 w PHP przez kevin Mądrala (5,010 p.)

93,335 zapytań

142,330 odpowiedzi

322,415 komentarzy

62,669 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...