The regexp used in Varnish ban has very poor performance.
This is a backport of a fix already merged in API Platform, where it's a little easier to fix because we know in advance the pattern of the tags to ban. More specifically, on APIP, we know that a tag always began with a / and as they are iri, they are unique and not nested. We can then strip the first group (^|,).
This is not the case here where tags could be anything.
This is something I wanted to talk since a long time but didn't took the time to share because I don't have the correct generic solution. Maybe you will have one.
The current ban regexp is not optimize and killed my varnish server to 100% cpu.
Several reasons, but let's explain how that work. This is a question of
rq/s * ban/s * size of the cache tags header * complexity of the regexp
I've a high number of requests and bans per seconds. The response has a lot of tags.
But I only ban one resource at a time, so the regexp was not that complex at first look.
Varnish stores all ban in a (deduplicated) list. Each cached resource has a pointer to the last ban checked.
If you add bans, when you call a cached resources, it will check against all the new bans and store the last ones.
The number of regexp analysis was high, but I can change my traffic, so I can only adjust the header itself or the regexp.
I looked at the regexp first
((^|,)/pim/v1/variants($|,))|((^|,)/pim/v1/variants/e3615f0c-a957-4a85-88b9-8db30d5c5c02($|,))|((^|,)/pim/v1/models/bebdee7b-fb53-448b-b79e-1bcf0dbcf050($|,))
Step 1: checking the begining of the resources is not useful if tags are only handled by apip.
(/pim/v1/variants($|,))|(/pim/v1/variants/e3615f0c-a957-4a85-88b9-8db30d5c5c02($|,))|(/pim/v1/models/bebdee7b-fb53-448b-b79e-1bcf0dbcf050($|,))
Stepe 2: regrouping the end tag at the end is better.
(/pim/v1/variants|/pim/v1/variants/e3615f0c-a957-4a85-88b9-8db30d5c5c02|/pim/v1/models/bebdee7b-fb53-448b-b79e-1bcf0dbcf050)($|,)
Step 3: remove the prefix from the regexp
(/variants|/variants/e3615f0c-a957-4a85-88b9-8db30d5c5c02|/models/bebdee7b-fb53-448b-b79e-1bcf0dbcf050)($|,)
Step 4: remove the prefix from the source header
Bench:
| subject |
mean |
diff |
| benchCurrent |
1.612μs |
7.91x |
| benchStep1 |
0.575μs |
2.82x |
| benchStep2 |
0.504μs |
2.47x |
| benchStep3 |
0.492μs |
2.41x |
| benchStep4 |
0.204μs |
1.00x |
On my production, I published Step3 today at 12:15:

On another project, I will let you guess when the patch was released:

The regexp used in Varnish ban has very poor performance.
This is a backport of a fix already merged in API Platform, where it's a little easier to fix because we know in advance the pattern of the tags to ban. More specifically, on APIP, we know that a tag always began with a / and as they are iri, they are unique and not nested. We can then strip the first group
(^|,).This is not the case here where tags could be anything.
This is something I wanted to talk since a long time but didn't took the time to share because I don't have the correct generic solution. Maybe you will have one.
The current ban regexp is not optimize and killed my varnish server to 100% cpu.
Several reasons, but let's explain how that work. This is a question of
I've a high number of requests and bans per seconds. The response has a lot of tags.
But I only ban one resource at a time, so the regexp was not that complex at first look.
Varnish stores all ban in a (deduplicated) list. Each cached resource has a pointer to the last ban checked.
If you add bans, when you call a cached resources, it will check against all the new bans and store the last ones.
The number of regexp analysis was high, but I can change my traffic, so I can only adjust the header itself or the regexp.
I looked at the regexp first
Step 1: checking the begining of the resources is not useful if tags are only handled by apip.
Stepe 2: regrouping the end tag at the end is better.
Step 3: remove the prefix from the regexp
Step 4: remove the prefix from the source header
Bench:
On my production, I published Step3 today at 12:15:
On another project, I will let you guess when the patch was released:
