[Python-Dev] impact of cycle gc...

Neil Schemenauer nascheme@enme.ucalgary.ca
Thu, 8 Jun 2000 19:29:00 -0600


Just a few points and then I will get off python-dev. :)

First of all, I don't think it is very meaningful to use leaking
applications to do timing comparisons.  The collector has be
quite careful when freeing structures containing reference
cycles.  However, using something other than pystone is
definitely a good idea.

Here the pybench results for the latest patch:

PYBENCH 0.6

Benchmark: b_nogc (rounds=4, warp=30)

Tests:                              per run    per oper.  diff *
------------------------------------------------------------------------
          BuiltinFunctionCalls:     286.25 ms    3.37 us   -4.22%
           BuiltinMethodLookup:     367.50 ms    1.05 us   -4.55%
                 ConcatStrings:     368.37 ms    3.68 us  +42.50%
               CreateInstances:     477.87 ms   17.07 us   -4.45%
       CreateStringsWithConcat:     322.12 ms    2.42 us  +10.27%
                  DictCreation:     382.75 ms    3.83 us   +1.29%
                      ForLoops:     536.88 ms   80.73 us   +0.99%
                    IfThenElse:     432.75 ms    0.96 us   -3.21%
                   ListSlicing:     236.87 ms  104.12 us  +11.73%
                NestedForLoops:     320.00 ms    1.28 us   +0.16%
          NormalClassAttribute:     386.50 ms    0.97 us   +0.00%
           PythonFunctionCalls:     477.87 ms    4.34 us   -3.51%
             PythonMethodCalls:     379.12 ms    7.59 us  -12.67%
                     Recursion:     280.75 ms   33.70 us   -0.88%
                  SecondImport:     206.62 ms   12.41 us   -5.76%
           SecondPackageImport:     216.75 ms   13.02 us   -4.41%
         SecondSubmoduleImport:     279.25 ms   16.77 us   -2.57%
       SimpleComplexArithmetic:     351.00 ms    2.39 us   +0.72%
        SimpleDictManipulation:     320.75 ms    1.60 us   -2.99%
         SimpleFloatArithmetic:     361.50 ms    0.99 us  -20.37%
      SimpleIntFloatArithmetic:     336.00 ms    0.76 us   +0.04%
       SimpleIntegerArithmetic:     328.38 ms    0.75 us   -0.76%
        SimpleListManipulation:     312.88 ms    1.74 us   -1.61%
          SimpleLongArithmetic:     308.75 ms    2.81 us   +9.88%
                    SmallLists:     470.13 ms    2.77 us   -5.05%
                   SmallTuples:     374.62 ms    2.34 us  -15.74%
         SpecialClassAttribute:     384.00 ms    0.96 us   -1.88%
      SpecialInstanceAttribute:     446.38 ms    1.12 us   -2.75%
                 StringSlicing:     315.50 ms    2.70 us  +16.58%
                     TryExcept:     585.37 ms    0.59 us   -1.70%
                TryRaiseExcept:     312.75 ms   31.28 us   -5.30%
                  TupleSlicing:     299.38 ms    4.39 us  +12.18%
------------------------------------------------------------------------
            Average round time:   13615.00 ms              -1.13%

My AMD-K6-II processor is a pretty quirky beast so I don't think
you can conclude too much for those results.  Here are the
median timings from running Jeremy's compiler on its own source:

	$ time python compile.py `find . -name '*.py'`

Python 1.6 without GC:

	real    0m16.926s
	user    0m16.810s
	sys     0m0.110s

Python 1.6 with GC:

	real    0m21.593s
	user    0m21.470s
	sys     0m0.080s

Python 1.6 with GC, collection disabled (ie. gc.set_threshold(0)):

	real    0m18.441s
	user    0m18.220s
	sys     0m0.220s

We can tune the collection frequency all we want but we won't do
any better than the last numbers.  Those numbers reflect the cost
of keeping track of the objects and the increase in object size.

On a related note, I would like to cleanup the PyGC_{NEW,
VAR_NEW} macros but I can't figure out a way to transform this
code into a macro:

    op = PyObject_MALLOC(sizeof(PyGCInfo) + _PyObject_SIZE(tp));
    if (op)
        op = PyGC_OBJ((PyGCInfo *)op);

If C's || operator was like the Python or I could do something
like:

    #define PyGC_OBJ_SAFE(g) ((PyGCInfo *)(((g) || -1) + 1))

Any ideas?  Using an inline function in the header file would
be nice but of course it is not portable.  GCC has statement
expressions but again they are not portable.

    Neil