added buffering to boost performance

This commit is contained in:
2019-09-28 09:41:21 +01:00
parent 428c4a68d5
commit 51a7e8ffb0
5 changed files with 42 additions and 43 deletions

View File

@@ -30,7 +30,7 @@ public class Main {
@SneakyThrows
private static InputStream extractTestData() {
return new XZInputStream(new BufferedInputStream(Main.class.getResourceAsStream("/citylots.json.xz")));
return new XZInputStream(Main.class.getResourceAsStream("/citylots.json.xz"));
}
@SneakyThrows
@@ -62,7 +62,7 @@ public class Main {
for (int j = 0; j < 2; j++) {
chr.reset();
for (int i = 0; i < loops; i++) {
Value value = new JSONParser().parse(smallTestData());
Value value = new JSONParser().parse(new BufferedReader(new InputStreamReader(smallTestData())));
}
}
worthTime = chr.stop(Chronometer.TimeUnit.MILLISECOND);
@@ -98,7 +98,7 @@ public class Main {
try (InputStream is = extractTestData()) {
chr.reset();
ObjectMapper om = new ObjectMapper();
om.readTree(is);
om.readTree(new InputStreamReader(is));
double elapsedTime = chr.stop(Chronometer.TimeUnit.SECOND);
System.out.printf("Jackson time: %8s sec\n", String.format("%.3f", elapsedTime));
}

View File

@@ -8,7 +8,11 @@ import java.io.Reader;
public class LookAheadTextInputStream extends InputStream {
private final Reader reader;
private int currentByte;
private char[] buffer = new char[1024];
private int bufferFill = -1;
private int cursor = -1;
private int currentChar;
public LookAheadTextInputStream(Reader reader) {
this.reader = reader;
@@ -17,12 +21,21 @@ public class LookAheadTextInputStream extends InputStream {
@Override
@SneakyThrows
public int read() {
int result = currentByte;
currentByte = reader.read();
return result;
if (cursor > bufferFill) {
return -1;
} else if (cursor == bufferFill) {
do {
bufferFill = reader.read(buffer, 0, buffer.length) - 1;
cursor = 0;
} while(bufferFill == -1);
currentChar = bufferFill == -2 ? -1 : buffer[0];
} else {
currentChar = buffer[++cursor];
}
return currentChar;
}
public int getCurrentByte(){
return currentByte;
public int getCurrentByte() {
return currentChar;
}
}

View File

@@ -27,10 +27,10 @@ public class JSONParser extends ValueParser {
return c >= '0' && c <= '9' || c == '+' || c == '-' || c == '.' || c == 'e';
}
private static int parseHex(LookAheadTextInputStream stream) {
static int parseHex(LookAheadTextInputStream stream) {
int result = 0;
while (true) {
int c = stream.getCurrentByte();
int c = stream.getCurrentByte();
while (c != -1) {
if (c >= '0' && c <= '9') {
result = result << 4;
result += (c - '0');
@@ -43,7 +43,7 @@ public class JSONParser extends ValueParser {
} else {
break;
}
stream.read();
c = stream.read();
}
return result;
}
@@ -64,19 +64,19 @@ public class JSONParser extends ValueParser {
return sb.toString();
}
private final int parseId(LookAheadTextInputStream stream) {
private int parseId(LookAheadTextInputStream stream) {
StringBuilder sb = new StringBuilder();
boolean digitsStarted = false;
boolean digitsEnded = false;
while (true) {
int b = stream.getCurrentByte();
if(b == '(' ) {
} else if(Character.isWhitespace(b)) {
if(digitsStarted) digitsEnded = true;
if (b == '(') {
} else if (Character.isWhitespace(b)) {
if (digitsStarted) digitsEnded = true;
} else if (b < 0 || b == ')') {
break;
} else if (isDecimal(b)) {
if(digitsEnded) {
if (digitsEnded) {
error(ParseException::new, "error parsing id");
} else {
digitsStarted = true;
@@ -85,7 +85,7 @@ public class JSONParser extends ValueParser {
}
stream.read();
}
return Integer.valueOf(sb.toString());
return Integer.parseInt(sb.toString());
}
private String readString(LookAheadTextInputStream stream) {
@@ -151,14 +151,15 @@ public class JSONParser extends ValueParser {
}
@Override
protected <T extends RuntimeException> T error(Function<String, T> constructor, String fmt, Object ...args) {
protected <T extends RuntimeException> T error(Function<String, T> constructor, String fmt, Object... args) {
return constructor.apply(String.format("Error at line %d column %d: %s",
currentLine, currentColumn, String.format(fmt, args)));
currentLine, currentColumn, String.format(fmt, args)));
}
public static Parser newInstance() {
return new JSONParser();
}
public static Parser newInstance(Value.Configuration cfg) {
return new JSONParser(cfg);
}
@@ -192,6 +193,7 @@ public class JSONParser extends ValueParser {
return result;
}
};
stream.read();
try {
Integer currentId = null;
@@ -204,13 +206,13 @@ public class JSONParser extends ValueParser {
currentId = parseId(stream);
} else if (c == '{') {
Value newObject = beginObject();
if(currentId != null) valueId(currentId, newObject);
if (currentId != null) valueId(currentId, newObject);
currentId = null;
} else if (c == '}') {
endObject();
} else if (c == '[') {
Value newArray = beginArray();
if(currentId != null) valueId(currentId, newArray);
if (currentId != null) valueId(currentId, newArray);
currentId = null;
} else if (c == ']') {
endArray();
@@ -246,7 +248,7 @@ public class JSONParser extends ValueParser {
} else if (idMap != null && c == '$') {
stream.read();
String text = parseNumber(stream);
valueReference(Integer.valueOf(text));
valueReference(Integer.parseInt(text));
continue;
}
stream.read();
@@ -262,7 +264,7 @@ public class JSONParser extends ValueParser {
}
throw error(ParseException::new, "Missing '%c' token", c);
}
return WorthUtils.dynamicCast(stack.getFirst(), ArrayStackLevel.class).value.get(0);
return ((ArrayStackLevel) stack.getFirst()).value.get(0);
} catch (NumberFormatException e) {
throw error(ParseException::new, e.getMessage());
} finally {

View File

@@ -79,18 +79,4 @@ public class JBONTest {
Assert.assertEquals(originalValue, binarySerializedValue);
}
}
@Test
@SneakyThrows
public void hexTest() {
String hex = "1F608";
byte[] buffer = hex.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
Method method = JSONParser.class.getDeclaredMethod("parseHex", LookAheadTextInputStream.class);
method.setAccessible(true);
LookAheadTextInputStream ltis = new LookAheadTextInputStream(new InputStreamReader(bais));
ltis.read();
int result = (int) method.invoke(null, ltis);
Assert.assertEquals((int) Integer.valueOf(hex, 16), result);
}
}

View File

@@ -228,11 +228,9 @@ public class JSONTest {
String hex = "1F608";
byte[] buffer = hex.getBytes();
ByteArrayInputStream bais = new ByteArrayInputStream(buffer);
Method method = JSONParser.class.getDeclaredMethod("parseHex", LookAheadTextInputStream.class);
method.setAccessible(true);
LookAheadTextInputStream ltis = new LookAheadTextInputStream(new InputStreamReader(bais));
ltis.read();
int result = (int) method.invoke(null, ltis);
Assert.assertEquals((int) Integer.valueOf(hex, 16), result);
int result = JSONParser.parseHex(ltis);
Assert.assertEquals(Integer.parseInt(hex, 16), result);
}
}