- Timestamp:
- 2022-04-19T19:12:51+02:00 (3 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/data
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/Command.java
r17867 r18431 23 23 ClosePath((byte) 7, (byte) 0); 24 24 25 private static final Command[] CACHED_VALUES = Command.values(); 25 26 private final byte id; 26 27 private final byte parameters; … … 46 47 return this.parameters; 47 48 } 49 50 /** 51 * Get a pre-calculated array of all {@link Command} values. 52 * @return An array of values, meant as a drop-in replacement for {@link Command#values()} 53 * <i>where the array is not modified</i>! This can significantly reduce allocations, as there is no defensive 54 * array copy. 55 */ 56 static Command[] getAllValues() { 57 return CACHED_VALUES; 58 } 48 59 } -
trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/CommandInteger.java
r17994 r18431 3 3 4 4 import java.util.Arrays; 5 import java.util.stream.Stream;6 5 7 6 /** … … 22 21 // Technically, the int is unsigned, but it is easier to work with the long 23 22 final long unsigned = Integer.toUnsignedLong(command); 24 this.type = Stream.of(Command.values()).filter(e -> e.getId() == (unsigned & 0x7)).findAny() 25 .orElseThrow(InvalidMapboxVectorTileException::new); 23 // By avoiding using a stream for getting the Command type, we go from 72 MB to 13 MB. 24 // By using a cached value for Command.values(), we further reduce the allocations to 5 MB (new short[] call 25 // at end of initializer) 26 Command rType = null; 27 for (Command tType : Command.getAllValues()) { 28 if (tType.getId() == (unsigned & 0x7)) { 29 rType = tType; 30 break; 31 } 32 } 33 this.type = rType; 34 if (this.type == null) { 35 throw new InvalidMapboxVectorTileException(); 36 } 37 26 38 // This is safe, since we are shifting right 3 when we converted an int to a long (for unsigned). 27 39 // So we <i>cannot</i> lose anything. -
trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/Feature.java
r17994 r18431 25 25 private static final byte GEOMETRY_TYPE_FIELD = 3; 26 26 private static final byte GEOMETRY_FIELD = 4; 27 /** 28 * The number format instance to use (using a static instance gets rid of quite o few allocations) 29 * Doing this reduced the allocations of {@link #parseTagValue(String, Layer, Number)} from 22.79% of parent to 30 * 12.2% of parent. 31 */ 32 private static final NumberFormat NUMBER_FORMAT = NumberFormat.getNumberInstance(Locale.ROOT); 27 33 /** 28 34 * The geometry of the feature. Required. … … 112 118 if (value instanceof Double || value instanceof Float) { 113 119 // reset grouping if the instance is a singleton 114 final NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.ROOT); 115 final boolean grouping = numberFormat.isGroupingUsed();120 121 final boolean grouping = NUMBER_FORMAT.isGroupingUsed(); 116 122 try { 117 numberFormat.setGroupingUsed(false);118 this.tags.put(key, numberFormat.format(value));123 NUMBER_FORMAT.setGroupingUsed(false); 124 this.tags.put(key, NUMBER_FORMAT.format(value)); 119 125 } finally { 120 numberFormat.setGroupingUsed(grouping);126 NUMBER_FORMAT.setGroupingUsed(grouping); 121 127 } 122 128 } else { -
trunk/src/org/openstreetmap/josm/data/protobuf/ProtobufPacked.java
r17867 r18431 2 2 package org.openstreetmap.josm.data.protobuf; 3 3 4 import java.io.ByteArrayOutputStream; 4 5 import java.util.ArrayList; 5 6 import java.util.List; … … 25 26 this.bytes = bytes; 26 27 List<Number> numbersT = new ArrayList<>(); 28 // By reusing a ByteArrayOutputStream, we can reduce allocations in nextVarInt from 230 MB to 74 MB. 29 ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(4); 27 30 while (this.location < bytes.length) { 28 numbersT.add(ProtobufParser.convertByteArray(this.nextVarInt(), ProtobufParser.VAR_INT_BYTE_SIZE)); 31 numbersT.add(ProtobufParser.convertByteArray(this.nextVarInt(byteArrayOutputStream), ProtobufParser.VAR_INT_BYTE_SIZE)); 32 byteArrayOutputStream.reset(); 29 33 } 30 34 … … 44 48 } 45 49 46 private byte[] nextVarInt() { 47 List<Byte> byteList = new ArrayList<>(); 50 private byte[] nextVarInt(final ByteArrayOutputStream byteArrayOutputStream) { 51 // In a real world test, the largest List<Byte> seen had 3 elements. Use 4 to avoid most new array allocations. 52 // Memory allocations went from 368 MB to 280 MB by using an initial array allocation. When using a 53 // ByteArrayOutputStream, it went down to 230 MB. 48 54 while ((this.bytes[this.location] & ProtobufParser.MOST_SIGNIFICANT_BYTE) 49 55 == ProtobufParser.MOST_SIGNIFICANT_BYTE) { 50 56 // Get rid of the leading bit (shift left 1, then shift right 1 unsigned) 51 byte List.add((byte) (this.bytes[this.location++] ^ ProtobufParser.MOST_SIGNIFICANT_BYTE));57 byteArrayOutputStream.write(this.bytes[this.location++] ^ ProtobufParser.MOST_SIGNIFICANT_BYTE); 52 58 } 53 59 // The last byte doesn't drop the most significant bit 54 byteList.add(this.bytes[this.location++]); 55 byte[] byteArray = new byte[byteList.size()]; 56 for (int i = 0; i < byteList.size(); i++) { 57 byteArray[i] = byteList.get(i); 58 } 59 60 return byteArray; 60 byteArrayOutputStream.write(this.bytes[this.location++]); 61 return byteArrayOutputStream.toByteArray(); 61 62 } 62 63 } -
trunk/src/org/openstreetmap/josm/data/protobuf/ProtobufParser.java
r17867 r18431 4 4 import java.io.BufferedInputStream; 5 5 import java.io.ByteArrayInputStream; 6 import java.io.ByteArrayOutputStream; 6 7 import java.io.IOException; 7 8 import java.io.InputStream; 8 9 import java.util.ArrayList; 9 10 import java.util.Collection; 10 import java.util.List;11 11 12 12 import org.openstreetmap.josm.tools.Logging; … … 156 156 this.inputStream.mark(16); 157 157 try { 158 return WireType. values()[this.inputStream.read() << 3];158 return WireType.getAllValues()[this.inputStream.read() << 3]; 159 159 } finally { 160 160 this.inputStream.reset(); … … 212 212 */ 213 213 public byte[] nextVarInt() throws IOException { 214 List<Byte> byteList = new ArrayList<>(); 214 // Using this reduces the allocations from 150 MB to 95 MB. 215 final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(4); 215 216 int currentByte = this.nextByte(); 216 217 while ((byte) (currentByte & MOST_SIGNIFICANT_BYTE) == MOST_SIGNIFICANT_BYTE && currentByte > 0) { 217 218 // Get rid of the leading bit (shift left 1, then shift right 1 unsigned) 218 byte List.add((byte)(currentByte ^ MOST_SIGNIFICANT_BYTE));219 byteArrayOutputStream.write((currentByte ^ MOST_SIGNIFICANT_BYTE)); 219 220 currentByte = this.nextByte(); 220 221 } 221 222 // The last byte doesn't drop the most significant bit 222 byteList.add((byte) currentByte); 223 byte[] byteArray = new byte[byteList.size()]; 224 for (int i = 0; i < byteList.size(); i++) { 225 byteArray[i] = byteList.get(i); 226 } 227 228 return byteArray; 223 byteArrayOutputStream.write(currentByte); 224 return byteArrayOutputStream.toByteArray(); 229 225 } 230 226 -
trunk/src/org/openstreetmap/josm/data/protobuf/ProtobufRecord.java
r17867 r18431 4 4 import java.io.IOException; 5 5 import java.nio.charset.StandardCharsets; 6 import java.util.stream.Stream;7 6 8 7 import org.openstreetmap.josm.tools.Utils; … … 32 31 // 7 is 111 (so last three bits) 33 32 byte wireType = (byte) (number.longValue() & 7); 34 this.type = Stream.of(WireType.values()).filter(wType -> wType.getTypeRepresentation() == wireType).findFirst() 35 .orElse(WireType.UNKNOWN); 33 // By not using a stream, we reduce the number of allocations (for getting the WireType) from 257 MB to 40 MB. 34 // (The remaining 40 MB is from WireType#values). By using the cached getAllValues(), we drop the 40 MB. 35 WireType tType = null; 36 for (WireType wType : WireType.getAllValues()) { 37 if (wType.getTypeRepresentation() == wireType) { 38 tType = wType; 39 break; 40 } 41 } 42 this.type = tType; 36 43 37 44 if (this.type == WireType.VARINT) { -
trunk/src/org/openstreetmap/josm/data/protobuf/WireType.java
r17867 r18431 45 45 UNKNOWN(Byte.MAX_VALUE); 46 46 47 private static final WireType[] CACHED_VALUES = values(); 48 47 49 private final byte type; 48 50 … … 59 61 return this.type; 60 62 } 63 64 /** 65 * Get a pre-calculated array of all {@link WireType} values. 66 * @return An array of values, meant as a drop-in replacement for {@link WireType#values()} 67 * <i>where the array is not modified</i>! This can significantly reduce allocations, as there is no defensive 68 * array copy. 69 */ 70 static WireType[] getAllValues() { 71 return CACHED_VALUES; 72 } 61 73 }
Note:
See TracChangeset
for help on using the changeset viewer.