Redundant calculation causes 2x lag during explosions
Snapshot 23w45a introduces a redundant set of calculations during the explode method, which leads to a significant (approximately 2x) increase in lag from explosions. This is less likely to be felt on the scale of a single explosion at a time, however it has a notably outsized affect on players who use contraptions that use many TNT or have many entities in close proximity to explosions.
Data from in-game testing in versions 23w44a and 23w45a (shows test setup):
https://www.desmos.com/calculator/c4ccpegwpp
Background (for analysis):
The value returned by the getSeenPercent method represents what proportion of an entity is "exposed" to an explosion, and it is a value that ranges from 0 to 1. The value is sometimes colloquially called the "exposure". The lower an entity's exposure, the less of an effect the explosion has on the entity. Exposure is used when calculating how much the explosion damages an entity, as well as how much the explosion propels the entity. The method uses an array of "raycasts" that probe the area between the entity and the explosion for blocks that may protect the entity from the explosion. These raycasts can number in the dozens per entity, and each requires a non-trivial amount of math to compute.
Code Analysis [brackets refer to attached screenshots]:
- Prior to 23w45a, getSeenPercent was computed only once and stored in a variable that was then used by both the entity damage and propulsion computations [1a].
- Snapshot 23w45a introduced wind charges, which create non-damaging explosions. In order to allow some explosions to cause no health damage, a condition was added during the explode method that skips computing damage if the damageSource for the explosion is null [1b]. Therefore, explosions with damageSource == null (like those of wind charges) do not hurt entities.
- The default Explosion constructor previously overwrote null damageSource values with a non-null value [2a], so in 23w45a the constructor was also modified to accept null damageSource [2b].
Altogether, this means that the logic for skipping damage would work simply by wrapping the existing damage code (1 line of code; see [1a]) in the conditional statement previously mentioned.
Despite this, as of 23w45a, the explosion's damage calculation was relocated to a different class, in a new method that takes only an Explosion object and an entity as parameters [3]. This means that to have the necessary values to compute the damage, the costly exposure computation and a handful of helper values need to be recomputed from scratch using the positions of the explosion and entity, even though all of them are already computed in the explode method for the applied velocity calculation [see 1b again]. As a result, each explosion now has about twice the amount of work when processing how it affects entities.
Created Issue:
Redundant calculation causes 2x lag during explosions
Snapshot 23w45a introduces a redundant set of calculations during the explode method, which leads to a significant (approximately 2x) increase in lag from explosions. This is less likely to be felt on the scale of a single explosion at a time, however it has a notably outsized affect on players who use contraptions that use many TNT or have many entities in close proximity to explosions.
Data from in-game testing in versions 23w44a and 23w45a (shows test setup):
https://www.desmos.com/calculator/oqccbpau9w
Background (for analysis):
The value returned by the getSeenPercent method represents what proportion of an entity is "exposed" to an explosion, and it is a value that ranges from 0 to 1. The value is sometimes colloquially called the "exposure". The lower an entity's exposure, the less of an effect the explosion has on the entity. Exposure is used when calculating how much the explosion damages an entity, as well as how much the explosion propels the entity. The method uses an array of "raycasts" that probe the area between the entity and the explosion for blocks that may protect the entity from the explosion. These raycasts can number in the dozens per entity, and each requires a non-trivial amount of math to compute.Code Analysis [brackets refer to attached screenshots]:
- Prior to 23w45a, getSeenPercent was computed only once and stored in a variable that was then used by both the entity damage and propulsion computations [1a].
- Snapshot 23w45a introduced wind charges, which create non-damaging explosions. In order to allow some explosions to cause no health damage, a condition was added during the explode method that skips computing damage if the damageSource for the explosion is null [1b]. Therefore, explosions with damageSource == null (like those of wind charges) do not hurt entities.
- The default Explosion constructor previously overwrote null damageSource values with a non-null value [2a], so in 23w45a the constructor was also modified to accept null damageSource [2b].
Altogether, this means that the logic for skipping damage would work simply by wrapping the existing damage code (1 line of code; see [1a]) in the conditional statement previously mentioned.Despite this, as of 23w45a, the explosion's damage calculation was relocated to a different class, in a new method that takes only an Explosion object and an entity as parameters [3]. This means that to have the necessary values to compute the damage, the costly exposure computation and a handful of helper values need to be recomputed from scratch using the positions of the explosion and entity, even though all of them are already computed in the explode method __ for the applied velocity calculation [see 1b again]. As a result, each explosion now has about twice the amount of work when processing how it affects entities.
Snapshot 23w45a introduces a redundant set of calculations during the explode method, which leads to a significant (approximately 2x) increase in lag from explosions. This is less likely to be felt on the scale of a single explosion at a time, however it has a notably outsized affect on players who use contraptions that use many TNT or have many entities in close proximity to explosions.
Data from in-game testing in versions 23w44a and 23w45a (shows test setup):
https://www.desmos.com/calculator/oqccbpau9w
Background (for analysis):
The value returned by the getSeenPercent method represents what proportion of an entity is "exposed" to an explosion, and it is a value that ranges from 0 to 1. The value is sometimes colloquially called the "exposure". The lower an entity's exposure, the less of an effect the explosion has on the entity. Exposure is used when calculating how much the explosion damages an entity, as well as how much the explosion propels the entity. The method uses an array of "raycasts" that probe the area between the entity and the explosion for blocks that may protect the entity from the explosion. These raycasts can number in the dozens per entity, and each requires a non-trivial amount of math to compute.Code Analysis [brackets refer to attached screenshots]:
- Prior to 23w45a, getSeenPercent was computed only once and stored in a variable that was then used by both the entity damage and propulsion computations [1a].
- Snapshot 23w45a introduced wind charges, which create non-damaging explosions. In order to allow some explosions to cause no health damage, a condition was added during the explode method that skips computing damage if the damageSource for the explosion is null [1b]. Therefore, explosions with damageSource == null (like those of wind charges) do not hurt entities.
- The default Explosion constructor previously overwrote null damageSource values with a non-null value [2a], so in 23w45a the constructor was also modified to accept null damageSource [2b].
Altogether, this means that the logic for skipping damage would work simply by wrapping the existing damage code (1 line of code; see [1a]) in the conditional statement previously mentioned.Despite this, as of 23w45a, the explosion's damage calculation was relocated to a different class, in a new method that takes only an Explosion object and an entity as parameters [3]. This means that to have the necessary values to compute the damage, the costly exposure computation and a handful of helper values need to be recomputed from scratch using the positions of the explosion and entity, even though all of them are already computed in the explode method
__for the applied velocity calculation [see 1b again]. As a result, each explosion now has about twice the amount of work when processing how it affects entities.
Snapshot 23w45a introduces a redundant set of calculations during the explode method, which leads to a significant (approximately 2x) increase in lag from explosions. This is less likely to be felt on the scale of a single explosion at a time, however it has a notably outsized affect on players who use contraptions that use many TNT or have many entities in close proximity to explosions.
Data from in-game testing in versions 23w44a and 23w45a (shows test setup):
https://www.desmos.com/calculator/oqccbpau9w
Background (for analysis):
The value returned by the getSeenPercent method represents what proportion of an entity is "exposed" to an explosion, and it is a value that ranges from 0 to 1. The value is sometimes colloquially called the "exposure". The lower an entity's exposure, the less of an effect the explosion has on the entity. Exposure is used when calculating how much the explosion damages an entity, as well as how much the explosion propels the entity. The method uses an array of "raycasts" that probe the area between the entity and the explosion for blocks that may protect the entity from the explosion. These raycasts can number in the dozens per entity, and each requires a non-trivial amount of math to compute.Code Analysis [brackets refer to attached screenshots]:
- Prior to 23w45a, getSeenPercent was computed only once and stored in a variable that was then used by both the entity damage and propulsion computations [1a].
- Snapshot 23w45a introduced wind charges, which create non-damaging explosions. In order to allow some explosions to cause no health damage, a condition was added during the explode method that skips computing damage if the damageSource for the explosion is null [1b]. Therefore, explosions with damageSource == null (like those of wind charges) do not hurt entities.
- The default Explosion constructor previously overwrote null damageSource values with a non-null value [2a], so in 23w45a the constructor was also modified to accept null damageSource [2b].
Altogether, this means that the logic for skipping damage would work simply by wrapping the existing damage code (1 line of code; see [1a]) in the conditional statement previously mentioned.Despite this, as of 23w45a, the explosion's damage calculation was relocated to a different class, in a new method that takes only an Explosion object and an entity as parameters [3]. This means that to have the necessary values to compute the damage, the costly exposure computation and a handful of helper values need to be recomputed from scratch using the positions of the explosion and entity, even though all of them are already computed in the explode method for the applied velocity calculation [see 1b again]. As a result, each explosion now has about twice the amount of work when processing how it affects entities.
Snapshot 23w45a introduces a redundant set of calculations during the explode method, which leads to a significant (approximately 2x) increase in lag from explosions. This is less likely to be felt on the scale of a single explosion at a time, however it has a notably outsized affect on players who use contraptions that use many TNT or have many entities in close proximity to explosions.
Data from in-game testing in versions 23w44a and 23w45a (shows test setup):
https://www.desmos.com/calculator/c4ccpegwpp
Background (for analysis):
The value returned by the getSeenPercent method represents what proportion of an entity is "exposed" to an explosion, and it is a value that ranges from 0 to 1. The value is sometimes colloquially called the "exposure". The lower an entity's exposure, the less of an effect the explosion has on the entity. Exposure is used when calculating how much the explosion damages an entity, as well as how much the explosion propels the entity. The method uses an array of "raycasts" that probe the area between the entity and the explosion for blocks that may protect the entity from the explosion. These raycasts can number in the dozens per entity, and each requires a non-trivial amount of math to compute.Code Analysis [brackets refer to attached screenshots]:
- Prior to 23w45a, getSeenPercent was computed only once and stored in a variable that was then used by both the entity damage and propulsion computations [1a].
- Snapshot 23w45a introduced wind charges, which create non-damaging explosions. In order to allow some explosions to cause no health damage, a condition was added during the explode method that skips computing damage if the damageSource for the explosion is null [1b]. Therefore, explosions with damageSource == null (like those of wind charges) do not hurt entities.
- The default Explosion constructor previously overwrote null damageSource values with a non-null value [2a], so in 23w45a the constructor was also modified to accept null damageSource [2b].
Altogether, this means that the logic for skipping damage would work simply by wrapping the existing damage code (1 line of code; see [1a]) in the conditional statement previously mentioned.Despite this, as of 23w45a, the explosion's damage calculation was relocated to a different class, in a new method that takes only an Explosion object and an entity as parameters [3]. This means that to have the necessary values to compute the damage, the costly exposure computation and a handful of helper values need to be recomputed from scratch using the positions of the explosion and entity, even though all of them are already computed in the explode method for the applied velocity calculation [see 1b again]. As a result, each explosion now has about twice the amount of work when processing how it affects entities.
Snapshot 23w45a introduces a redundant set of calculations during the explode method, which leads to a significant (approximately 2x) increase in lag from explosions. This is less likely to be felt on the scale of a single explosion at a time, however it has a notably outsized affect on players who use contraptions that use many TNT or have many entities in close proximity to explosions.
Data from in-game testing in versions 23w44a and 23w45a (shows test setup):
https://www.desmos.com/calculator/c4ccpegwpp
Background (for analysis):
The value returned by the getSeenPercent method represents what proportion of an entity is "exposed" to an explosion, and it is a value that ranges from 0 to 1. The value is sometimes colloquially called the "exposure". The lower an entity's exposure, the less of an effect the explosion has on the entity. Exposure is used when calculating how much the explosion damages an entity, as well as how much the explosion propels the entity. The method uses an array of "raycasts" that probe the area between the entity and the explosion for blocks that may protect the entity from the explosion. These raycasts can number in the dozens per entity, and each requires a non-trivial amount of math to compute.Code Analysis [brackets refer to attached screenshots]:
- Prior to 23w45a, getSeenPercent was computed only once and stored in a variable that was then used by both the entity damage and propulsion computations [1a].
- Snapshot 23w45a introduced wind charges, which create non-damaging explosions. In order to allow some explosions to cause no health damage, a condition was added during the explode method that skips computing damage if the damageSource for the explosion is null [1b]. Therefore, explosions with damageSource == null (like those of wind charges) do not hurt entities.
- The default Explosion constructor previously overwrote null damageSource values with a non-null value [2a], so in 23w45a the constructor was also modified to accept null damageSource [2b].
Altogether, this means that the logic for skipping damage would work simply by wrapping the existing damage code (1 line of code; see [1a]) in the conditional statement previously mentioned.Despite this, as of 23w45a, the explosion's damage calculation was relocated to a different class, in a new method that takes only an Explosion object and an entity as parameters [3]. This means that to have the necessary values to compute the damage, the costly exposure computation and a handful of helper values need to be recomputed from scratch using the positions of the explosion and entity, even though all of them are already computed in the explode method for the applied velocity calculation [see 1b again]. As a result, each explosion now has about twice the amount of work when processing how it affects entities.
relates to
can confirm for 1.20.6, here is the test setup for those who want to replicate: explosion_lag_issue.zip
how to use the setup:
-load the world in 1.20.2 (version before the issue is introduced), press the button on the command block (its near the diamond block), wait till the game unfreezes from lag, check how much server is lagging behind in the console
-load the world in 1.20.6 (version after the issue is introduced), press the button, wait till the game unfreezes from lag and check how much server is lagging behind in the console, it should be roughly twice as much behind as the test in 1.20.2 was.
in my own testing this issue indeed made explosions lag about twice as much compared to how it was before the issue was introduced, exact amount of lag is in the attached screenshots.
It is important to note, that even though this issue is marked as related to two other reports, MC-238249 is about a completely different issue (the one related to block breaking and not entity interaction) and the MC-260762 just being a feature request asking to implement an optimization from a certain mod even though it is not vanilla-preserving (as in it breaks vanilla behavior thus breaking even more explosion related contraptions).
However this report (MC-272414), states that since 23w45a the entire exposure calculation is needlessly done twice which worsens the lag from it even more, this leads to tnt cannons becoming too laggy to use for many players. thus entire field of cannon and tnt related redstone suffers a lot, i (and many others from tnt tech community) really hope this issue gets fixed soon.
Through a meta analysis of various minecraft versions and a simple test case involving 100 TnT exploding every 4 gameticks there seems to have been a significant decline in the performance of the TnT explosion code starting in version 1.20.3 and continuing to the latest release. This can be seen in the attatched screenshots showing the milliseconds per tick (/50 ms) of the same test case in different versions
Snapshot 24w33a improved the performance slightly however it still remains at least 2x worse than in 1.20.2 which was found the be the last version where explosion code was most performant in the recent update pool.
Savva looked into the code and found 1.20.3 introduced 2 lag causes to explosion code:
- calculating the exposure twice for each entity, but it is already fixed as stated in
MC-272414and after looking at code and testing in game we can verify that this specific issue is indeed fixed. - something within the block removal logic (its interactWithBlocks method in ServerExplosion.java). We're not sure that there is only one lag causer within, but we can verify that the lag comes from somewhere there, as it is the only part of explosion code which changed significantly from 1.20.2 to 24w33a
To verify that the issue lies within the block removal, one can use the same setup as shown in the screenshots above, but with a liquid source where the explosions happen, that way each explosion will collect no block positions for blocks to be exploded, thus skipping almost the entire block removal part of the explosion but not the other parts of the explosion, and indeed from our testing there is no lag difference in between 1.20.2 and 24w34a with water present.
Yet without water the lag difference between versions is about x1.5
100 TnT explosions is a relatively moderate amount in the average players gameplay environment. As shown in older versions such as 1.19.4 and 1.20.2 this amount of TnT would only consume half of the computation time for my particular machine that is possibly better than what most players could afford.
Proliferation of Minecraft's code without consideration for the impacts on performance threatens to push newer players on lower end systems out of the Minecraft community and so these optimization issues should be taken with great concern.
1.20.3 introduced 2 lag causes to explosion code:
- calculating the exposure twice for each entity, but it is already fixed as stated in
MC-272414and after looking at code and testing in game i can verify that this specific issue is indeed fixed. - something within the block removal logic (its interactWithBlocks method in ServerExplosion.java). Im not sure that there is only one lag causer within, but i can verify that the lag comes from somewhere there, as it is the only part of explosion code which changed significantly from 1.20.2 to 24w33a
To verify that the issue lies within the block removal, one can use the same setup as shown in the screenshots above, but with a liquid source where the explosions happen, that way each explosion will collect no block positions for blocks to be exploded, thus skipping almost the entire block removal part of the explosion but not the other parts of the explosion, and indeed from my testing there is no lag difference in between 1.20.2 and 24w34a with water present.
Yet without water the lag difference between versions is about x1.5
i hope someone can post a propper code analisys of the block removal part of the explosion, if noone does ill do it later





