#18109: Restructure IntegerListLex code
-------------------------------------+-------------------------------------
       Reporter:  vdelecroix         |        Owner:
           Type:  defect             |       Status:  needs_review
       Priority:  major              |    Milestone:  sage-6.6
      Component:  combinatorics      |   Resolution:
       Keywords:                     |    Merged in:
        Authors:  Jeroen Demeyer     |    Reviewers:
Report Upstream:  N/A                |  Work issues:
         Branch:                     |       Commit:
  u/jdemeyer/ticket/18109            |  9582a7a5248f609a2d2de02497b4b1d36d9dd96e
   Dependencies:  #18181, #18184     |     Stopgaps:
-------------------------------------+-------------------------------------

Comment (by nthiery):

 Replying to [comment:51 jdemeyer]:
 > That's not a fair benchmark, since that's Python, not Cython. The real
 benchmark is this:
 > {{{
 > sage: cython("cdef class A(object): pass")
 > sage: cython("from sage.structure.parent cimport Parent\ncdef class
 B(Parent): pass")
 > sage: timeit("A()", number=10^4, repeat=20)
 > 10000 loops, best of 20: 68.9 ns per loop
 > sage: timeit("B()", number=10^4, repeat=20)
 > 10000 loops, best of 20: 14.5 µs per loop
 > }}}

 Thanks Vincent and Jeroen. For fairness, we should also initialize the
 category. Here it is:
 {{{
 sage: %timeit B()
 The slowest run took 4.13 times longer than the fastest. This could mean
 that an intermediate result is being cached
 100000 loops, best of 3: 13.3 µs per loop
 sage: %timeit B(category=C)
 The slowest run took 7.14 times longer than the fastest. This could mean
 that an intermediate result is being cached
 10000 loops, best of 3: 21.7 µs per loop
 }}}

 Those benchmarks teach us that constructing a `Parent` costs 24 times
 more than a trivial object. Not quite surprising, but it's a
 start. Now what I really had in mind was a benchmark in a real use
 case, to estimate what's the relative overhead in a typical situation.

 Let's take something really trivial:
 {{{
 sage: sage: %timeit IntegerListsLex(n=1, max_length=1).an_element()
 The slowest run took 6.67 times longer than the fastest. This could mean
 that an intermediate result is being cached
 10000 loops, best of 3: 113 µs per loop
 }}}

 Now we start to have some concrete ground to start discussions: what
 we are speaking about is an overhead of 13% in the case of the most
 trivial operation. There probably is some room for improvements in the
 initialization of `IntegerListsLex` objects; but not so much either:
 there is some unavoidable option parsing and initialization work to
 do. Similarly, there may be room for improvement in the initialization
 of a `Parent` (I am surprised that initializing the category is
 costly, since for a Cython parent it does nothing but set an
 attribute). Altogether, the 13% has to be taken with a grain of salt
 at this point.

 For additional insight, I believe we would be need to have some
 typical concrete use case, like the one Vincent has for matrices or
 flat surfaces. And see, then, what's the actual overhead. With that,
 we will be able to take an informed decision; not just out of fear
 that "parents are slow".

 Vincent, could you pickup such a situation and make a benchmark?

 In general I would like to follow this rule of thumb for our
 enumerated sets:

 - On one hand, implement super optimized standalone iterators with
   bare bone API, whenever there is a proven need for them.

 - On the other hand, when modeling an enumerated set, implement it as
   a `Parent`s with nice input parsing and a full fledged API; and
   typically using the above iterators under the hood.

 - Avoid half measures with iterables that are not `Parent`.

 Here the situation is a bit delicate since we are in between the
 shores: the iterator needs some non trivial parsing and internal
 data. Which calls for an intermediate class handling the parsing and
 the data storage; is this class meant to model the enumerated set
 itself or not?


 All that being said, just make your call. I am fine with additional
 complexity when there is a proven and worthwhile need for it. And when
 someone is willing to pay for the maintenance overhead ...

 Cheers,
                               Nicolas

--
Ticket URL: <http://trac.sagemath.org/ticket/18109#comment:52>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sage-trac.
For more options, visit https://groups.google.com/d/optout.

Reply via email to