Skip to content

Commit f5e50f1

Browse files
committed
Keep track of the size of things that are being allocated on the heap.
1 parent a84a2dc commit f5e50f1

File tree

1 file changed

+46
-4
lines changed

1 file changed

+46
-4
lines changed

src/parser.rs

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ struct Parser<'a> {
5353

5454
// Lenght of the source
5555
length: usize,
56+
57+
// Current depth. Objects and arrays increment depth when they
58+
// start being parsed, decrement when they stop being parsed.
59+
depth: usize,
60+
61+
// Size stack is an auxiliary array holding expected heap allocation
62+
// sizes on each level of depth, up to 16. When an array of objects,
63+
// the size stack will be set to the length of the first object parsed,
64+
// so that each consecutive object can do a guess for a precise heap
65+
// allocation for it's entires, reducing the amount of reallocations
66+
// for large files conisderably!
67+
size_stack: [usize; 16],
5668
}
5769

5870

@@ -411,6 +423,8 @@ impl<'a> Parser<'a> {
411423
byte_ptr: source.as_ptr(),
412424
index: 0,
413425
length: source.len(),
426+
depth: 0,
427+
size_stack: [3; 16],
414428
}
415429
}
416430

@@ -707,16 +721,34 @@ impl<'a> Parser<'a> {
707721
Ok(num * exponent_to_power(e * sign))
708722
}
709723

724+
#[inline(always)]
725+
fn set_alloc_size(&mut self, size: usize) {
726+
if self.depth < 16 {
727+
self.size_stack[self.depth] = size;
728+
}
729+
}
730+
731+
#[inline(always)]
732+
fn get_alloc_size(&mut self) -> usize {
733+
if self.depth < 16 {
734+
self.size_stack[self.depth]
735+
} else {
736+
3
737+
}
738+
}
739+
710740
// Given how compilcated reading numbers and strings is, reading objects
711741
// is actually pretty simple.
712742
fn read_object(&mut self) -> Result<Object> {
713-
let mut object = Object::with_capacity(3);
714-
715743
let key = expect!{ self,
716-
b'}' => return Ok(object),
744+
b'}' => return Ok(Object::new()),
717745
b'\"' => expect_string!(self)
718746
};
719747

748+
self.depth += 1;
749+
750+
let mut object = Object::with_capacity(self.get_alloc_size());
751+
720752
expect!(self, b':');
721753

722754
object.insert(key, expect_value!(self));
@@ -735,14 +767,20 @@ impl<'a> Parser<'a> {
735767
object.insert(key, expect_value!(self));
736768
}
737769

770+
self.depth -= 1;
771+
772+
self.set_alloc_size(object.len());
773+
738774
Ok(object)
739775
}
740776

741777
// And reading arrays is simpler still!
742778
fn read_array(&mut self) -> Result<Vec<JsonValue>> {
743779
let first = expect_value!{ self, b']' => return Ok(Vec::new()) };
744780

745-
let mut array = Vec::with_capacity(2);
781+
self.depth += 1;
782+
783+
let mut array = Vec::with_capacity(self.get_alloc_size());
746784
array.push(first);
747785

748786
loop {
@@ -754,6 +792,10 @@ impl<'a> Parser<'a> {
754792
};
755793
}
756794

795+
self.depth -= 1;
796+
797+
self.set_alloc_size(array.len());
798+
757799
Ok(array)
758800
}
759801

0 commit comments

Comments
 (0)