Uploaded image for project: 'Minecraft: Java Edition'
  1. Minecraft: Java Edition
  2. MC-217303

Potential optimization target in DepthBasedReplacingBaseStoneSource

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Resolution: Fixed
    • Affects Version/s: 21w08b
    • Fix Version/s: 21w11a
    • Labels:
      None
    • Confirmation Status:
      Plausible
    • Category:
      Performance
    • Mojang Priority:
      Important

      Description

      The bug

      When run through a profiler, DepthBasedReplacingBaseStoneSource is seen to take up a significant part of the time while generating chunks. This is because the random.nextFloat() is called for every solid block, regardless of whether it'll be able to generate deepslate or not (above or at 0 and below or at -8). The majority of the CPU time within this method is spent in Random#nextLong as it calculates the random values for every placed block. The optimization here is to compute these nextLong calls ahead of time in the constructor as they are static per seed, as well as only calculating the random in y levels that can contain a mix of both stone blocks.
      Here is the code that will fix it:

      private final WorldgenRandom random;
      private final long seed;
      private final BlockState normalBlock;
      private final BlockState replacementBlock;
      private final long longX;
      private final long longY;
      private final long longZ;
      
      public DepthBasedReplacingBaseStoneSource(long seed, BlockState normalBlock, BlockState replacementBlock) {
          this.random = new WorldgenRandom(seed);
          this.seed = seed;
          this.normalBlock = normalBlock;
          this.replacementBlock = replacementBlock;
          this.longX = this.random.nextLong();
          this.longY = this.random.nextLong();
          this.longZ = this.random.nextLong();
      }
      
      @Override
      public BlockState getBaseStone(int x, int y, int z, NoiseGeneratorSettings settings) {
          if (!settings.isDeepslateEnabled() || y >= 0) {
              return this.normalBlock;
          } else if (y <= -8) {
              return this.replacementBlock;
          } else {
              this.random.setSeed((x * longX) ^ (y * longY) ^ (z * longZ) ^ this.seed);
              double chance = Mth.clampedMap(y, -8.0, 0.0, 1.0, 0.0);
              return this.random.nextFloat() < chance ? this.replacementBlock : this.normalBlock;
          }
      }
      

      This should maintain the same deepslate generation from before. My changes here are licensed CC0. When measuring with a profiler while generating chunks constantly, deepslate generation took up 5% of the total CPU time. These changes made it take up 0.2% instead, a significant improvement.

        Attachments

          Activity

            People

            Assignee:
            slicedlime [Mojang] slicedlime
            Reporter:
            SuperCoder79 SuperCoder79
            Votes:
            3 Vote for this issue
            Watchers:
            4 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:
              CHK: