Re: Cheb's Game Engine
Добавлено: 11.09.2015 19:25:38
Изыскания на тему дружественности к кешу. Взял свой дрееевний тест с объектами, связанными цепочкой next/previous, и добавил параллельно массив, в котором хранится та же цепочка.
Результ просчёта физики:
CycleFriendly - 120 наносекунд / шт. Тупым обходом массива.
CycleNonFriendly - 200 наносекунд /шт. Угадайте за счёт чего? Рекурсия, вершина стека всё время ползёт по памяти,
Поправка: 103 и 175 соответственно. Встроенная видяха (сюрприз, сюрприз!) перетягивает ресурсы у ядр процессора, если не убить качество рендера ручную в ноль.
P.P.S. И 375 / 500 в режиме экономии батареи.
Это жалкий миллион просчётов в секунду (10 тысяч на кадр) если брать с запасом.
Подробно, физега (для этого теста закомментил вызовы random(), смазывали всю картину):
где
Результ просчёта физики:
CycleFriendly - 120 наносекунд / шт. Тупым обходом массива.
CycleNonFriendly - 200 наносекунд /шт. Угадайте за счёт чего? Рекурсия, вершина стека всё время ползёт по памяти,
Поправка: 103 и 175 соответственно. Встроенная видяха (сюрприз, сюрприз!) перетягивает ресурсы у ядр процессора, если не убить качество рендера ручную в ноль.
P.P.S. И 375 / 500 в режиме экономии батареи.
Это жалкий миллион просчётов в секунду (10 тысяч на кадр) если брать с запасом.
- Код: Выделить всё
procedure TTest12Data.CycleNonFriendly;
var
distance,
force: float;
dmx, dmy: float;
i: integer;
begin
if Assigned(next) then next.CycleNonFriendly;
//физега, TL;DR
end;
procedure TTest12Data.CycleFriendly;
var i: integer;
begin
if Self <> first then Die(RuEn(
'Метод CycleFriendly() имеет смысл вызывать только у первого объекта верёвочки.'#10#13' Искренне ваш, Капитан Очевидность.',
'The CycleFriendly() has to be called only on the forst object of the rope.'#10#13' Sincerely yours, Captain Obvious.'));
for i:= High(all) downto 0 do all[i].Cycle;
end;
procedure TTest12Data.Cycle;
var
distance,
force: float;
dmx, dmy: float;
i: integer;
begin
//такая же физега, TL;DR
end;
Подробно, физега (для этого теста закомментил вызовы random(), смазывали всю картину):
- Код: Выделить всё
procedure TTest12Data.Cycle;
var
distance,
force: float;
dmx, dmy: float;
i: integer;
begin
if Assigned(next) then begin
if Assigned(previous) then begin
distance:=sqrt(sqr(previous.mx - mx) + sqr(previous.my - my));
if distance < 1 then distance:=1;
force:= - speed * 0.01 * sqr(PrefDist)/sqr(Distance);
if force < -5 then force:=-5;
// force:=aa * force;
dmx:= (previous.mx - mx) / distance;
dmy:= (previous.my - my) / distance;
mx += force * dmx;
my += force * dmy;
end;
end;
if Assigned(previous) then begin
ag:=previous.ag;
ab:=previous.ab;
ar:=previous.ar;
aa:=previous.aa;
distance:=sqrt(sqr(previous.mx - mx) + sqr(previous.my - my));
if distance < 1 then distance:=1;
dmx:= (previous.mx - mx) / distance;
dmy:= (previous.my - my) / distance;
if distance > PrefDist
then begin
force:= speed * 0.1 * (distance - PrefDist);
if ag < 0.5 then force:= -force;
end
else force:= - speed * 0.1 * PrefDist/Distance;
if force > 50 then force:=50;
if force < -5 then force:= -5;
// force:=aa * force;
mx += force * dmx + dx;
my += force * dmy + dy;
if mx < -1000 then mx:= -1000;
if mx > 3000//Mother^.Display.WindowClientRect.Width + 1000
then mx:=3000;//Mother^.Display.WindowClientRect.Width + 1000;
if my < -1000 then my:= -1000;
if my > 2000//Mother^.Display.WindowClientRect.Height + 1000
then my:= 2000;//Mother^.Display.WindowClientRect.Height + 1000;
// dx += Speed * 0.01 * (random() - 0.5);
dx *= 0.98;
// dy += Speed * 0.01 * (random() - 0.5);
dy *= 0.98;
// s += Speed * 0.01 * (PrefSize * (PrefDist/distance) - s);
end;
distance:=sqrt(sqr(Module.Logic.mousex - mx) + sqr(Module.Logic.mousey - my));
if distance < 1 then distance:=1;
dmx:= (Module.Logic.mousex - mx) / distance;
dmy:= (Module.Logic.mousey - my) / distance;
force:=0;
if ar < 0.5 then force -= speed * 1 * PrefDist / Distance;
if ab < 0.5 then force += 0.1;
if force > 5 then force:=5;
if force < -5 then force:= -5;
// force:=aa * force;
mx += force * dmx;
my += force * dmy;
end;
где
- Код: Выделить всё
type
TTest12Data = class;
TT12Array = array of TTest12Data;
TTest12Data = class (TcgeObject)//TTrulyPersistent)
public
all: TT12Array;
/// _666: integer;
mx, my, r, g, b, ar, ag ,ab, aa, s, dx, dy: glFloat;
// m: TImageMode;
// w,h, t: integer;
// Oopaloopa: Int64;
// p: pointer;
// texture: glUint;
previous, next, first: TTest12Data;
// BigBin: TBigBin;
constructor FirstCreate(prv: TTest12Data); virtual;
procedure RegisterFields; override;
// procedure InitTexture;
procedure Render;
procedure RenderFirst(OffX, OffY, VsizeX, VsizeY, PixelSize: float);
procedure Cycle;
procedure CycleNonFriendly;
procedure CycleFriendly;
procedure Scrape; override;
procedure Grow;
end;