Reduce memory usage to improve GC performance

This commit is contained in:
Mattéo Delabre 2020-05-04 18:17:25 +02:00
parent 11ffc81848
commit 9c9afa2409
Signed by: matteo
GPG Key ID: AE3FBD02DC583ABB
3 changed files with 93 additions and 77 deletions

View File

@ -1,79 +1,75 @@
import Vector from './vector.mjs'; import Vector from './vector.mjs';
const findNeighbors = (boids, boid, radius) => const meanPos = new Vector(0, 0);
{ const meanVel = new Vector(0, 0);
const neighbors = []; const repelForce = new Vector(0, 0);
for (let otherBoid of boids)
{
if (boid != otherBoid)
{
const dist = boid.pos.sub(otherBoid.pos).normSquared();
if (dist < radius * radius)
{
neighbors.push(otherBoid);
}
}
}
return neighbors;
};
export const update = (boids, params, time) => export const update = (boids, params, time) =>
{ {
for (let boid of boids) const boidsSize = boids.length;
{
const visible = findNeighbors(boids, boid, params.visibleDist);
const close = findNeighbors(boids, boid, params.closeDist);
// Attract towards center of visible flock for (let i = 0; i < boidsSize; ++i)
const center = new Vector(0, 0);
for (let otherBoid of visible)
{ {
center.addMut(otherBoid.pos); const me = boids[i];
meanPos.reset();
meanVel.reset();
repelForce.reset();
let visibleSize = 0;
for (let j = 0; j < boidsSize; ++j)
{
if (i != j)
{
const you = boids[j];
const dist = Vector.distSquared(me.pos, you.pos);
if (dist < params.visibleDist * params.visibleDist)
{
meanPos.add(you.pos);
meanVel.add(you.vel);
visibleSize += 1;
if (dist < params.closeDist * params.closeDist)
{
repelForce.add(me.pos).sub(you.pos);
}
}
}
} }
if (visible.length >= 1) // Attract towards center of visible flock
if (visibleSize >= 1)
{ {
center.divMut(visible.length); me.vel.add(meanPos.div(visibleSize)
boid.vel.addMut(center.sub(boid.pos).mul(params.centerAccel)); .sub(me.pos)
.mul(params.centerAccel));
} }
// Attract toward center of screen // Attract toward center of screen
boid.vel.addMut(boid.pos.mul(-0.01)); me.vel.addMul(me.pos, -0.01);
// Repel away from close boids // Repel away from close boids
for (let otherBoid of close) me.vel.add(repelForce.mul(params.repelAccel));
{
boid.vel.addMut(boid.pos
.sub(otherBoid.pos)
.mul(params.repelAccel));
}
// Match other boids velocity // Match other boids velocity
const velocity = new Vector(0, 0); if (visibleSize >= 1)
for (let otherBoid of visible)
{ {
velocity.addMut(otherBoid.vel); me.vel.add(meanVel.div(visibleSize)
} .sub(me.vel)
.mul(params.matchAccel));
if (visible.length >= 1)
{
velocity.divMut(visible.length);
boid.vel.addMut(velocity.sub(boid.vel).mul(params.matchAccel));
} }
// Do not surpass maximum speed // Do not surpass maximum speed
const speed = boid.vel.normSquared(); const speed = me.vel.normSquared();
if (speed > params.maxSpeed * params.maxSpeed) if (speed > params.maxSpeed * params.maxSpeed)
{ {
boid.vel.divMut(Math.sqrt(speed)).mulMut(params.maxSpeed); me.vel.div(Math.sqrt(speed)).mul(params.maxSpeed);
} }
boid.pos.addMut(boid.vel.mul(time)); // Integrate speed
me.pos.addMul(me.vel, time);
} }
}; };

View File

@ -7,8 +7,13 @@ const boidShape = [
new Vector(2, 0), new Vector(2, 0),
]; ];
const boidShapeSize = boidShape.length;
const transformed = new Vector(0, 0);
export const boids = (activeBoids, params, ctx, width, height, center) => export const boids = (activeBoids, params, ctx, width, height, center) =>
{ {
const boidsSize = activeBoids.length;
ctx.clearRect(0, 0, width, height); ctx.clearRect(0, 0, width, height);
// // Draw each boids visibility and proximity zones // // Draw each boids visibility and proximity zones
@ -75,24 +80,31 @@ export const boids = (activeBoids, params, ctx, width, height, center) =>
ctx.beginPath(); ctx.beginPath();
ctx.fillStyle = 'black'; ctx.fillStyle = 'black';
for (let boid of activeBoids) for (let i = 0; i < boidsSize; ++i)
{ {
const boid = activeBoids[i];
const angle = boid.vel.angle(); const angle = boid.vel.angle();
let isFirst = true; let isFirst = true;
for (let point of boidShape) for (let j = 0; j < boidShapeSize; ++j)
{ {
const trans = boid.pos.add(center) transformed.x = boidShape[j].x;
.add(point.rotate(angle).mul(params.radius)) transformed.y = boidShape[j].y;
transformed
.rotate(angle)
.mul(params.radius)
.add(center)
.add(boid.pos);
if (isFirst) if (isFirst)
{ {
ctx.moveTo(trans.x, trans.y); ctx.moveTo(transformed.x, transformed.y);
isFirst = false; isFirst = false;
} }
else else
{ {
ctx.lineTo(trans.x, trans.y); ctx.lineTo(transformed.x, transformed.y);
} }
} }
} }

View File

@ -7,23 +7,20 @@ class Vector
} }
add(vector) add(vector)
{
return new Vector(this.x + vector.x, this.y + vector.y);
}
addMut(vector)
{ {
this.x += vector.x; this.x += vector.x;
this.y += vector.y; this.y += vector.y;
return this; return this;
} }
sub(vector) addMul(vector, scalar)
{ {
return new Vector(this.x - vector.x, this.y - vector.y); this.x += vector.x * scalar;
this.y += vector.y * scalar;
return this;
} }
subMut(vector) sub(vector)
{ {
this.x -= vector.x; this.x -= vector.x;
this.y -= vector.y; this.y -= vector.y;
@ -31,11 +28,6 @@ class Vector
} }
mul(scalar) mul(scalar)
{
return new Vector(this.x * scalar, this.y * scalar);
}
mulMut(scalar)
{ {
this.x *= scalar; this.x *= scalar;
this.y *= scalar; this.y *= scalar;
@ -47,20 +39,16 @@ class Vector
return this.mul(1 / scalar); return this.mul(1 / scalar);
} }
divMut(scalar)
{
return this.mulMut(1 / scalar);
}
rotate(angle) rotate(angle)
{ {
const cos = Math.cos(angle); const cos = Math.cos(angle);
const sin = Math.sin(angle); const sin = Math.sin(angle);
const nextX = cos * this.x - sin * this.y;
const nextY = cos * this.y + sin * this.x;
return new Vector( this.x = nextX;
cos * this.x - sin * this.y, this.y = nextY;
cos * this.y + sin * this.x, return this;
);
} }
angle() angle()
@ -72,6 +60,26 @@ class Vector
{ {
return this.x * this.x + this.y * this.y; return this.x * this.x + this.y * this.y;
} }
static distSquared(lhs, rhs)
{
return (
(lhs.x - rhs.x) * (lhs.x - rhs.x)
+ (lhs.y - rhs.y) * (lhs.y - rhs.y)
);
}
reset()
{
this.x = 0;
this.y = 0;
return this;
}
clone()
{
return new Vector(this.x, this.y);
}
} }
export default Vector; export default Vector;