Skip to content

Optimise searching for placeholders - #1370

Merged
quis merged 3 commits into
mainfrom
optimise-placeholder-extraction
Jun 12, 2026
Merged

Optimise searching for placeholders #1370
quis merged 3 commits into
mainfrom
optimise-placeholder-extraction

Conversation

@quis

@quis quis commented Jun 11, 2026

Copy link
Copy Markdown
Member

If a string doesn’t have an opening parentheses then we can guarantee it doesn’t have any placeholders in it.

We can take advantage of this to skip the expensive regex search.

Benchmark for string with no placeholders

python -m timeit -s "import random; import string; from notifications_utils.field import Field; s = ''.join(random.choices(string.ascii_uppercase + string.digits + string.whitespace, k=1000))" "Field(s).placeholders"

Before

50000 loops, best of 5: 7.68 usec per loop

After

500000 loops, best of 5: 536 nsec per loop

14× faster

Benchmark for same string with one placeholder right at the end

python -m timeit -s "import random; import string; from notifications_utils.field import Field; s = ''.join(random.choices(string.ascii_uppercase + string.digits + string.whitespace, k=1000)) + '((name))'" "Field(s).placeholders"

Before

50000 loops, best of 5: 9.06 usec per loop

After

50000 loops, best of 5: 9.06 usec per loop

No change.

@quis
quis force-pushed the optimise-placeholder-extraction branch 2 times, most recently from 7b86026 to 9acc20c Compare June 11, 2026 11:32
quis added 3 commits June 11, 2026 13:03
Mocking the init method is messy because then the code in the real
`__init__` method doesn’t get run, so properties like `content` don’t
get set.

We can still test the same thing (which arguments the `Field` is
instantiated with) by mocking the whole class. Then any downstream code
which is looking at the field will be dealing with a mock, which returns
something for properties like `content` which don’t exist.
If a string doesn’t have an opening parentheses then we can guarantee
it doesn’t have any placeholders in it.

We can take advantage of this to skip the expensive regex search.

Benchmark for string with no placeholders:
```shell
python -m timeit -s "import random; import string; from notifications_utils.field import Field; s = ''.join(random.choices(string.ascii_uppercase + string.digits + string.whitespace, k=1000))" "Field(s).placeholders"
```

Before
> 50000 loops, best of 5: 7.68 usec per loop

After
> 500000 loops, best of 5: 536 nsec per loop

14× faster

Benchmark for same string with one placeholder right at the end:
```shell
python -m timeit -s "import random; import string; from notifications_utils.field import Field; s = ''.join(random.choices(string.ascii_uppercase + string.digits + string.whitespace, k=1000)) + '((name))'" "Field(s).placeholders"
```

Before
> 50000 loops, best of 5: 9.06 usec per loop

After
> 50000 loops, best of 5: 9.06 usec per loop

No change.
@quis
quis force-pushed the optimise-placeholder-extraction branch from 9acc20c to 48e06c3 Compare June 11, 2026 12:03
@quis
quis merged commit 1499c51 into main Jun 12, 2026
6 checks passed
@quis
quis deleted the optimise-placeholder-extraction branch June 12, 2026 09:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants