about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGary Linscott <glinscott@gmail.com>2013-07-05 19:01:57 -0400
committerGary Linscott <glinscott@gmail.com>2013-07-05 19:40:01 -0400
commit37494d39d38be33a589a1f46dae38fe2ceb9d94f (patch)
treed77211e7042fbf860b3cc7a461b76dd81590d980
parent58eb70a5e2ce6602e5685f5cc18ab2fe0c327020 (diff)
downloadrust-37494d39d38be33a589a1f46dae38fe2ceb9d94f.tar.gz
rust-37494d39d38be33a589a1f46dae38fe2ceb9d94f.zip
Switch json parsing to read_chars for performance
Avoids the overhead of read_char for every character.

Benchmark reading example.json 10 times from
https://code.google.com/p/rapidjson/wiki/Performance

Before: 2.55s
After:  0.16s

Regression testing is already done by isrustfastyet.
-rw-r--r--src/libextra/json.rs35
1 files changed, 28 insertions, 7 deletions
diff --git a/src/libextra/json.rs b/src/libextra/json.rs
index 71d99479693..5b9cc338b37 100644
--- a/src/libextra/json.rs
+++ b/src/libextra/json.rs
@@ -481,9 +481,13 @@ pub fn to_pretty_str(json: &Json) -> ~str {
     io::with_str_writer(|wr| to_pretty_writer(wr, json))
 }
 
+static BUF_SIZE : uint = 64000;
+
 #[allow(missing_doc)]
 pub struct Parser {
     priv rdr: @io::Reader,
+    priv buf: ~[char],
+    priv buf_idx: uint,
     priv ch: char,
     priv line: uint,
     priv col: uint,
@@ -491,12 +495,16 @@ pub struct Parser {
 
 /// Decode a json value from an io::reader
 pub fn Parser(rdr: @io::Reader) -> Parser {
-    Parser {
+    let mut p = Parser {
         rdr: rdr,
-        ch: rdr.read_char(),
+        buf: rdr.read_chars(BUF_SIZE),
+        buf_idx: 0,
+        ch: 0 as char,
         line: 1,
-        col: 1,
-    }
+        col: 0,
+    };
+    p.bump();
+    p
 }
 
 impl Parser {
@@ -521,13 +529,26 @@ impl Parser {
     fn eof(&self) -> bool { self.ch == -1 as char }
 
     fn bump(&mut self) {
-        self.ch = self.rdr.read_char();
+        if self.eof() {
+            return;
+        }
+
+        self.col += 1u;
+
+        if self.buf_idx >= self.buf.len() {
+            self.buf = self.rdr.read_chars(BUF_SIZE);
+            if self.buf.len() == 0 {
+                self.ch = -1 as char;
+                return;
+            }
+            self.buf_idx = 0;
+        }
+        self.ch = self.buf[self.buf_idx];
+        self.buf_idx += 1;
 
         if self.ch == '\n' {
             self.line += 1u;
             self.col = 1u;
-        } else {
-            self.col += 1u;
         }
     }