| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| skipper-v0.27.95-windows-amd64.zip | < 23 hours ago | 156.3 MB | |
| skipper-v0.27.95-linux-armv7.tar.gz | < 23 hours ago | 143.1 MB | |
| skipper-v0.27.95-linux-arm64.tar.gz | < 23 hours ago | 142.1 MB | |
| skipper-v0.27.95-linux-amd64.tar.gz | < 23 hours ago | 154.9 MB | |
| skipper-v0.27.95-darwin-arm64.tar.gz | < 23 hours ago | 152.8 MB | |
| skipper-v0.27.95-darwin-amd64.tar.gz | < 23 hours ago | 162.1 MB | |
| sha256sum.txt | < 23 hours ago | 613 Bytes | |
| README.md | < 23 hours ago | 3.1 kB | |
| v0.27.95 source code.tar.gz | < 23 hours ago | 5.2 MB | |
| v0.27.95 source code.zip | < 23 hours ago | 6.2 MB | |
| Totals: 10 Items | 922.7 MB | 0 | |
Changes
Cache parsed filters and predicates across RouteGroups (#4266)
Fixes [#4228]. Based on https://github.com/zalando/skipper/pull/4229
Problem
[#4223] added a parse cache scoped to a single RouteGroup, so a filter
or predicate string repeated across the routes of one RouteGroup is
parsed once. In a real cluster many RouteGroups repeat the same strings
(Method("GET") appears in almost every one), and those are still
parsed once per RouteGroup.
Change
RouteGroupList.ShareParseCache() gives every RouteGroup in a load one
shared filter map and one shared predicate map. It is called in
clusterClient.LoadRouteGroups right after the RouteGroups are fetched,
before validation and conversion. Both phases already go through
RouteGroupSpec.ParseFilter / ParsePredicate, so a string that
repeats across RouteGroups is now parsed once per load instead of once
per RouteGroup. ParseFilter / ParsePredicate are unchanged.
Correctness
The parsed *eskip.Filter / *eskip.Predicate were already shared
across the routes of a RouteGroup by [#4223] and documented as "MUST NOT
be mutated in place". Sharing them across RouteGroups keeps the same
contract: conversion only appends them to route slices
(transformExplicitGroupRoute), and eskip deep-copies routes
(Route.Copy, which copies filters and predicates) before any mutation.
Validation and conversion run from a single goroutine over the load,
matching the previous per-RouteGroup cache, so no locking is added. go
test -race ./dataclients/kubernetes/... passes.
Benchmark
BenchmarkRouteGroupsLoadAll already loads 200 RouteGroups that repeat
the same filter and predicate strings, so it exercises the
cross-RouteGroup case directly. benchstat over 10 runs, per-RouteGroup
cache (base) vs shared cache:
│ base │ shared │
│ sec/op │ sec/op vs base │
RouteGroupsLoadAll-8 4.579m ± 1% 3.628m ± 0% -20.76% (p=0.000 n=10)
│ base │ shared │
│ B/op │ B/op vs base │
RouteGroupsLoadAll-8 2.420Mi ± 0% 2.133Mi ± 0% -11.83% (p=0.000 n=10)
│ base │ shared │
│ allocs/op │ allocs/op vs base │
RouteGroupsLoadAll-8 48.14k ± 0% 35.61k ± 0% -26.04% (p=0.000 n=10)
Testing
- Added
TestRouteGroupListShareParseCache(a string parsed through two different RouteGroups resolves to the same cached object) andTestRouteGroupParseCacheIsPerRouteGroupWithoutSharing(independent caches without the call). go test ./dataclients/kubernetes/...and-racepass;staticcheck -checks "all,-ST1003,-ST1020"andgofmt -sare clean.
Multiarch Docker image
Multiarch Docker image is available in GitHub's docker registry:
docker run -it ghcr.io/zalando/skipper:v0.27.95 skipper --help