ecs: a despawnWhere that matches nothing should cost nothing

オープン
#252 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
25/100
issue の種類
機能追加
明瞭さ
おおむね明確
活発さ
活発
技術スタック
typescript
領域
performance

調査の方向性

The payload names no source files. Start from how commands.despawnWhere is queued and how the sync point decides whether to run, using the #245 idle-sync-point work as the reference. The benchmarks derive cells idle 100k and drag frame select 256 reproduce the cost. Choose option 1 or 2 from the issue and confirm the empty-query frame costs what the idle frame does. Done when an empty despawnWhere no longer adds a sync point.

索引モデルが issue の本文から書いたものです。

説明

Summary

commands.despawnWhere(query) issued by a system that runs every frame makes every frame pay for a sync point, even when the query matches nothing. A per-row system that calls commands.despawn(row.entity) makes no command when no row matches and so costs nothing. For a "clear last frame's events" system, which runs every frame and usually has nothing to clear, the batch call is slower than the loop it was meant to replace.

Where this came from (mecs)

mecs has an endFrame system that despawns every entity marked frameTransient (one-frame events). With 0.3.0 (#244) despawnWhere has the right meaning for it, so I tried:

export const endFrame = System.create({ after: [input] }, ({ commands }) => {
    commands.despawnWhere({ with: [frameTransient] });
});

Measured on the editor's frame (input, pointer, voxel and editor systems, nothing happening; the derive cells idle 100k and drag frame select 256 benchmarks, Apple M3, node):

endFrame idle frame drag-select frame
one despawnWhere each frame 5.5 µs 6.2 µs
per-row despawn (no rows, no command) 2.2 µs 3.1 µs

So an empty despawnWhere costs about 3 µs, roughly the frame. The idle-sync-point work in #245 skips a sync point that has nothing to apply, but a despawnWhere is a command, so the sync point can't be known empty until it is applied.

What I need

Any one of these would do; the first is what I'd reach for:

  1. A sync point whose only commands are despawnWhere (or other query-shaped commands) that match nothing costs what an idle one does: evaluate the query against the tables when the command is issued (or at the start of the sync point), and drop the command if no table matches, so the tier boundary can still be skipped.
  2. Or a cheap way for a system to ask "is there any row for this query" without a lookup/Index (the systems-use-queries rule in mecs says not to define an Index for what a query reads), so the caller can skip issuing it.

Why it matters

One-frame events and "clear then respawn if changed" are common (previewBrush in mecs clears and respawns its preview marks only when the brush changes, which is fine, but endFrame runs unconditionally). The pattern the guide's chapter 06 shows ("the producer clears its last events") is the same shape. Per-row despawn is the workaround, and it is fine, but it means the batch command is only a win when something matches.

主要言語
TypeScript
スター
12
フォーク
8
平均マージ
11時間 2分
マージ済み PR(30日)
23

環境構築

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

adobe/data のほかの issue

adobe/data の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。