Javascript pomiar ilosci iteracji

0

Witam wszystkich serdecznie. Mam mały problem. Chciałbym zmierzyć ilość iteracji jakie zostaną wykonane w zadanym czasie. Niestety nie programuje za bardzo w Javascript i sama obsługa Timerów jest dla mnie nie do końca jasna. Po wczytaniu się w temat zrobiłem coś takiego:


function  StartTests ()
{	
	globalStartTests = this;
	this.results = new Array ();    	
	this.timer;

	StartTests.prototype.RunTests = function ()
	{
              this.JakisTest ( 200 );
        }
     
         StartTests.prototype.JakisTest = function ( time_ms )
	{				
		this.time_ms = time_ms;	
		this.JakisTest = 0;			
		this.JakisTestFlag = true;
		
		this.timer = setTimeout ( function () { globalStartTests.JakisTestFlag = false; }, this.time_ms );		

		while ( this.JakisTestFlag == true )
		{
                        // Moje operacje jakie poddaje pomiarowi
			
			this.JakisTestCounts++;
		}
				 
		document.write ( "Wykonano: " +  this.JakisTestCounts + "iteracji<br />" );

        this.results.push ( this.JakisTestCounts );      
	}	
 

Wynikiem działania jest zapętlenie. Nie zostaje zmieniona zmienna JakisTestFlag. Nie bardzo wiem gdzie jest bład. Będę wdzięczny za wszelkie wskazówki.

0

być może w jakiejś przeglądarce to zadziała, ale raczej silniki javascriptu są "jednowątkowe" i mimo złudzenia że setTimeout tworzy nowy "wątek" to tak naprawdę będą zajęte wykonywaniem nieskończonej pętli while, a timer czeka nieruszony

musiałbyś dawać przeglądarce "odetchnąć" powiedzmy co kilka(set) iteracji kończąc i kontynuując po setTimeout(..., 0) - z tym że nie będzie to zbyt dokładne
ewentualnie w pętli po prostu sprawdzać czy minęła już odpowiednia liczba ms - z tym że wynik obejmie też czas wykonywania funkcji czasu
możesz też testy przeprowadzać w ramce, wtedy ramka prawdopodobnie będzie pracować równolegle i będzie mogła zmienić tę flagę

ja na Twoim miejscu sprawdzałbym raczej ile czasu zajmie wykonanie n iteracji - z tego można już prosto też wyliczyć ile iteracji zostanie wykonane w podanym czasie

poza tym małe wskazówki nie mające wspólnego z problemem:

nie musisz używać tu zmiennych globalnych - this możesz przepisać do nowej zmiennej, która będzie widoczna w tym kontekście:

zamiast:
this.timer = setTimeout ( function () { globalStartTests.JakisTestFlag = false; }, this.time_ms );
daj:
var that = this; this.time = setTimeout ( function() { that.JakisTestFlag = false }, this.time_ms );

poza tym nie wiem po co Ci tu prototypy - tylko zaciemniają jak dla mnie

zamiast:
StartTests.prototype.RunTests = function()
wystarczy:
this.RunTests = function()

unikniesz zmiany kodu w stu miejscach gdy będziesz chciał zmienić nazwę klasy

nie używaj document.write bo zmniejszasz elastyczność kodu - nie będziesz mógł tworzyć nowych testów po załadowaniu strony

0

Taką wersję też mam zrobione i to działa bez problemu, niestety zależy mi na zrobieniu tego w ten sposób jaki opisałem. Zgodnie z logiką jaką zaproponowałeś mam już napisane dosyć spore narzędzie - benchmark testujący różne rzeczy. Problem polega na tym, że muszę napisać teraz mini odpowiednik tego narzędzia działający w sposób jaki opisałem. Cała struktura jest napisana już brakuje mi tylko tego elementu odpowiedzialnego za zmianę wartości mojej zmiennej logicznej po określonym czasie...

0

Co do document.write to tylko na potrzeby testowania tego co napisałem. W wersji końcowej tego nie będzie.

0

no niestety, nawet pomysł z ramkami jak się okazuje po sprawdzeniu odpada
spróbowałem też przez window.open otworzyć nowe okno, a potem się do niego dobrać, ale okazuje się, że okna potomne są powiązane ze swoimi rodzicami i ich też zawieszają

tak więc dwa możliwe sposoby opisałem i innych możliwości raczej nie widzę

możesz zrobić jedną iterację, sprawdzić czas i z tego wyliczyć przybliżoną liczbę iteracji potrzebną do wypełnienia 200ms, potem zrobić korektę z czasu rzeczywistego - z punktu widzenia usera nie będzie widać różnicy

0

zauważ że setTimeout też nie jest dokładny
w zależności od obciążenia procesora użytkownika, liczby otwartych stron i tego czy strona jest aktywna w przypadku niektórych przeglądarek, silnik javascript dostaje różne czasy procesora
setTimeout(..., 200) może się wykonać nawet po sekundzie i więcej

0

W sumie racja. To co napisałeś o sprawdzeniu czasu jednej iteracji i aproksymowaniu go ma sens. Jednak czas wykonania będzie bardzo mały - załóżmy, że testuję operacje atomowe. Aproksymacja takiego czasu da bardzo niedokładny wynik. No ale zobaczę co z tego wyjdzie. Dzięki za rady.

0

możesz zrobić jedną iterację żeby mieć rozeznanie czy funkcja nie wykonuje się bardzo długo, a jeśli nie aproksymować z większej próbki, 5ciu i więcej iteracji
mógłbyś rekurencyjnie zwiększać liczbę iteracji uzyskując coraz większą dokładność

0
squal147 napisał(a)

W sumie racja. To co napisałeś o sprawdzeniu czasu jednej iteracji i aproksymowaniu go ma sens.

Nie, sprawdzanie jednej iteracji i aproksymowanie (prawie) nigdy nie ma sensu. Niestety. Chyba że iteracje są bardzo długie, ale przeważnie są bardzo krótkie, dlatego trzeba wykonywać je grupami po N iteracji, przy czym N dostraja się do problemu i maszyny.

Podejście z pierwszego posta jest błędne. Zakłada istnienie wielowątkowości w JavaScripcie. Tymczasem, w JavaScripcie wielowątkowości nie ma -- jest pętla zdarzeń. I jeden wątek. Tak długo, jak długo wykonuje się jakikolwiek kod, tak długo nie zostanie przerwany innym. Jeśli na początku pętli dałbyś setTimeout(callback, 200), a pętla trwałaby 5 minut, to callback nie zostałaby wywołana w ciągu tych 5 minut. Dopiero, gdy JavaScript "nie ma nic do roboty", to wtedy zerka na kolejkę zadań do wykonania, czyli np. timeouty.

Pan @rewfdfggdg ma rację. Napiszę Ci to wyraźnie: tego co chcesz, nie da się zrobić. Namiastkę wielowątkowości dają dopiero WebWorkery z HTML-a 5, ale one nie są dostępne we wszystkich liczących się przeglądarkach. A poza tym, to nie są takie całkiem normalne wątki ze wszystkimi ich możliwościami i zdaje mi się, że i nimi tego nie zrobisz.

Język po prostu nie pozwala na to, co chcesz osiągnąć, tj. podmienienie wartości zmiennej w trakcie wykonywania innego kodu. Jest to niebezpieczne, bo współbieżność jest szalenie skomplikowana. Nawet bardzo doświadczeni programiści mają z nią ogromne problemy, a debuguje się toto koszmarnie. Większość ludzi, którzy piszą w JS-ie, jest bardzo słabymi programistami, więc nie ma sensu dawać im narzędzia aż proszącego o strzał w stopę.

Jakbym ja chciał przerwać wykonywanie iteracji po iluś milisekundach, to użyłbym Date() i w warunku pętli sprawdzałbym, czy już nie czas ją skończyć. Jeśli poszczególne iteracje byłyby bardzo krótkie -- tak krótkie, że tworzenie obiektów Date() wpływałoby istotnie na pomiar -- sprawdzałbym czas co ileś tam iteracji.

0

Ok dziekuję. Ustosunkuję sie do tej wypowiedzi. Ja raczej nie programuje w Javascript a w Java. Tam już są znacznie większe możliwości. Javascript jak dla mnie nie jest specjalnie przydatnym językiem. Jednak w pracy czasem dostaje zadanie tego typu w ściśle określonym języku. Dziękuję za tą wypowiedź.

1

@squall147:
JavaScript jest zupełnie, zupełnie innym językiem niż Java, mimo iż nieco ją udaje jeśli chodzi o składnię. W JavaScripcie nie masz nawet klas, jest dziedziczenie prototypowe -- obiekty dziedziczą po obiektach. To, że jest to mniej popularny sposób dziedziczenia nie oznacza, że jest gorszy lub obiektywnie mniej naturalny. W JS-ie obiekty dziedziczą po innych obiektach, i tyle ("prototyp" to po prostu obiekt połączony z innym specjalnym linkiem umożliwiającym dziedziczenie). Nie ma dodatkowego bytu, jakim są klasy.

W JS-ie ekstremalnie ważna jest funkcyjność, która w Javie jest strasznie uboga; niemal nie istnieje w porównaniu do JS-a. Funkcyjność to ekstremalnie potężna cecha języka programowania, bardzo ułatwia utrzymanie DRY, czy nawet umożliwia bezpośrednią implementację niektórych wzorców projektowych (np. Strategia).

Te najważniejsze cechy JavaScriptu nie są praktycznie dostępne w Javie, która używai innych rozwiązań. Bez dogłębnego poznania sił języka ciężko jest go obiektywnie oceniać. Jasne, że jeśli będziesz próbował kodować w JS-ie tak jak w Javie, to JS będzie w tym dużo gorszy od Javy.

JS ma oczywiście trochę (sporo) błędów projektowych, ale jego rdzeń zawiera kilka bardzo fajnych, bardzo potężnych rzeczy.

Co do wielowątkowości, to A) jej brak jest celowy (o czym wspomniałem) i B) może to wyjść językowi i Twojej aplikacji na dobre (!). I nie mówię tu tylko o obronie przed ludźmi, którzy w wielu wątkach by się zamotali. Mówię o... wydajności. Znasz NodeJS? Istnieją napisane w nim serwery, które radzą sobie sporo lepiej niż Apache. Apache jest napisany w niskopoziomowym C, w NodeJS pisze się w JS (JS też dorobił się JIT-a i kompilacji w locie praktycznie do kodu maszynowego, ale i tak to nie C), a to Node wypada lepiej właśnie ze względu na cechy JS-u. Brak wątków, więc nowe połączenia do serwera nie spawnują żadnych wątków i nie dają żadnego narzutu. Funkcyjność i naturalna asynchroniczność pozwala zaś sprawnie, naturalnie dla JS-owców pisać nieblokujące operacje I/O. I tutaj zyski są takie, że w niektórych zastosowaniach faktycznie Apache wymięka.

