Skip to content

Commit

Permalink
Add benchmark for an object with a list.
Browse files Browse the repository at this point in the history
Current timing on cpython2.7:

.....................
__main__: toExternalObject: Mean +- std dev: 405 us +- 9 us
.....................
__main__: fromExternalObject: Mean +- std dev: 1.37 ms +- 0.03 ms
  • Loading branch information
jamadden committed Jul 13, 2018
1 parent 0c3b14d commit 9dc6ec9
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/nti/externalization/__base_interfaces.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ cdef class LocatedExternalDict(dict):
cdef public __name__
cdef public __parent__
cdef public __acl__
cdef readonly mimeType
cdef public mimeType

cdef update_from_other(self, other)

Expand Down
24 changes: 16 additions & 8 deletions src/nti/externalization/tests/benchmarks/bm_simple_iface.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,20 @@
from __future__ import division
from __future__ import print_function


import sys

import perf
from perf import perf_counter

from zope.configuration import xmlconfig

from nti.externalization.representation import JsonRepresenter
from nti.externalization.externalization import toExternalObject
from nti.externalization.interfaces import StandardExternalFields
from nti.externalization.internalization import default_externalized_object_factory_finder
from nti.externalization.internalization import update_from_external_object

import nti.externalization.tests.benchmarks
from nti.externalization.tests.benchmarks.objects import DerivedWithOneTextField

Expand All @@ -42,21 +45,26 @@ def find_factory_time_func(loops, ext):

def update_from_external_object_time_func(loops, ext):
factory = default_externalized_object_factory_finder(ext)
# Updating *may* modify the object in place, so we need to
# make deep copies of it.
rep = JsonRepresenter()
json = rep.dump(ext)
exts = [rep.load(json) for x in range(loops * INNER_LOOPS)]
begin = perf_counter()
for _ in range(loops):
for _ in range(INNER_LOOPS):
obj = factory()
update_from_external_object(obj, ext)
for x in exts:
obj = factory()
update_from_external_object(obj, x)
end = perf_counter()
return end - begin


def profile():
def profile(loops=1000, obj=None):
from cProfile import Profile
import pstats

obj = DerivedWithOneTextField()
obj.text = u'This is some text'
if obj is None:
obj = DerivedWithOneTextField()
obj.text = u'This is some text'

ext = toExternalObject(obj)

Expand All @@ -68,7 +76,7 @@ def profile():

prof = Profile()
prof.enable()
func(1000, arg)
func(loops, arg)
prof.disable()
stats = pstats.Stats(prof)
stats.strip_dirs()
Expand Down
67 changes: 67 additions & 0 deletions src/nti/externalization/tests/benchmarks/bm_simple_iface_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
"""
Extends bm_simple_iface to add a list.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import sys

import perf


from zope.configuration import xmlconfig

from nti.externalization.externalization import toExternalObject
from nti.externalization.interfaces import StandardExternalFields

import nti.externalization.tests.benchmarks

from nti.externalization.tests.benchmarks.objects import DerivedWithOneTextField
from nti.externalization.tests.benchmarks.objects import HasListOfDerived

from nti.externalization.tests.benchmarks.bm_simple_iface import (
INNER_LOOPS,
to_external_object_time_func,
update_from_external_object_time_func,
profile
)

logger = __import__('logging').getLogger(__name__)


def main(runner=None):

xmlconfig.file('configure.zcml', nti.externalization.tests.benchmarks)

obj = HasListOfDerived()
obj.the_objects = [DerivedWithOneTextField(text=u"This is some text " + str(i))
for i in range(10)]


if '--profile' in sys.argv:
profile(100, obj)
return

mt = getattr(obj, 'mimeType')
assert mt == 'application/vnd.nextthought.benchmarks.haslistofderived', mt

runner = runner or perf.Runner()
runner.bench_time_func(__name__ + ": toExternalObject",
to_external_object_time_func,
obj,
inner_loops=INNER_LOOPS)

ext = toExternalObject(obj)
assert StandardExternalFields.MIMETYPE in ext


runner.bench_time_func(__name__ + ": fromExternalObject",
update_from_external_object_time_func,
ext,
inner_loops=INNER_LOOPS)

if __name__ == '__main__':
main()
11 changes: 11 additions & 0 deletions src/nti/externalization/tests/benchmarks/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
from zope.interface import Interface
from zope.interface import taggedValue

from zope.schema import List
from zope.schema import Object

from nti.schema.field import TextLine

class ISimplestPossibleObject(Interface):
Expand All @@ -29,3 +32,11 @@ class IDerivedWithOneTextField(IRootInterface):

taggedValue('__external_class_name__',
'DerivedWithOneTextField')


class IHasListOfDerived(IRootInterface):

the_objects = List(Object(IDerivedWithOneTextField))

taggedValue('__external_class_name__',
'HasListOfDerived')
7 changes: 7 additions & 0 deletions src/nti/externalization/tests/benchmarks/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,10 @@ class SimplestPossibleObject(ExternalizableInstanceDict):
@interface.implementer(interfaces.IDerivedWithOneTextField)
class DerivedWithOneTextField(object):
createDirectFieldProperties(interfaces.IDerivedWithOneTextField)

def __init__(self, text=u''):
self.text = text

@interface.implementer(interfaces.IHasListOfDerived)
class HasListOfDerived(object):
createDirectFieldProperties(interfaces.IHasListOfDerived)

0 comments on commit 9dc6ec9

Please sign in to comment.