PERF: thaumicadditions 污染作物每 tick 重复取块 3 次、取元数据 2 次,并为一条常量阈值每 tick 查一次 biome #22

Closed
opened 2026-11-04 09:05:01 +00:00 by layue13 · 1 comment
Owner

调研编号:

现象

污染作物的 updateEntity 每 tick 的常态路径(生长分支)里,getBlock(x, y-1, z) 在一条 && 条件中被求值 3 次(短路也至少 1 次、通常 3 次),getBlockMetadata(x, y, z) 被求值 2 次,另外每 tick 查一次 biome——而 biome 只用于把生长阈值从 4000 改成 3550,同一方块的 biome 在 tick 之间根本不变。整个过程没有任何局部变量承接,也没有节流门。

危害类与优先级

  • PERF(每 tick 同参数重复求值 + 每 tick 重算 tick 不变的不变量)→ 标签 type/perf
  • p3 单次开销小,但乘数是「每 tick × 每株作物」;污染作物是成片种植的(一片 10×10 就是 100 株),且 biome 查询走 getChunkFromBlockCoords + chunk biome 数组,比 getBlock 更重

证据(生效源码)

  • 载体:TDLM/thaumicadditions + 分支 origin/main + pin cded7cd3ee59(source 类仓,无 patch 层,代码可点开)
  • 位置:src/main/java/com/pengu/thaumcraft/additions/tileentity/TileTaintedCrops.java:21、:33、:37-38
  • 关键原文:
// :21  同一个坐标 (x, y-1, z) 在一条短路口径里被 getBlock 三次
      if(!this.worldObj.getBlock(this.xCoord, this.yCoord - 1, this.zCoord).canSustainPlant(this.worldObj, this.xCoord, this.yCoord - 1, this.zCoord, ForgeDirection.UP, (IPlantable)All.B_taint_crops) && this.worldObj.getBlock(this.xCoord, this.yCoord - 1, this.zCoord) != Blocks.grass && this.worldObj.getBlock(this.xCoord, this.yCoord - 1, this.zCoord) != Blocks.dirt) {

// :33 / :38  同一 tick 内 getBlockMetadata(x,y,z) 两次
         if(this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord) < 4) {
            ++this.tick;
         }
// :37  每 tick 只为一个常量阈值查一次 biome
         if(this.tick >= 4000 - (this.worldObj.getBiomeGenForCoords(this.xCoord, this.zCoord).biomeID == Config.biomeTaintID?450:0)) {
            Util.setBlockMetadata(this.worldObj, this.xCoord, this.yCoord, this.zCoord, this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord) + 1);
  • 计数(每株作物、每 tick,常态生长分支):getBlock(y-1) 3 次、getBlockMetadata(y) 2 次、getBiomeGenForCoords(x,z) 1 次 ⇒ 6 次查询里 4 次是同一目标的重复;把 Block below = worldObj.getBlock(x, y-1, z); int meta = worldObj.getBlockMetadata(x,y,z); 提到前面复用,biome 换成缓存的 taintBiome 布尔(或在 markDirty/onNeighborChange 时重算),可压到 2 次且结果逐 tick 相同
  • 上游状态:[x] 未修(upstream 同形,无 upstream 仓库可链)

触发与复现

  • 触发条件:污染作物方块进入 tick(成片种植即批量触发),默认配置可达、无需玩家操作。
  • 静态推演:一片 10×10 = 100 株作物 → 每 tick 300 次 getBlock + 200 次 getBlockMetadata + 100 次 biome 查询 = 600 次/片/tick;20 tps ⇒ 12,000 次/秒,其中 8,000 次是同一目标的重复查询。等价改法(局部变量承接 + biome 结果缓存)后降到 2×100 = 200 次/tick,生长判定逐 tick 相同。
  • 包内相关性:模块 thaumicadditions/sides client,server/默认配置可达 是

落点

  • 主仓:TDLM/thaumicadditions → src/main/java/com/pengu/thaumcraft/additions/tileentity/TileTaintedCrops.java:21(重复取块)、:33/:38(重复取元数据)、:37(每 tick biome)

范式

  • 命中范式:F4 帧内不变量重复求值(同参查询无局部承接;:37 属 tick 级不变量)
  • 邻位:T1 tick 重扫无 memo(biome 结果未缓存)

引证

  1. 生效源码 permalink — https://git.potatolab.uk/TDLM/thaumicadditions/src/commit/cded7cd3ee59/src/main/java/com/pengu/thaumcraft/additions/tileentity/TileTaintedCrops.java#L21-L38

来源

  • 线索类型:内部代码审查(无外部报障)
  • 可解析指针:src/main/java/com/pengu/thaumcraft/additions/tileentity/TileTaintedCrops.java:21,33,37-38