Should be clear from the writeup, but this affects versions since 23w45a, and 1.20.3 is the first full version that it affects. But the "Affects Version/s" box wouldn't accept anything but 1.20.6.
can confirm for 1.20.6, here is the test setup for those who want to replicate: explosion_lag_issue.zip
how to use the setup:
-load the world in 1.20.2 (version before the issue is introduced), press the button on the command block (its near the diamond block), wait till the game unfreezes from lag, check how much server is lagging behind in the console
-load the world in 1.20.6 (version after the issue is introduced), press the button, wait till the game unfreezes from lag and check how much server is lagging behind in the console, it should be roughly twice as much behind as the test in 1.20.2 was.
in my own testing this issue indeed made explosions lag about twice as much compared to how it was before the issue was introduced, exact amount of lag is in the attached screenshots.
It is important to note, that even though this issue is marked as related to two other reports, MC-238249 is about a completely different issue (the one related to block breaking and not entity interaction) and the MC-260762 just being a feature request asking to implement an optimization from a certain mod even though it is not vanilla-preserving (as in it breaks vanilla behavior thus breaking even more explosion related contraptions).
However this report (
MC-272414), states that since 23w45a the entire exposure calculation is needlessly done twice which worsens the lag from it even more, this leads to tnt cannons becoming too laggy to use for many players. thus entire field of cannon and tnt related redstone suffers a lot, i (and many others from tnt tech community) really hope this issue gets fixed soon.can confirm in 1.20.6