source:
josm/trunk/src/org/openstreetmap/josm/data/protobuf/ProtobufPacked.java@
18431
| Last change on this file since 18431 was 18431, checked in by , 4 years ago | |
|---|---|
| File size: 2.3 KB | |
| Line | |
|---|---|
| 1 | // License: GPL. For details, see LICENSE file. |
| 2 | package org.openstreetmap.josm.data.protobuf; |
| 3 | |
| 4 | import java.io.ByteArrayOutputStream; |
| 5 | import java.util.ArrayList; |
| 6 | import java.util.List; |
| 7 | |
| 8 | /** |
| 9 | * Parse packed values (only numerical values) |
| 10 | * |
| 11 | * @author Taylor Smock |
| 12 | * @since 17862 |
| 13 | */ |
| 14 | public class ProtobufPacked { |
| 15 | private final byte[] bytes; |
| 16 | private final Number[] numbers; |
| 17 | private int location; |
| 18 | |
| 19 | /** |
| 20 | * Create a new ProtobufPacked object |
| 21 | * |
| 22 | * @param bytes The packed bytes |
| 23 | */ |
| 24 | public ProtobufPacked(byte[] bytes) { |
| 25 | this.location = 0; |
| 26 | this.bytes = bytes; |
| 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); |
| 30 | while (this.location < bytes.length) { |
| 31 | numbersT.add(ProtobufParser.convertByteArray(this.nextVarInt(byteArrayOutputStream), ProtobufParser.VAR_INT_BYTE_SIZE)); |
| 32 | byteArrayOutputStream.reset(); |
| 33 | } |
| 34 | |
| 35 | this.numbers = new Number[numbersT.size()]; |
| 36 | for (int i = 0; i < numbersT.size(); i++) { |
| 37 | this.numbers[i] = numbersT.get(i); |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | * Get the parsed number array |
| 43 | * |
| 44 | * @return The number array |
| 45 | */ |
| 46 | public Number[] getArray() { |
| 47 | return this.numbers; |
| 48 | } |
| 49 | |
| 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. |
| 54 | while ((this.bytes[this.location] & ProtobufParser.MOST_SIGNIFICANT_BYTE) |
| 55 | == ProtobufParser.MOST_SIGNIFICANT_BYTE) { |
| 56 | // Get rid of the leading bit (shift left 1, then shift right 1 unsigned) |
| 57 | byteArrayOutputStream.write(this.bytes[this.location++] ^ ProtobufParser.MOST_SIGNIFICANT_BYTE); |
| 58 | } |
| 59 | // The last byte doesn't drop the most significant bit |
| 60 | byteArrayOutputStream.write(this.bytes[this.location++]); |
| 61 | return byteArrayOutputStream.toByteArray(); |
| 62 | } |
| 63 | } |
Note:
See TracBrowser
for help on using the repository browser.
