Skip to content

Commit

Permalink
Extend scoping optimisation coverage to include functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
Robadob committed Mar 28, 2024
1 parent 536f7ca commit cc15d24
Showing 1 changed file with 19 additions and 7 deletions.
26 changes: 19 additions & 7 deletions episodes/optimisation-minimise-python.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,18 +202,18 @@ dis.dis(searchListC)

## Scope

When Python executes your code, it has to find the variables that you're using.
When Python executes your code, it has to find the variables and functions that you're using.

This adds an additional cost to accessing variables in Python, which isn't typically seen in compiled languages.
This adds an additional cost to accessing variables and calling functions in Python, which isn't typically seen in compiled languages.

In particular, it will first check whether the variable has been declared within the current function (local scope), if it can't find it there it will check whether it has been declared in the file (global scope) after which it may even check whether it's from an imported package.
In particular, it will first check whether the variable or functions has been declared within the current function (local scope), if it can't find it there it will check whether it has been declared in the file (global scope) after which it may even check whether it's from an imported package.

Repeated accesses to variables, will repeat these checks.
These are not implicitly cached, therefore repeated accesses to variables and functions, will repeat these checks.

The implication, is that as local scope variables are checked first, they will be faster to access.
The implication, is that as local scope variables and functions are checked first, they will be faster to use.

If you're only accessing a variable once or twice that's nothing to worry about, this is a relatively small cost.
But if a variable is being accessed regularly, such as within a loop, the impact may become visible.
But if a variable or functions is being accessed regularly, such as within a loop, the impact may become visible.

The below example provides a small demonstration of this in practice.

Expand Down Expand Up @@ -242,7 +242,7 @@ print(f"Global Scope: {timeit(test_list_global, number=repeats):.5f}ms")
print(f"Local Scope: {timeit(test_list_local, number=repeats):.5f}ms")
```

This is only a trivial example, but local scope is about 20% faster than global scope!
This is only a trivial example, whereby `N` has been copied to the local scope `N_local`, but local scope is about 20% faster than global scope!

```output
Global Scope: 0.06416ms
Expand All @@ -251,6 +251,18 @@ Local Scope: 0.05391ms

Consider copying highly accessed variables into local scope, you can always copy them back to global scope before you return from a function.

Copying functions to local scope works much the same as variables, e.g.

```py
import numpy as np

def my_function():
uniform_local = np.random.uniform

for i in range(10000):
t = uniform_local()
```

## Built-in Functions Operators

In order to take advantage of offloading computation to the CPython back-end it's necessary to be aware of what functionality is present. Those available without importing packages are considered [built-in](https://docs.python.org/3/library/functions.html) functions.
Expand Down

0 comments on commit cc15d24

Please sign in to comment.