• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Javascript: Funktion in Objekt übergeben und als Property speichern.

Sollte er aber (ich kenne jetzt die Browserimplementation nicht so gut, dass ich sagen könnte, dass jeder Browser das kann). Vor jedem neuen Bildschirmbildaufbau ist ein guter Renderzeitpunkt.
was meinst du denn mit Bildschirmbildaufbau? den inhalt des grafikspeichers auf den monitor projizieren?
damit hat der browser gar nichts zu tun. der browser ist nur ein fenster von 100en die angezeigt werden.
der browser zeichnet nicht direkt in den grafikspeichers. das läuft änderungsgesteuert. unter windows jedenfalls und das wird überall ähnlich laufen.
der browser macht eine änderung, die sich auf die anzeige auswirkt, daraufhin meldet er das dem BS (UpdateWindow)
das BS sendet an den browser eine WM_PAINT message
der browser zeichnet seine änderungen in ein abstraktes device
um den rest kümmert sich das BS

Code:
Chrome:
	animation: mean: 19.922310756972113 ± 1.395760598544772
	setTimeout: mean: 4.93339911198816 ± 0.5161472008683037
Firefox:
	animation: mean: 20.044088176352705 ± 2.0263940055111886
	setTimeout: mean: 4.156691604322527 ± 2.249589162193331
IE:
	animation: mean: 20.014 ± 1.240082255336312
	setTimeout: mean: 3.360551075268817 ± 1.4161283800521635
Opera:
	animation: mean: 19.882703777335983 ± 1.3227475493268288
	mean: 4.995504495504496 ± 0.1563819520112744

damit können wir eigentlich hier aufhören, ich sehe hier keine großartigen unterschiede in den abweichungen zw. animation und setTimeout, worum es ja ursprünglich ging

Auch sieht man, dass zwar ca. alle 4ms eigentlich ein neues Rendern nötig ist (der Zufallstext hat sich geändert) aber trotzdem nur alle 20ms der Repaint ausgeführt wird...
weil 4ms ja auch nicht nötig ist bzw. die 20ms, oder wie du selbst sagtest, die bildfrequenz des monitors sicher schon ein gutes bewegtes bild erzeugen.
laut wikipedia:
Das menschliche Gehirn nimmt ab etwa 14 bis 16 Bildern pro Sekunde (individuell verschieden) aufeinanderfolgende Bilder als bewegte (aber nicht unbedingt ruckelfreie) Szene wahr
warum sollte man da öfter ändern als überhaupt dargestellt wird?

Wenn mein Monitor 50 Hz hat, hab' ich alle 20 ms einen idealen Renderzeitpunkt... das kann man wunderbar vorhersehen... also ich kann das.
so arbeitet aber keine anwendung

Der Test oben zeigt etwas anderes. Aber jetzt verstehe ich allmählich, was dein Punkt ist.
wenn ich einen test mache, mit einem button(so, dass der browser nicht intern optimieren kann und so evtl. timeouts mit animationen zusammenlegt), bekomme ich bei 1000 aufrufen ohne den button zu drücken so zw. 30 und 60 abweichungen größer 1ms vom mittelwert
wenn ich jetzt den button zwischendurch immer mal drücke, welcher ein element ins dom einfügt, werden das 200 bis 250 abweichungen
 
was meinst du denn mit Bildschirmbildaufbau? den inhalt des grafikspeichers auf den monitor projizieren?
Ja. Das was ich zu sehen bekomme.
damit hat der browser gar nichts zu tun. [...]
Mir ist schon klar, dass sich der Browser nicht selbst um den Monitor kümmert. Aber wenn der Grafikspeicher nur alle 20ms "projiziert" wird, ist es nicht sinnvoll einen Vorgang, der sehr aufwändig ist und nur dort zu sehen ist, öfters durchzuführen.

damit können wir eigentlich hier aufhören, ich sehe hier keine großartigen unterschiede in den abweichungen zw. animation und setTimeout, worum es ja ursprünglich ging
Stimmt - ich hatte ehrlich gesagt mehr Streuung beim setTimeout erwartet. Aber da alles nicht genau ist, sollte man seine Animationen immer mit einem Date-Objekt (oder mit window.performance, wo verfügbar) steuern.


weil 4ms ja auch nicht nötig ist bzw. die 20ms, oder wie du selbst sagtest, die bildfrequenz des monitors sicher schon ein gutes bewegtes bild erzeugen.
laut wikipedia:

warum sollte man da öfter ändern als überhaupt dargestellt wird?
Genau das ist ja mein Punkt. Es ändert sich 5 mal das DOM, aber es wird nur ein Repaint und damit nur einmal das requestAnimationFrame ausgeführt.


so arbeitet aber keine anwendung
Das glaube ich nicht. Alles was eine flüssige Darstellung braucht wird sich auf die Grafikkarte und damit den Monitor abstimmen. Sonst bekommst du, trotz dem 50 Hz, ruckelige Bilder (wenn du z.B. etwas in den Grafikspeicher schreibst, während der gerade ausgelesen wird - das ergibt ganz fiese Effekte). Z.B. ein Grafikintensives Spiel wird das Rendern nur so häufig wie nötig machen - wobei das die Hauptarbeit natürlich auf die Grafikkarte abwälzt.


wenn ich einen test mache, mit einem button(so, dass der browser nicht intern optimieren kann und so evtl. timeouts mit animationen zusammenlegt), bekomme ich bei 1000 aufrufen ohne den button zu drücken so zw. 30 und 60 abweichungen größer 1ms vom mittelwert
wenn ich jetzt den button zwischendurch immer mal drücke, welcher ein element ins dom einfügt, werden das 200 bis 250 abweichungen
Zeig' mir bitte deinen Code. Hat sich bei der Messung der Mittelwert verschoben? Bitte Zahlen.

Wenn ich sowas einbaue (und dazu auch noch das window.setTimeout() unverhersehbar mache):
Code:
<!DOCTYPE html>

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Fenstertitel</title>
<script type="text/javascript" src="/kkjs/modules/kkjs.load.js?modules=Timer,sprintf"></script>
</head>
<body>
	Running...
	<div id="timer"></div>
	<div id="animationResult"></div>
	<div id="normalResult"></div>
	<button id="userButton">click (<span id="clickCount">0</span>)</button>
<script type="text/javascript">
function generateTimer(output){
	var t = new kkjs.Timer(10000);
	var lastNow = Date.now();
	var sum = 0;
	var count = 0;
	var sum2 = 0;
	t.on("tick", function(){
		var now = Date.now();
		var diff = now - lastNow;
		sum += diff;
		count += 1;
		sum2 += diff * diff
		lastNow = now;
	});

	t.on("timeOver", function(){
		t.stop();
		output.innerHTML = kkjs.sprintf(
			"mean: %f ± %f",
			sum / count,
			Math.sqrt(sum2/count - sum*sum/count/count)
		);
	});
	return t;
}

var t = generateTimer(kkjs.$("animationResult"));
t.animation = true;

var t2 = generateTimer(kkjs.$("normalResult"));
t2.tickTime = 0;
t2.on("tick", function(){
	this.tickTime = Math.random() * 50;
	kkjs.$("timer").innerHTML = this.getTimeString() + " (" + Math.random() + ")";
});

t2.start();
t.start();

count = 0;
kkjs.event.add(kkjs.$("userButton"), "click", function(){
	count += 1;
	kkjs.$("clickCount").innerHTML = count;
});
</script>
</body>
</html>
bekomme ich auch so gut wie das Gleiche (außer beim FF - aber der hat bei mir auch das schlechteste Renderverhalten):
Code:
Chrome:
mean: 19.922310756972113 ± 1.2368593110062804
mean: 24.330900243309003 ± 14.117080607653715
click (81)

Firefox:
mean: 20.34349593495935 ± 5.2759134351490955
mean: 26.497354497354497 ± 15.307820160972655
click (101)

IE:
mean: 20.024 ± 1.2631009460846667
mean: 31 ± 17.709209442298867
click (103) 

Opera:
mean: 19.88667992047714 ± 1.4202040815092656
mean: 25.648717948717948 ± 14.314138103231917
click (101)
- das setTimeout streut jetzt natürlich viel mehr, da es auf zufällige Werte zwischen 0 und 50ms gestellt wurde - vor jedem Tick.
Da kann der Browser jetzt gar nichts optimieren, da er nichts weiß.

