[IronPython] Generator Performance (IronPython vs. CPython(

Dino Viehland dinov at exchange.microsoft.com
Fri Mar 17 17:38:52 CET 2006


The good news this is basically the same issue.  The better news is I've got a fix that gets us performance that's pretty much equal to CPython that will be in Beta 5 for both this and the other generator case.

Thanks for reporting these.  If you (or anyone else) has other issues they'd like to point out now's a great time, keep them coming!


Do you want to help develop Dynamic languages on CLR? (http://members.microsoft.com/careers/search/details.aspx?JobID=6D4754DE-11F0-45DF-8B78-DC1B43134038)

-----Original Message-----
From: users-bounces at lists.ironpython.com [mailto:users-bounces at lists.ironpython.com] On Behalf Of Anthony Tarlano
Sent: Thursday, March 16, 2006 11:45 PM
To: Discussion of IronPython
Subject: Re: [IronPython] Generator Performance (IronPython vs. CPython(

Dino,

Here is another performance example to provide more "food for thought".

This is the second example from the article. In this example a
comparison between a for loop and another generator based thread
scheduler performing the same operations is made.

Here is the code:

# overhead.py

import time

TIMES = 100000

threads = list()

def stringops():
    for n in xrange(TIMES):
        s = "Mary had a little lamb"
        s = s.upper()
        s = "Mary had a little lamb"
        s = s.lower()
        s = "Mary had a little lamb"
        s = s.replace('a','A')

def scheduler():
    for n in xrange(TIMES):
        for thread in threads: thread.next()

def upper():
    while 1:
        s = "Mary had a little lamb"
        s = s.upper()
        yield None

def lower():
    while 1:
        s = "Mary had a little lamb"
        s = s.lower()
        yield None

def replace():
    while 1:
        s = "Mary had a little lamb"
        s = s.replace('a','A')
        yield None

if __name__=='__main__':
    start = time.clock()
    stringops()
    looptime = time.clock()-start
    print "LOOP TIME:", looptime

    threads.append(upper())
    threads.append(lower())
    threads.append(replace())
    start = time.clock()
    scheduler()
    threadtime = time.clock()-start
    print "THREAD TIME:", threadtime


And here are the pitiful results for IronPython vs CPython:

sh-2.04$ python overhead.py
LOOP TIME: 0.326167711259
THREAD TIME: 0.548508818858

sh-2.04$ IronPythonConsole overhead.py
LOOP TIME: 0.734375
THREAD TIME: 1.046875

Anthony

On 3/16/06, Dino Viehland <dinov at exchange.microsoft.com> wrote:
> Thanks for the report of the perf issue.
>
> We are actually actively working on improving the perf of IronPython for the next release so I've gone ahead and filed a bug to make sure we look into this issue.  Hopefully we'll have something more concrete to let you know about this scenario soon, but unfortunately it's not one of the issues we've fixed so far.
>
>
>
> Do you want to help develop Dynamic languages on CLR? (http://members.microsoft.com/careers/search/details.aspx?JobID=6D4754DE-11F0-45DF-8B78-DC1B43134038)
> -----Original Message-----
> From: users-bounces at lists.ironpython.com [mailto:users-bounces at lists.ironpython.com] On Behalf Of Anthony Tarlano
> Sent: Thursday, March 16, 2006 1:24 PM
> To: Discussion of IronPython
> Subject: [IronPython] Generator Performance (IronPython vs. CPython(
>
> Hi,
>
> I investigating the use of  lightweight threads, so I was reading
> "Charming Python #b7: Implementing weightless threads with Python
> generators. by David Mertz, Ph.D."
>
> The first example microthreads.py is about the simplest weightless
> thread scheduler one could choose. Here is the code:
>
> -------------------------------------------------------------------------------------------------------------------
> # microthreads.py
>
> import sys, time
>
> threads = []
> TOTALSWITCHES = 10**6
> NUMTHREADS    = 10**5
>
> def null_factory():
>     def empty():
>         while 1: yield None
>     return empty()
>
> def quitter():
>     for n in xrange(TOTALSWITCHES/NUMTHREADS):
>         yield None
>
> def scheduler():
>     global threads
>     try:
>         while 1:
>             for thread in threads: thread.next()
>     except StopIteration:
>         pass
>
> if __name__ == "__main__":
>     for i in range(NUMTHREADS):
>         threads.append(null_factory())
>     threads.append(quitter())
>     starttime = time.clock()
>     scheduler()
>     print "TOTAL TIME:    ", time.clock()-starttime
>     print "TOTAL SWITCHES:", TOTALSWITCHES
>     print "TOTAL THREADS: ", NUMTHREADS
>
> -------------------------------------------------------------------------------------------------------------------
>
> After running the example on CPython the following results are printed:
>
> sh-2.04$ python microthreads.py
> TOTAL TIME:     0.718205526121
> TOTAL SWITCHES: 1000000
> TOTAL THREADS:  100000
>
> After running the example on IronPython the following results are printed:
>
> sh-2.04$ IronPythonConsole microthreads.py
> TOTAL TIME:     1.49999237061
> TOTAL SWITCHES: 1000000
> TOTAL THREADS:  100000
>
> This shows that IronPython took 0.781786844489 more then CPython to do
> the same switching between generators in this example. I was quites
> surprise to see this since that's more then double the time of
> CPython.
>
> Thus, the question is whether this performance result is acceptable to
> the IronPython team.
>
> Thanks,
>
> Anthony
> _______________________________________________
> users mailing list
> users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
> _______________________________________________
> users mailing list
> users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>
_______________________________________________
users mailing list
users at lists.ironpython.com
http://lists.ironpython.com/listinfo.cgi/users-ironpython.com



More information about the Ironpython-users mailing list