diff options
author | Jesse Wilson <jessewilson@google.com> | 2010-11-17 17:46:42 -0800 |
---|---|---|
committer | Jesse Wilson <jessewilson@google.com> | 2010-11-18 23:06:50 -0800 |
commit | 9d9b4e70a1e7f9ffb6cedd8a86fdd926f2a28202 (patch) | |
tree | eb3e42e394a5b9e35f8ef40614815a591d421336 /core/tests | |
parent | 762b33f9494ba48aa1be3701d345b692e8432af9 (diff) | |
download | frameworks_base-9d9b4e70a1e7f9ffb6cedd8a86fdd926f2a28202.zip frameworks_base-9d9b4e70a1e7f9ffb6cedd8a86fdd926f2a28202.tar.gz frameworks_base-9d9b4e70a1e7f9ffb6cedd8a86fdd926f2a28202.tar.bz2 |
Decode JSON literal types eagerly and with our own decoder.
Previously we relied on Double.parseDouble() to decode tokens. Since
that method is expensive, we deferred calling it unless absolutely
necessary.
Now we decode the literal type immediately. For efficiency we decode
the token right out of the char buffer. This makes things more
complicated but it saves many calls to charAt().
With this change overall performance is 7% faster for JSON documents
cited in the bug.
benchmark run ms linear runtime %
GsonParseFull no switch, no int parse 309 ============================ 93%
GsonParseFull baseline 330 ============================== 100%
http://b/3201883
Change-Id: I436b6769956b1357a17c807a327d3a234691c73f
Diffstat (limited to 'core/tests')
-rw-r--r-- | core/tests/coretests/src/android/util/JsonReaderTest.java | 159 |
1 files changed, 145 insertions, 14 deletions
diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java index ced9310..216a772 100644 --- a/core/tests/coretests/src/android/util/JsonReaderTest.java +++ b/core/tests/coretests/src/android/util/JsonReaderTest.java @@ -16,6 +16,7 @@ package android.util; +import java.util.Arrays; import junit.framework.TestCase; import java.io.IOException; @@ -23,6 +24,8 @@ import java.io.StringReader; public final class JsonReaderTest extends TestCase { + private static final int READER_BUFFER_SIZE = 1024; + public void testReadArray() throws IOException { JsonReader reader = new JsonReader(new StringReader("[true, true]")); reader.beginArray(); @@ -178,7 +181,13 @@ public final class JsonReaderTest extends TestCase { + "-0.5," + "2.2250738585072014E-308," + "3.141592653589793," - + "2.718281828459045]"; + + "2.718281828459045," + + "\"1.0\"," + + "\"011.0\"," + + "\"NaN\"," + + "\"Infinity\"," + + "\"-Infinity\"" + + "]"; JsonReader reader = new JsonReader(new StringReader(json)); reader.beginArray(); assertEquals(-0.0, reader.nextDouble()); @@ -190,19 +199,98 @@ public final class JsonReaderTest extends TestCase { assertEquals(2.2250738585072014E-308, reader.nextDouble()); assertEquals(3.141592653589793, reader.nextDouble()); assertEquals(2.718281828459045, reader.nextDouble()); + assertEquals(1,0, reader.nextDouble()); + assertEquals(11.0, reader.nextDouble()); + assertTrue(Double.isNaN(reader.nextDouble())); + assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble()); + assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } - public void testNonFiniteDoubles() throws IOException { - String json = "[NaN]"; + public void testLenientDoubles() throws IOException { + String json = "[" + + "011.0," + + "NaN," + + "NAN," + + "Infinity," + + "INFINITY," + + "-Infinity" + + "]"; JsonReader reader = new JsonReader(new StringReader(json)); + reader.setLenient(true); reader.beginArray(); + assertEquals(11.0, reader.nextDouble()); + assertTrue(Double.isNaN(reader.nextDouble())); + try { + reader.nextDouble(); + fail(); + } catch (NumberFormatException expected) { + } + assertEquals("NAN", reader.nextString()); + assertEquals(Double.POSITIVE_INFINITY, reader.nextDouble()); try { reader.nextDouble(); fail(); } catch (NumberFormatException expected) { } + assertEquals("INFINITY", reader.nextString()); + assertEquals(Double.NEGATIVE_INFINITY, reader.nextDouble()); + reader.endArray(); + assertEquals(JsonToken.END_DOCUMENT, reader.peek()); + } + + public void testBufferBoundary() throws IOException { + char[] pad = new char[READER_BUFFER_SIZE - 8]; + Arrays.fill(pad, '5'); + String json = "[\"" + new String(pad) + "\",33333]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); + assertEquals(JsonToken.STRING, reader.peek()); + assertEquals(new String(pad), reader.nextString()); + assertEquals(JsonToken.NUMBER, reader.peek()); + assertEquals(33333, reader.nextInt()); + } + + public void testTruncatedBufferBoundary() throws IOException { + char[] pad = new char[READER_BUFFER_SIZE - 8]; + Arrays.fill(pad, '5'); + String json = "[\"" + new String(pad) + "\",33333"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.setLenient(true); + reader.beginArray(); + assertEquals(JsonToken.STRING, reader.peek()); + assertEquals(new String(pad), reader.nextString()); + assertEquals(JsonToken.NUMBER, reader.peek()); + assertEquals(33333, reader.nextInt()); + try { + reader.endArray(); + fail(); + } catch (IOException e) { + } + } + + public void testLongestSupportedNumericLiterals() throws IOException { + testLongNumericLiterals(READER_BUFFER_SIZE - 1, JsonToken.NUMBER); + } + + public void testLongerNumericLiterals() throws IOException { + testLongNumericLiterals(READER_BUFFER_SIZE, JsonToken.STRING); + } + + private void testLongNumericLiterals(int length, JsonToken expectedToken) throws IOException { + char[] longNumber = new char[length]; + Arrays.fill(longNumber, '9'); + longNumber[0] = '1'; + longNumber[1] = '.'; + + String json = "[" + new String(longNumber) + "]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.setLenient(true); + reader.beginArray(); + assertEquals(expectedToken, reader.peek()); + assertEquals(2.0d, reader.nextDouble()); + reader.endArray(); } public void testLongs() throws IOException { @@ -210,7 +298,13 @@ public final class JsonReaderTest extends TestCase { + "1,1,1," + "-1,-1,-1," + "-9223372036854775808," - + "9223372036854775807]"; + + "9223372036854775807," + + "5.0," + + "1.0e2," + + "\"011\"," + + "\"5.0\"," + + "\"1.0e2\"" + + "]"; JsonReader reader = new JsonReader(new StringReader(json)); reader.beginArray(); assertEquals(0L, reader.nextLong()); @@ -234,6 +328,11 @@ public final class JsonReaderTest extends TestCase { } catch (NumberFormatException expected) { } assertEquals(Long.MAX_VALUE, reader.nextLong()); + assertEquals(5, reader.nextLong()); + assertEquals(100, reader.nextLong()); + assertEquals(11, reader.nextLong()); + assertEquals(5, reader.nextLong()); + assertEquals(100, reader.nextLong()); reader.endArray(); assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } @@ -250,28 +349,60 @@ public final class JsonReaderTest extends TestCase { reader.endArray(); } - public void testNumberWithOctalPrefix() throws IOException { - String json = "[01]"; + public void testMatchingValidNumbers() throws IOException { + String json = "[-1,99,-0,0,0e1,0e+1,0e-1,0E1,0E+1,0E-1,0.0,1.0,-1.0,1.0e0,1.0e+1,1.0e-1]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); + for (int i = 0; i < 16; i++) { + assertEquals(JsonToken.NUMBER, reader.peek()); + reader.nextDouble(); + } + reader.endArray(); + } + + public void testRecognizingInvalidNumbers() throws IOException { + String json = "[-00,00,001,+1,1f,0x,0xf,0x0,0f1,0ee1,1..0,1e0.1,1.-01,1.+1,1.0x,1.0+]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.setLenient(true); + reader.beginArray(); + for (int i = 0; i < 16; i++) { + assertEquals(JsonToken.STRING, reader.peek()); + reader.nextString(); + } + reader.endArray(); + } + + public void testNonFiniteDouble() throws IOException { + String json = "[NaN]"; JsonReader reader = new JsonReader(new StringReader(json)); reader.beginArray(); try { - reader.nextInt(); + reader.nextDouble(); fail(); - } catch (NumberFormatException expected) { + } catch (IOException expected) { } + } + + public void testNumberWithHexPrefix() throws IOException { + String json = "[0x11]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); try { reader.nextLong(); fail(); - } catch (NumberFormatException expected) { + } catch (IOException expected) { } + } + + public void testNumberWithOctalPrefix() throws IOException { + String json = "[01]"; + JsonReader reader = new JsonReader(new StringReader(json)); + reader.beginArray(); try { - reader.nextDouble(); + reader.nextInt(); fail(); - } catch (NumberFormatException expected) { + } catch (IOException expected) { } - assertEquals("01", reader.nextString()); - reader.endArray(); - assertEquals(JsonToken.END_DOCUMENT, reader.peek()); } public void testBooleans() throws IOException { |