Ich denke mal, dass bei deinem Test das Erzeugen des DOM-Elements das ganze unter Last legt - und JS-Timing mit Last ist nie präzise. Bei mir wird nur der Text des <button>s geändert - aber auch das muss neu gezeichnet werden.
 
Mir ist schon klar, dass sich der Browser nicht selbst um den Monitor kümmert. Aber wenn der Grafikspeicher nur alle 20ms "projiziert" wird, ist es nicht sinnvoll einen Vorgang, der sehr aufwändig ist und nur dort zu sehen ist, öfters durchzuführen.
sicher
"projiziert" - gefällt dir nicht? mir fiel nichts besseres ein

Genau das ist ja mein Punkt. Es ändert sich 5 mal das DOM, aber es wird nur ein Repaint und damit nur einmal das requestAnimationFrame ausgeführt.
meiner nicht, so wie es zwischenschritte geben muss, ist es sinnvoll (nicht zwingend) die updaterate auf einen wert zu begrenzen. ob das die monitorfrequez ist kann ich nicht sagen, scheint aber so. vermutet hätte ich einen wert leicht größer als diese.


Das glaube ich nicht. Alles was eine flüssige Darstellung braucht wird sich auf die Grafikkarte und damit den Monitor abstimmen.
ist aber so, die einen haben eine fps von 120 die anderen von 30, je nach cpu/grafikkarte

Sonst bekommst du, trotz dem 50 Hz, ruckelige Bilder (wenn du z.B. etwas in den Grafikspeicher schreibst, während der gerade ausgelesen wird - das ergibt ganz fiese Effekte).
Tearing
deshalb wird ja ab vista auch gepuffert
es gibt im bereich der spiele, die directx nutzen auch möglichkeiten sich mit der grafikkarte zu syncronisieren, das wird aber immer nur optional angeboten, weil du damit deine fps künstlich begrenzt, da du immer wartest, bei 50Hz monitor und ner 51er fps kein problem, aber aus ner 49er fps die möglich wären machst du 25.

Zeig' mir bitte deinen Code.
reich ich morgen nach
EDIT:
Code:
<!DOCTYPE html>
<html>
  <head>
    <title>test</title>
    <style>
      .animation {
        position:absolute;
        width:20px;
        top:40px;
        left:20px;
        color:#ffffff;
        background-color:#00ff00;
      }
    </style>
    <script>
      window.addEventListener("load", function()
      {
        var addButtonClickHandler = function()
        {
          var elems = 0;
          var div = null;
          var test = document.getElementById("test");
          document.getElementById("click").addEventListener("click", function()
          {
            if (!(elems++ % 10))
            {
              div = document.createElement("div");
              var text = document.createTextNode("div");
              div.appendChild(text);
              test.appendChild(div);
            }
            else
            {
              var spawn = document.createElement("spawn");
              var text = document.createTextNode("spawn");
              spawn.appendChild(text);
              div.appendChild(spawn);
            }
          });
        };
        addButtonClickHandler();
        
        var analyze = function(timings)
        {
          var animationTime = 0;
          for (var i = 1; i < timings.length; ++i)
          {
            animationTime += timings[i];
          }
          animationTime /= (timings.length - 1);
          var deviants = 0;
          var epsilonIdx = 0;
          var animationEpsilon = 0;
          var animationResult = "";
          for (var i = 1; i < timings.length; ++i)
          {
            animationResult += timings[i] + "; ";
            if (Math.abs(animationTime - timings[i]) > animationEpsilon)
            {
              epsilonIdx = i;
              animationEpsilon = Math.abs(animationTime-timings[i]);
            }
            if (Math.abs(animationTime - timings[i]) > 1)
            {
              ++deviants;
            }
            
          }
          document.getElementById("animationResult").innerHTML = "animation: " + animationTime + " +- " + animationEpsilon;
          document.getElementById("animationResult").innerHTML += "<br>" + animationResult;
          document.getElementById("animationResult").innerHTML += "<br>" + "<br> max. Abweichung bei: " + epsilonIdx + " Wert: " + timings[epsilonIdx] + "<br>" + " Abweichungen: " + deviants;
        }
        
        var animate = function()
        {
          var animationTiming = [];
          var animationTime = 0;
          var animationInc = 1;
          
          var animationDiv = document.getElementsByClassName("animation")[0];
          animationDiv.style.height = "20px";
          var animationLoop = function()
          {
            var time = new Date();
            animationTiming.push(time - animationTime);
            var height = parseInt(animationDiv.style.height);
            if (height > 100 || height < 20)
            {
              animationInc *= -1;
            }
            animationDiv.style.height = (height + animationInc) + "px";
            animationTime = time;
            if (animationTiming.length >= 1000)
            {
              animationDiv.style.height = "0px";
              analyze(animationTiming);
            }
            else
            {
              requestAnimationFrame(animationLoop);
            }
          }
          requestAnimationFrame(animationLoop);
        };
        animate();
      });
    </script>
  </head>
  <body>
	  <div id="animationResult"></div>
	  <div class="animation"></div>
    <button id="click" type="button">test</button>
    <div id="test"></div>
  </body>
