[pypy-commit] pypy json-decoder-maps: simplify fringe handling
cfbolz
pypy.commits at gmail.com
Wed Jun 5 09:49:57 EDT 2019
Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch: json-decoder-maps
Changeset: r96758:5dc3d4fba79a
Date: 2019-06-05 15:27 +0200
http://bitbucket.org/pypy/pypy/changeset/5dc3d4fba79a/
Log: simplify fringe handling
diff --git a/pypy/module/_pypyjson/interp_decoder.py b/pypy/module/_pypyjson/interp_decoder.py
--- a/pypy/module/_pypyjson/interp_decoder.py
+++ b/pypy/module/_pypyjson/interp_decoder.py
@@ -595,7 +595,7 @@
def decode_key(self, i, currmap):
newmap = self._decode_key(i, currmap)
- currmap.observe_transition(newmap)
+ currmap.observe_transition(newmap, self.startmap)
return newmap
def _decode_key(self, i, currmap):
@@ -789,7 +789,7 @@
decoder.pos = position + len(single_nextmap.key_repr)
return single_nextmap
- def observe_transition(self, newmap):
+ def observe_transition(self, newmap, terminator):
""" observe a transition from self to newmap.
This does a few things, including updating the self size estimate with
the knowledge that one object transitioned from self to newmap.
@@ -797,7 +797,7 @@
self.instantiation_count += 1
if isinstance(self, JSONMap) and self.state == MapBase.FRINGE:
if self.is_useful():
- self.mark_useful(self.startmap)
+ self.mark_useful(terminator)
def _make_next_map(self, w_key, key_repr):
return JSONMap(self.space, self, w_key, key_repr)
@@ -852,23 +852,21 @@
self.cleanup_fringe()
self.current_fringe[prelim] = None
+ def remove_from_fringe(self, former_fringe):
+ assert former_fringe.state in (MapBase.USEFUL, MapBase.BLOCKED)
+ del self.current_fringe[former_fringe]
+
def cleanup_fringe(self):
min_fringe = None
min_avg = 10000000000
for f in self.current_fringe:
- if f.state == MapBase.FRINGE:
- avg = f.average_instantiation()
- if avg < min_avg:
- min_avg = avg
- min_fringe = f
- else:
- for f in self.current_fringe.keys():
- if f.state != MapBase.FRINGE:
- del self.current_fringe[f]
- return
+ assert f.state == MapBase.FRINGE
+ avg = f.average_instantiation()
+ if avg < min_avg:
+ min_avg = avg
+ min_fringe = f
assert min_fringe
min_fringe.mark_blocked(self)
- del self.current_fringe[min_fringe]
class JSONMap(MapBase):
@@ -932,8 +930,11 @@
def mark_useful(self, terminator):
# mark self as useful, and also the most commonly instantiated
# children, recursively
+ was_fringe = self.state == MapBase.FRINGE
assert self.state in (MapBase.FRINGE, MapBase.PRELIMINARY)
self.state = MapBase.USEFUL
+ if was_fringe:
+ terminator.remove_from_fringe(self)
maxchild = self.single_nextmap
if self.all_next is not None:
for child in self.all_next.itervalues():
@@ -948,7 +949,10 @@
self.single_nextmap = maxchild
def mark_blocked(self, terminator):
+ was_fringe = self.state == MapBase.FRINGE
self.state = MapBase.BLOCKED
+ if was_fringe:
+ terminator.remove_from_fringe(self)
if self.all_next:
for next in self.all_next.itervalues():
next.mark_blocked(terminator)
diff --git a/pypy/module/_pypyjson/test/test__pypyjson.py b/pypy/module/_pypyjson/test/test__pypyjson.py
--- a/pypy/module/_pypyjson/test/test__pypyjson.py
+++ b/pypy/module/_pypyjson/test/test__pypyjson.py
@@ -150,7 +150,7 @@
assert m2.number_of_leaves == 3
assert m5.number_of_leaves == 1
- def test_cleanup_fringe_simple(self):
+ def test_mark_useful_cleans_fringe(self):
base, m1, m2, m3, m4 = self._make_some_maps()
base.instantiation_count = 6
assert m1.state == MapBase.FRINGE
@@ -161,11 +161,9 @@
assert base.current_fringe == {m1: None}
m1.mark_useful(base)
- assert base.current_fringe == {m1: None, m3: None} # not cleaned up
- base.cleanup_fringe()
assert base.current_fringe == {m3: None}
- def test_cleanup_fringe_block(self):
+ def test_cleanup_fringe(self):
w_a = self.space.newutf8("a", 1)
w_b = self.space.newutf8("b", 1)
w_c = self.space.newutf8("c", 1)
More information about the pypy-commit
mailing list