Download Latest Version skipper-v0.27.97-windows-amd64.zip (156.4 MB) Google Add to Preferred Sources
Home / v0.27.95
Name Modified Size InfoDownloads / 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) and TestRouteGroupParseCacheIsPerRouteGroupWithoutSharing (independent caches without the call).
  • go test ./dataclients/kubernetes/... and -race pass; staticcheck -checks "all,-ST1003,-ST1020" and gofmt -s are 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
Source: README.md, updated 2026-09-15