</html>
:TIDE

Hat sich bei der Messung der Mittelwert verschoben? Bitte Zahlen.
nein, war meistens 16 oder 17 ms wenn es dann mal 20 wurden, war der nächste aufruf nach 12/13 ms

Ich denke mal, dass bei deinem Test das Erzeugen des DOM-Elements das ganze unter Last legt
sind wir wieder bei dem punkt, wo es eigentlich schon egal wäre.
 
Zuletzt bearbeitet:
Das war ein Teil meines Punktes... gut, dass wir uns da einig sind.
"projiziert" - gefällt dir nicht? mir fiel nichts besseres ein
Mir fällt auch nichts wirklich besseres ein ;)

meiner nicht, so wie es zwischenschritte geben muss
Warum muss es beim Repaint (das meine ich mit dem Rendern) Zwischenschritte geben? Beim DOM-Layout und Reflow gebe ich dir Recht (der Reflow wird ja sogar zwischen einzelnen JS-Statements gemacht, wenn er nötig ist). Aber beim Repaint?
, ist es sinnvoll (nicht zwingend) die updaterate auf einen wert zu begrenzen. ob das die monitorfrequez ist kann ich nicht sagen, scheint aber so. vermutet hätte ich einen wert leicht größer als diese.
Natürlich ist das nicht zwingend. Das war auch nicht mein Punkt. Aber, wie du sagst, scheinen die Browser das zu machen und das ist mein Punkt.

ist aber so, die einen haben eine fps von 120 die anderen von 30, je nach cpu/grafikkarte
Äh... das wiederspricht sich irgendwie für micht mit
es gibt im bereich der spiele, die directx nutzen auch möglichkeiten sich mit der grafikkarte zu syncronisieren
Und warum sollte ich 120 fps berechnen, wenn der Benutzer nur 50 fps sieht? Das ist doch komplette Verschwendung.

, das wird aber immer nur optional angeboten, weil du damit deine fps künstlich begrenzt, da du immer wartest, bei 50Hz monitor und ner 51er fps kein problem, aber aus ner 49er fps die möglich wären machst du 25.
Wenn ich die 50 fps nicht schaffe, ergibt es auch keinen Sinn, sich mit dem Monitor zu synchronisieren...

reich ich morgen nach
also bei mir ist kein Unterschied, ob ich die Elemente erzeuge oder nicht - und auch kein Unterschied zu meinem Test... könnte daran liegen, dass ich Win7 hab'... da scheinen sich die Browser anders zu verhalten als in XP. Gut zu wissen - für das nächste halbe Jahr... ;)
Wobei ich das Verhalten meiner Browser sinnvoller finde (ich weiß, dass du das nicht so siehst).


nein, war meistens 16 oder 17 ms wenn es dann mal 20 wurden, war der nächste aufruf nach 12/13 ms
Ja, das ist bei mir genauso und würde ja dafür sprechen, dass es mit dem Monitor synchronisiert ist ;)


sind wir wieder bei dem punkt, wo es eigentlich schon egal wäre.
Natürlich ist es egal. Verlassen kann man sich sowieso nicht drauf. Ich bin nur der Meinung, dass man sich auf window.setTimeout noch weniger verlassen kann.

Deswegen hab ich oben ja auch
Etwas besser ist window.requestAnimationFrame() , aber auch nicht perfekt
geschrieben.
 
