Author: Wim Lavrijsen <wlavrij...@lbl.gov> Branch: reflex-support Changeset: r56419:4d1ca3adc5d3 Date: 2012-07-23 20:28 -0700 http://bitbucket.org/pypy/pypy/changeset/4d1ca3adc5d3/
Log: optimized I/O for CINT backend diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py --- a/pypy/module/cppyy/capi/cint_capi.py +++ b/pypy/module/cppyy/capi/cint_capi.py @@ -140,39 +140,58 @@ # return control back to the original, unpythonized overload return tree_class.get_overload("Branch").call(w_self, args_w) +def activate_branch(space, w_branch): + w_branches = space.call_method(w_branch, "GetListOfBranches") + for i in range(space.int_w(space.call_method(w_branches, "GetEntriesFast"))): + w_b = space.call_method(w_branches, "At", space.wrap(i)) + activate_branch(space, w_b) + space.call_method(w_branch, "SetStatus", space.wrap(1)) + space.call_method(w_branch, "ResetReadEntry") + +@unwrap_spec(args_w='args_w') +def ttree_getattr(space, w_self, args_w): + """Specialized __getattr__ for TTree's that allows switching on/off the + reading of individual branchs.""" + + from pypy.module.cppyy import interp_cppyy + tree = space.interp_w(interp_cppyy.W_CPPInstance, w_self) + + # setup branch as a data member and enable it for reading + space = tree.space # holds the class cache in State + w_branch = space.call_method(w_self, "GetBranch", args_w[0]) + w_klassname = space.call_method(w_branch, "GetClassName") + klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) + w_obj = klass.construct() + #space.call_method(w_branch, "SetStatus", space.wrap(1)) + activate_branch(space, w_branch) + space.call_method(w_branch, "SetObject", w_obj) + space.call_method(w_branch, "GetEntry", space.wrap(0)) + space.setattr(w_self, args_w[0], w_obj) + return w_obj + class W_TTreeIter(Wrappable): def __init__(self, space, w_tree): - self.current = 0 + + from pypy.module.cppyy import interp_cppyy + tree = space.interp_w(interp_cppyy.W_CPPInstance, w_tree) + self.tree = tree.get_cppthis(tree.cppclass) self.w_tree = w_tree - from pypy.module.cppyy import interp_cppyy - tree = space.interp_w(interp_cppyy.W_CPPInstance, self.w_tree) - self.tree = tree.get_cppthis(tree.cppclass) + self.getentry = tree.cppclass.get_overload("GetEntry").functions[0] + self.current = 0 + self.maxentry = space.int_w(space.call_method(w_tree, "GetEntriesFast")) - # setup data members if this is the first iteration time - try: - space.getattr(w_tree, space.wrap("_pythonized")) - except OperationError: - self.space = space = tree.space # holds the class cache in State - w_branches = space.call_method(w_tree, "GetListOfBranches") - for i in range(space.int_w(space.call_method(w_branches, "GetEntriesFast"))): - w_branch = space.call_method(w_branches, "At", space.wrap(i)) - w_name = space.call_method(w_branch, "GetName") - w_klassname = space.call_method(w_branch, "GetClassName") - klass = interp_cppyy.scope_byname(space, space.str_w(w_klassname)) - w_obj = klass.construct() - space.call_method(w_branch, "SetObject", w_obj) - # cache the object and define this tree pythonized - space.setattr(w_tree, w_name, w_obj) - space.setattr(w_tree, space.wrap("_pythonized"), space.w_True) + space = self.space = tree.space # holds the class cache in State + space.call_method(w_tree, "SetBranchStatus", space.wrap("*"), space.wrap(0)) def iter_w(self): return self.space.wrap(self) def next_w(self): - w_bytes_read = self.getentry.call(self.tree, [self.space.wrap(self.current)]) - if not self.space.is_true(w_bytes_read): + if self.current == self.maxentry: raise OperationError(self.space.w_StopIteration, self.space.w_None) + # TODO: check bytes read? + self.getentry.call(self.tree, [self.space.wrap(self.current)]) self.current += 1 return self.w_tree @@ -194,8 +213,9 @@ "NOT_RPYTHON" ### TTree - _pythonizations['ttree_Branch'] = space.wrap(interp2app(ttree_Branch)) - _pythonizations['ttree_iter'] = space.wrap(interp2app(ttree_iter)) + _pythonizations['ttree_Branch'] = space.wrap(interp2app(ttree_Branch)) + _pythonizations['ttree_iter'] = space.wrap(interp2app(ttree_iter)) + _pythonizations['ttree_getattr'] = space.wrap(interp2app(ttree_getattr)) # callback coming in when app-level bound classes have been created def pythonize(space, name, w_pycppclass): @@ -209,6 +229,7 @@ space.getattr(w_pycppclass, space.wrap("Branch"))) space.setattr(w_pycppclass, space.wrap("Branch"), _pythonizations["ttree_Branch"]) space.setattr(w_pycppclass, space.wrap("__iter__"), _pythonizations["ttree_iter"]) + space.setattr(w_pycppclass, space.wrap("__getattr__"), _pythonizations["ttree_getattr"]) elif name[0:8] == "TVectorT": # TVectorT<> template space.setattr(w_pycppclass, space.wrap("__len__"), diff --git a/pypy/module/cppyy/test/test_cint.py b/pypy/module/cppyy/test/test_cint.py --- a/pypy/module/cppyy/test/test_cint.py +++ b/pypy/module/cppyy/test/test_cint.py @@ -132,7 +132,7 @@ import cppyy return cppyy.load_reflection_info(%r)""" % (iotypes_dct,)) - def test01_write_stdvector( self ): + def test01_write_stdvector(self): """Test writing of a single branched TTree with an std::vector<double>""" from cppyy import gbl # bootstraps, only needed for tests @@ -168,6 +168,7 @@ i = 0 for event in mytree: + assert len(event.mydata) == self.M for entry in event.mydata: assert i == int(entry) i += 1 @@ -209,16 +210,80 @@ f = TFile(self.fname) mytree = f.Get(self.tname) + j = 1 for event in mytree: i = 0 + assert len(event.data.get_floats()) == j*self.M for entry in event.data.get_floats(): assert i == int(entry) i += 1 + k = 1 + assert len(event.data.get_tuples()) == j for mytuple in event.data.get_tuples(): i = 0 + assert len(mytuple) == k*self.M for entry in mytuple: assert i == int(entry) i += 1 + k += 1 + j += 1 + assert j-1 == self.N # f.Close() + + def test05_branch_activation(self): + """Test of automatic branch activation""" + + from cppyy import gbl # bootstraps, only needed for tests + from cppyy.gbl import TFile, TTree + from cppyy.gbl.std import vector + + L = 5 + + # writing + f = TFile(self.fname, "RECREATE") + mytree = TTree(self.tname, self.title) + mytree._python_owns = False + + for i in range(L): + v = vector("double")() + mytree.Branch("mydata_%d"%i, v.__class__.__name__, v) + mytree.__dict__["v_%d"%i] = v + + for i in range(self.N): + for k in range(L): + v = mytree.__dict__["v_%d"%k] + for j in range(self.M): + mytree.__dict__["v_%d"%k].push_back(i*self.M+j*L+k) + mytree.Fill() + for k in range(L): + v = mytree.__dict__["v_%d"%k] + v.clear() + f.Write() + f.Close() + + del mytree, f + import gc + gc.collect() + + # reading + f = TFile(self.fname) + mytree = f.Get(self.tname) + + # force (initial) disabling of all branches + mytree.SetBranchStatus("*",0); + + i = 0 + for event in mytree: + for k in range(L): + j = 0 + data = getattr(mytree, "mydata_%d"%k) + assert len(data) == self.M + for entry in data: + assert entry == i*self.M+j*L+k + j += 1 + assert j == self.M + i += 1 + assert i == self.N + _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit