[Day13] Vite 出小蜜蜂~Memory Leak & Optimization!

Day13

目前做到这边的大家应该会发现一些问题,
在上一个章节,虽然我们成功产生了很多敌人,但是程序却发生了 Memory Leak

这就是这个章节的主题,程序优化
卡比将介绍如何找到真正的问题,并采取对应的优化方式。

Profiling

首先,我们要打开 DevTool,并切到 Memory 页签。

这边有三个选项,这次只会用到 Allocation instrumentation on timeline,他会做一个时间轴并记录时间内的记忆体使用状况。

按下 Take Snapshot 开始取样。

首先下面这张是按下 Snapshot 时的状态,

接着我们选时间轴,第一条蓝色的时间段,对照一下。

发现到 GraphicsGeometry2 产生的物件数量非常多,

再对照一下,最後一条蓝色的时间段。

也是一样最多的是 GraphicsGeometry2
我们基本可以确定问题出在 Graphicspixi.jsAPI

於是查询 pixi.js文件或是 issue
我们最後会查到,原来 pixi.jsGraphics
在建立时会顺便产生一些 Bonus,而这些并不会自动被清除。

Refector

找到问题後,我们就很清楚要修正 src/systems/render.ts,因为我们只有在那里用到。
我们要修改成,只使用同一个 Graphics 并每次画面更新前都要先清除上次的资料。

修正如下:

-- src/systems/render.ts

function Graphics(
  graphics: _Graphics,
  { renderer, position }: Renderer & Transform
) {
  const src = renderer.src;

  for (let y = 0; y < src.length; y++) {
    for (let x = 0; x < src[y].length; x++) {
      if (src[y][x] === 0) continue;

      graphics.beginFill(0xffffff);

      graphics.drawRect(position.x + x, position.y + y, 1, 1);

      graphics.endFill();
    }
  }
}

const graphics = new _Graphics();

export function clear() {
  graphics.clear();
}

export function render(stage: Container, instance: GameObject & Renderer) {
  stage.addChild(graphics);

  if (instance.renderer.type === "graphics" && canTransform(instance)) {
    Graphics(graphics, instance);
  }
}

接着,我们只需要在 src/scenes/Game.ts,那边呼叫 clear 即可。

export default function Game(screen: Rectangle): Scene<Container> {
  let instances: GameObject[] = [LaserCannon(screen), ...spawn(Enemy, points)];

  return {
    update(delta) {
      collisionDetect(instances.filter(canCollision).filter(canTransform));

      instances.forEach((instance) => {
        if (canControl(instance)) {
          instance.handleInput(getKeyPressed());
        }

        if (canShoot(instance) && instance.canShoot) {
          requestAnimationFrame(() => {
            instances = [...instances, instance.shoot()];
          });

          instance.canShoot = false;
        }

        if (instance.destroy) {
          requestAnimationFrame(() => {
            instances = instances.filter((_instance) => _instance !== instance);
          });

          return;
        }

        instance.update?.(delta);
      });
    },

    render(stage) {
+     clear();

      instances
        .filter(canRender)
        .forEach((instance) => render(stage, instance));
    },
  };
}

这时我们再重新检测 memory,这时的记忆体使用量会低非常多,就表示优化成功了。

关於兔兔们:


<<:  自动化 End-End 测试 Nightwatch.js 之踩雷笔记:前言

>>:  [Android Studio 30天自我挑战] RelativeLayout元件对齐方式

Day7 Let's ODOO: Model(4) ORM API

本章节介绍ORM对资料库的CURD方法,我们以上个章节介绍的student model 为例。 # ...

第 2 天 诸神早安晨之美|建立 Angular 专案、使用 JSON-server

今天我们将建构专案开发环境,除了 Angular 之外,我们也将在专案中配置 json-server...

爬虫怎麽爬 从零开始的爬虫自学 DAY2 开发环境-1 安装python

前言 各位早安,学习一个技术会遇到的第一个大难题就是开发环境的建置,很多新手就是在这里被劝退的,密密...

【D1】前言与规划

本届比赛的第二个系列,也就是挑战永丰API的部分。 这次要挑战的是永丰证的API-Shioaji,这...

[火锅吃到饱-16] 斗牛士二锅 - 台中文心店

官网有分店资讯 之前在脸书社团就看过版友分享过桃园店的用餐体验,平日午餐328的价位,提供6种肉品吃...