**调研编号**: ## 现象 污染作物的 `updateEntity` 每 tick 的常态路径(生长分支)里,`getBlock(x, y-1, z)` 在一条 `&&` 条件中被求值 **3 次**(短路也至少 1 次、通常 3 次),`getBlockMetadata(x, y, z)` 被求值 **2 次**,另外**每 tick 查一次 biome**——而 biome 只用于把生长阈值从 4000 改成 3550,同一方块的 biome 在 tick 之间根本不变。整个过程没有任何局部变量承接,也没有节流门。 ## 危害类与优先级 - `PERF`(每 tick 同参数重复求值 + 每 tick 重算 tick 不变的不变量)→ 标签 `type/perf` - `p3` 单次开销小,但**乘数是「每 tick × 每株作物」**;污染作物是成片种植的(一片 10×10 就是 100 株),且 biome 查询走 `getChunkFromBlockCoords` + chunk biome 数组,比 `getBlock` 更重 ## 证据(生效源码) - 载体:`TDLM/thaumicadditions` + 分支 `origin/main` + pin `cded7cd3ee59`(source 类仓,无 patch 层,代码可点开) - 位置:`src/main/java/com/pengu/thaumcraft/additions/tileentity/TileTaintedCrops.java:21`、`:33`、`:37-38` - 关键原文: ```java // :21 同一个坐标 (x, y-1, z) 在一条短路口径里被 getBlock 三次 if(!this.worldObj.getBlock(this.xCoord, this.yCoord - 1, this.zCoord).canSustainPlant(this.worldObj, this.xCoord, this.yCoord - 1, this.zCoord, ForgeDirection.UP, (IPlantable)All.B_taint_crops) && this.worldObj.getBlock(this.xCoord, this.yCoord - 1, this.zCoord) != Blocks.grass && this.worldObj.getBlock(this.xCoord, this.yCoord - 1, this.zCoord) != Blocks.dirt) { // :33 / :38 同一 tick 内 getBlockMetadata(x,y,z) 两次 if(this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord) < 4) { ++this.tick; } // :37 每 tick 只为一个常量阈值查一次 biome if(this.tick >= 4000 - (this.worldObj.getBiomeGenForCoords(this.xCoord, this.zCoord).biomeID == Config.biomeTaintID?450:0)) { Util.setBlockMetadata(this.worldObj, this.xCoord, this.yCoord, this.zCoord, this.worldObj.getBlockMetadata(this.xCoord, this.yCoord, this.zCoord) + 1); ``` - 计数(每株作物、每 tick,常态生长分支):`getBlock(y-1)` **3 次**、`getBlockMetadata(y)` **2 次**、`getBiomeGenForCoords(x,z)` **1 次** ⇒ 6 次查询里 4 次是同一目标的重复;把 `Block below = worldObj.getBlock(x, y-1, z); int meta = worldObj.getBlockMetadata(x,y,z);` 提到前面复用,biome 换成缓存的 `taintBiome` 布尔(或在 `markDirty`/`onNeighborChange` 时重算),可压到 2 次且结果逐 tick 相同 - 上游状态:[x] 未修(upstream 同形,无 upstream 仓库可链) ## 触发与复现 - 触发条件:污染作物方块进入 tick(成片种植即批量触发),默认配置可达、无需玩家操作。 - [x] 静态推演:一片 10×10 = 100 株作物 → 每 tick 300 次 `getBlock` + 200 次 `getBlockMetadata` + 100 次 biome 查询 = 600 次/片/tick;20 tps ⇒ **12,000 次/秒**,其中 8,000 次是同一目标的重复查询。等价改法(局部变量承接 + biome 结果缓存)后降到 2×100 = 200 次/tick,**生长判定逐 tick 相同**。 - 包内相关性:模块 `thaumicadditions`/sides `client,server`/默认配置可达 是 ## 落点 - 主仓:`TDLM/thaumicadditions` → `src/main/java/com/pengu/thaumcraft/additions/tileentity/TileTaintedCrops.java:21`(重复取块)、`:33/:38`(重复取元数据)、`:37`(每 tick biome) ## 范式 - 命中范式:`F4 帧内不变量重复求值`(同参查询无局部承接;`:37` 属 tick 级不变量) - 邻位:`T1 tick 重扫无 memo`(biome 结果未缓存) ## 引证 1. 生效源码 permalink — https://git.potatolab.uk/TDLM/thaumicadditions/src/commit/cded7cd3ee59/src/main/java/com/pengu/thaumcraft/additions/tileentity/TileTaintedCrops.java#L21-L38 ## 来源 - 线索类型:内部代码审查(无外部报障) - 可解析指针:`src/main/java/com/pengu/thaumcraft/additions/tileentity/TileTaintedCrops.java:21,33,37-38`
layue13 added the
priority
p3
type
perf
origin/scanarea/performance
labels 2026-11-04 09:05:01 +00:00
Author
Owner

关闭,不改:TileTaintedCrops(:21-38)每个作物 tile 每 tick 三次 getBlock 和一次群系查询,开销微小且不在 profile 里。

关闭,不改:`TileTaintedCrops`(:21-38)每个作物 tile 每 tick 三次 `getBlock` 和一次群系查询,开销微小且不在 profile 里。
layue13 reopened this issue 2026-11-07 06:10:06 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: TDLM/thaumicadditions#22