Skip to content

Commit 153eedd

Browse files
Optimize memory usage for 1.7 chunk rewriting (#577)
* Optimize memory usage * Bump version; cleanup code --------- Co-authored-by: FlorianMichael <florian.michael07@gmail.com>
1 parent 2d40460 commit 153eedd

File tree

4 files changed

+65
-16
lines changed

4 files changed

+65
-16
lines changed

common/src/main/java/com/viaversion/viarewind/api/minecraft/ExtendedBlockStorage.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import com.viaversion.viaversion.api.minecraft.chunks.NibbleArray;
2222

2323
public class ExtendedBlockStorage {
24-
private final byte[] blockLSBArray = new byte[4096];
24+
private final byte[] blockLSBArray = new byte[ChunkSection.SIZE];
2525

2626
private final NibbleArray blockMetadataArray = new NibbleArray(this.blockLSBArray.length);
2727
private final NibbleArray blockLightArray = new NibbleArray(this.blockLSBArray.length);

common/src/main/java/com/viaversion/viarewind/api/type/chunk/BulkChunkType1_7_6.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import com.viaversion.viaversion.util.Pair;
2424
import io.netty.buffer.ByteBuf;
2525

26-
import java.io.ByteArrayOutputStream;
2726
import java.util.zip.Deflater;
2827

2928
public class BulkChunkType1_7_6 extends Type<Chunk[]> {
@@ -42,18 +41,22 @@ public Chunk[] read(ByteBuf byteBuf) {
4241
@Override
4342
public void write(ByteBuf byteBuf, Chunk[] chunks) {
4443
final int chunkCount = chunks.length;
45-
final ByteArrayOutputStream output = new ByteArrayOutputStream();
4644
final int[] chunkX = new int[chunkCount];
4745
final int[] chunkZ = new int[chunkCount];
4846
final short[] primaryBitMask = new short[chunkCount];
4947
final short[] additionalBitMask = new short[chunkCount];
5048

49+
final byte[][] dataArrays = new byte[chunkCount][];
50+
int dataSize = 0;
51+
5152
for (int i = 0; i < chunkCount; i++) {
5253
final Chunk chunk = chunks[i];
5354
Pair<byte[], Short> chunkData;
5455
try {
5556
chunkData = ChunkType1_7_6.serialize(chunk);
56-
output.write(chunkData.key());
57+
final byte[] data = chunkData.key();
58+
dataArrays[i] = data;
59+
dataSize += data.length;
5760
} catch (Exception e) {
5861
throw new RuntimeException("Unable to serialize chunk", e);
5962
}
@@ -62,7 +65,13 @@ public void write(ByteBuf byteBuf, Chunk[] chunks) {
6265
primaryBitMask[i] = (short) chunk.getBitmask();
6366
additionalBitMask[i] = chunkData.value();
6467
}
65-
final byte[] data = output.toByteArray();
68+
69+
final byte[] data = new byte[dataSize];
70+
int destPos = 0;
71+
for (final byte[] array : dataArrays) {
72+
System.arraycopy(array, 0, data, destPos, array.length);
73+
destPos += array.length;
74+
}
6675

6776
final Deflater deflater = new Deflater();
6877
byte[] compressedData;

common/src/main/java/com/viaversion/viarewind/api/type/chunk/ChunkType1_7_6.java

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323
import com.viaversion.viaversion.util.Pair;
2424
import io.netty.buffer.ByteBuf;
2525

26-
import java.io.ByteArrayOutputStream;
2726
import java.io.IOException;
2827
import java.util.zip.Deflater;
2928

29+
import static com.viaversion.viaversion.api.minecraft.chunks.ChunkSection.SIZE;
30+
import static com.viaversion.viaversion.api.minecraft.chunks.ChunkSectionLight.LIGHT_LENGTH;
31+
3032
public class ChunkType1_7_6 extends Type<Chunk> {
3133

3234
public static final ChunkType1_7_6 TYPE = new ChunkType1_7_6();
@@ -94,46 +96,84 @@ public static Pair<byte[], Short> serialize(final Chunk chunk) throws IOExceptio
9496
}
9597
}
9698

97-
final ByteArrayOutputStream output = new ByteArrayOutputStream();
99+
final boolean biomes = chunk.isFullChunk() && chunk.getBiomeData() != null;
100+
final int totalSize = calculateSize(storageArrays, chunk.getBitmask(), biomes);
101+
102+
final byte[] output = new byte[totalSize];
103+
int index = 0;
98104

99105
for (int i = 0; i < storageArrays.length; i++) {
100106
if ((chunk.getBitmask() & 1 << i) != 0) {
101-
output.write(storageArrays[i].getBlockLSBArray());
107+
final byte[] blockLSBArray = storageArrays[i].getBlockLSBArray();
108+
System.arraycopy(blockLSBArray, 0, output, index, blockLSBArray.length);
109+
index += blockLSBArray.length;
102110
}
103111
}
104112

105113
for (int i = 0; i < storageArrays.length; i++) {
106114
if ((chunk.getBitmask() & 1 << i) != 0) {
107-
output.write(storageArrays[i].getBlockMetadataArray().getHandle());
115+
final byte[] blockMetadataArray = storageArrays[i].getBlockMetadataArray().getHandle();
116+
System.arraycopy(blockMetadataArray, 0, output, index, blockMetadataArray.length);
117+
index += blockMetadataArray.length;
108118
}
109119
}
110120

111121
for (int i = 0; i < storageArrays.length; i++) {
112122
if ((chunk.getBitmask() & 1 << i) != 0) {
113-
output.write(storageArrays[i].getBlockLightArray().getHandle());
123+
final byte[] blockLightArray = storageArrays[i].getBlockLightArray().getHandle();
124+
System.arraycopy(blockLightArray, 0, output, index, blockLightArray.length);
125+
index += blockLightArray.length;
114126
}
115127
}
116128

117129
for (int i = 0; i < storageArrays.length; i++) {
118130
if ((chunk.getBitmask() & 1 << i) != 0 && storageArrays[i].getSkyLightArray() != null) {
119-
output.write(storageArrays[i].getSkyLightArray().getHandle());
131+
final byte[] skyLightArray = storageArrays[i].getSkyLightArray().getHandle();
132+
System.arraycopy(skyLightArray, 0, output, index, skyLightArray.length);
133+
index += skyLightArray.length;
120134
}
121135
}
122136

123137
short additionalBitMask = 0;
124138
for (int i = 0; i < storageArrays.length; i++) {
125139
if ((chunk.getBitmask() & 1 << i) != 0 && storageArrays[i].hasBlockMSBArray()) {
126140
additionalBitMask |= (short) (1 << i);
127-
output.write(storageArrays[i].getOrCreateBlockMSBArray().getHandle());
141+
final byte[] blockMSBArray = storageArrays[i].getOrCreateBlockMSBArray().getHandle();
142+
System.arraycopy(blockMSBArray, 0, output, index, blockMSBArray.length);
143+
index += blockMSBArray.length;
128144
}
129145
}
130146

131-
if (chunk.isFullChunk() && chunk.getBiomeData() != null) {
147+
if (biomes) {
132148
for (int biome : chunk.getBiomeData()) {
133-
output.write(biome);
149+
output[index++] = (byte) biome;
134150
}
135151
}
136152

137-
return new Pair<>(output.toByteArray(), additionalBitMask);
153+
return new Pair<>(output, additionalBitMask);
138154
}
155+
156+
private static int calculateSize(final ExtendedBlockStorage[] storageArrays, final int bitmask, final boolean biomes) {
157+
int totalSize = 0;
158+
for (int i = 0; i < storageArrays.length; i++) {
159+
if ((bitmask & 1 << i) != 0) {
160+
totalSize += SIZE; // Block lsb array
161+
totalSize += SIZE / 2; // Block metadata array
162+
totalSize += LIGHT_LENGTH; // Block light array
163+
164+
if (storageArrays[i].getSkyLightArray() != null) {
165+
totalSize += LIGHT_LENGTH;
166+
}
167+
168+
if (storageArrays[i].hasBlockMSBArray()) {
169+
totalSize += SIZE / 2; // Block msb array
170+
}
171+
}
172+
}
173+
if (biomes) {
174+
totalSize += 256;
175+
}
176+
return totalSize;
177+
}
178+
139179
}

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ org.gradle.parallel=true
44

55
# project
66
maven_group=com.viaversion
7-
maven_version=4.0.7
7+
maven_version=4.0.8-SNAPSHOT
88
maven_description=ViaBackwards addon to allow 1.8.x and 1.7.x clients on newer server versions.
99

1010
# Smile emoji

0 commit comments

Comments
 (0)