Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trio execution time without IO operations

I'm doing examples to understand how it works python asynchronously. I read the Trio documentation and I thought that only one task can be executed in the loop every time and in every checkpoint the scheduler decide which task will be executed.

I did an example to test it, in the trio example I don't use any checkpoint in the child that I spawn in the nursery but this example is two times faster than the synchronous version.

Async example:

import time
import trio

results = []

async def sum_numbers(first, last):
    result = 0
    for i in range(first, last):
        result += i
    results.append(result)

async def main():
    start_time = time.time()
    async with trio.open_nursery() as nursery:
        nursery.start_soon(sum_numbers, 0, 50000000)
        nursery.start_soon(sum_numbers, 50000000, 100000000)

    print(sum(results))
    print("Total time:", time.time() - start_time)

trio.run(main)

Result:

4999999950000000
Total time: 4.150018930435181

Sync example:

import time

start_time = time.time()
result = 0
for i in range(0, 100000000):
    result += i

print(result)
print("Total time:", time.time() - start_time)

Result:

4999999950000000
Total time: 8.002650737762451

Why? I expected the same time because I'm not using any checkpoint in my code. Seems like there are 2 threads running at the same time or Is there any I/O in the child function?

like image 993
Pentux Avatar asked Aug 15 '18 09:08

Pentux


Video Answer


1 Answers

After a small talk with the Trio author, Nathaniel J. Smith he found the problem in my code. The problem is in the synchronous example. I'm using global variables instead of local variables like in the asynchronous example.

Nathaniel: "In CPython, accessing locals is more optimized than accessing globals. (the compiler converts locals into offsets-in-an-array, while globals are always looked up by name in a dict)"

Then I put all the code from the sync example in a function and the time is similar of async, even faster. Now make sense, this was the theory and now is proved, it's clear for me. Thank you!

Sync example in a function:

import time

start_time = time.time()


def sum_range():
    result = 0
    for i in range(0, 100000000):
        result += i

    return result

print(sum_range())
print("Total time:", time.time() - start_time)

Result:

4999999950000000
Total time: 3.596266984939575
like image 58
Pentux Avatar answered Oct 26 '22 08:10

Pentux