mojira.dev
MC-159633

Command feedback messages are unnecessarily created during function execution

The bug

Command feedback is never sent to the command source during function execution, but a translatable component for command feedback is always created eagerly on each command execution. This imposes a constant overhead on commands in general and also makes some commands significantly slower in performance.

Examples

The following commands take linear time instead of constant time.

  • Size of forced chunks

    /forceload query
  • Deep size of collection

    /data get storage _ path.to.collection
  • Deep size of compound

    /data get storage _ path.to.compound
  • Length of string due to quoting and escaping

    /data get storage _ path.to.string

Linked issues

Comments 4

Still present in 1.16

Just for reference, here are the microbenchmark results for /data get storage ..., illustrating an example of how much feedback message creation is involved in command performance:

{0: 0b, 1: 0s, 2: 0, 3: 0L, 4: 0.0f, 5: 0.0d}

Benchmark               Mode  Cnt    Score    Error  Units
data get storage 0 0    avgt   25  181.837 ±  3.506  ns/op
data get storage 0 1    avgt   25  183.749 ±  1.202  ns/op
data get storage 0 2    avgt   25  120.708 ±  1.563  ns/op
data get storage 0 3    avgt   25  181.646 ±  1.464  ns/op
data get storage 0 4    avgt   25  188.979 ±  2.598  ns/op
data get storage 0 5    avgt   25  189.029 ±  2.258  ns/op

/data get storage 0 2 (which returns an IntTag) turns out to be faster than the others because IntTags do not require a numeric suffix and can reduce the cost of appending it when creating a feedback message.

{0: 0b, 1: 0s, 2: 0, 3: 0L, 4: 0.0f, 5: 0.0d}

Benchmark               Mode  Cnt    Score    Error  Units
data get storage 0 0 1  avgt   25  846.095 ± 14.720  ns/op
data get storage 0 1 1  avgt   25  847.678 ± 16.129  ns/op
data get storage 0 2 1  avgt   25  864.702 ± 14.426  ns/op
data get storage 0 3 1  avgt   25  847.377 ± 13.149  ns/op
data get storage 0 4 1  avgt   25  811.640 ±  8.092  ns/op
data get storage 0 5 1  avgt   25  832.317 ± 29.123  ns/op

Adding a <scale> argument makes the situation even worse. The primary cause of the slowdown is String.format(Locale.ROOT, "%.2f", scale), which is used for pretty-printing the scale.

intsuc

(Unassigned)

Community Consensus

Normal

Commands, Performance

function

1.14.4, 19w34a, 19w35a, 1.15 Pre-release 5, 1.15.2, ..., 23w14a, 23w16a, 23w17a, 23w18a, 1.20 Pre-release 1

1.20 Pre-release 2

Retrieved