Warum muss es beim Repaint (das meine ich mit dem Rendern) Zwischenschritte geben?
es muss Zwischenschritte bei der animation geben, auch wenn sonst kein Rendern nötig ist. das meinte ich.

Äh... das wiederspricht sich irgendwie für micht mit

Und warum sollte ich 120 fps berechnen, wenn der Benutzer nur 50 fps sieht? Das ist doch komplette Verschwendung.
so läuft das aber, es wird berechnet, was der rechner hergibt.

also bei mir ist kein Unterschied, ob ich die Elemente erzeuge oder nicht - und auch kein Unterschied zu meinem Test... könnte daran liegen, dass ich Win7 hab'... da scheinen sich die Browser anders zu verhalten als in XP.
Ich hab das auch unter Win 7 getestet.

Ja, das ist bei mir genauso und würde ja dafür sprechen, dass es mit dem Monitor synchronisiert ist ;)
nee, das spricht für einen festen timer von 16/17 ms, bei dem nicht berechnet wird, wenn seit dem letzten timerevent schon ein rendern erfolgte und somit schon berechnet wurde, ...
... wobei dann immer auf ein 13ms wert ein 20 ms wert folgen müsste, werd ich mir nochmal ansehen, wierum das nun genau war.
 
es muss Zwischenschritte bei der animation geben, auch wenn sonst kein Rendern nötig ist. das meinte ich.
Ach so. Klar muss es bei der Animation Zwischenschritte geben... aber das hab' ich auch nie abgestritten.

so läuft das aber, es wird berechnet, was der rechner hergibt.
So läuft das in schlecht geschriebener Software, die immer 100% meiner CPU/GPU beansprucht... sowas wird bei mir soft wieder deinstalliert.

Ich hab das auch unter Win 7 getestet.
Dann ist es seltsam...

nee, das spricht für einen festen timer von 16/17 ms, bei dem nicht berechnet wird, wenn seit dem letzten timerevent schon ein rendern erfolgte und somit schon berechnet wurde, ...
... wobei dann immer auf ein 13ms wert ein 20 ms wert folgen müsste, werd ich mir nochmal ansehen, wierum das nun genau war.
Die 50Hz (bzw. bei dir 60Hz) des Monitors sind auch ein fester Timer... und solange die beiden Timer mit der gleichen Frequenz arbeiten, kommt das (fast) auf das Gleiche raus.
 
So läuft das in schlecht geschriebener Software, die immer 100% meiner CPU/GPU beansprucht... sowas wird bei mir soft wieder deinstalliert.
wir reden hier über spiele?! nur da macht es überhaupt sinn über fps zu reden. und da ist es so. das witzige an der sache ist ja, daß es dann immer noch leute gibt, die behaupten den unterschied zw. 100 und 120 fps zu sehen. und das lange bevor es 120 hz monitore gab. Wieviel fps habt ihr so
Bei normalen Anwendungen hast du überhaupt keine fps, da dort in der regel nur auf usereingaben gewartet wird. wenn dann mal eine kommt, wird gerendert.

Die 50Hz (bzw. bei dir 60Hz) des Monitors sind auch ein fester Timer... und solange die beiden Timer mit der gleichen Frequenz arbeiten, kommt das (fast) auf das Gleiche raus.
ob ich einen timer habe, der ungefähr der monitorfrequenz entspricht oder synchron zur monitorfrequenz berechne ist ein himmelweiter unterschied.
 
wir reden hier über spiele?!
Nicht nur. Ich rede von allem, das eine Animation flüssig darstellen soll.
Super!

Bei normalen Anwendungen hast du überhaupt keine fps, da dort in der regel nur auf usereingaben gewartet wird. wenn dann mal eine kommt, wird gerendert.
Bei den meisten Anwendungen stimmt das, aber wenn ich mir z.B. ein Video ansehe oder ein 3D-Modell gerade animiert ansehe, kann man schon auch von fps reden.

ob ich einen timer habe, der ungefähr der monitorfrequenz entspricht oder synchron zur monitorfrequenz berechne ist ein himmelweiter unterschied.
Wer hat denn was von "ungefähr" gesagt? ;) Wenn die Frequenzen nichr genau übereinstimmen, ist das natürlich ein Unterschied.
 
Zurück
Oben