JavaScript to nie Erlang czy coś stworzonego do pracy po stronie serwera, ale i tak, jak widać, nawet tam radzi sobie zaskakująco dobrze, nieraz lepiej niż inne języki, bo umożliwia w miarę sprawne korzystanie z innego, efektywniejszego API, które w innych językach byłoby strasznie niewygodne.

Nie uważam, by należało JS lekceważyć. Naturalnie, jeśli Cię ten język nie interesuje, to Twoje prawo. Chcę Ci tylko uzmysłowić, że JS to nie taka zabawka, na jaką może javowcom wyglądać ;).

0

Nie no jasne. Wiem o tym co napisałeś i sie z tym zgadzam. Jednakże każdy ma swoje upodobania i mi jakoś JS średnio sie podoba. Na pewno w rękach utalentowanego programisty to również poteżne narzędzie. Mi po prostu troche ciężko jest się przerzucić z Javy w której pisałem sporo na JS. Może to też wynikać poniekąd z małego doświadczenia z tym językiem. No ale trudno praca to praca, zazwyczaj robię co mi zleca szefostwo. Teraz po prostu wymyśle coś innego. Docelowo moja aplikacja ma za zadanie szybką klasyfikację komputera uzytkownika by można było rozpoznać jaką ilość danych i jakiego typu wysłać do niego by moduł obliczeniowy mógł nad nimi pracować.

Co do lekceważenia języka to nie lekceważę żadnego. Uważam, że nawet takie abstrakcje jak Brainfuck, które nie nadaja się do pisania zarobkowego, mają swoje zalety (programowanie w tym rozwija myślenie).

1 użytkowników online, w tym zalogowanych: 0, gości: 1