Avoid copying EndpointBuilder struct in buildEndpoints
perfloop/istio · AVOIDABLE COPY
https://perfloop.ai/t/oss/case_gqvx3m7sq4
Verdict
VERIFIED · settled 2026-08-23
What happened: The paired measurements met the required improvement.
Hypothesis
In `pilot/pkg/xds/eds.go` within `buildEndpoints`, the loop over `w.ResourceNames` constructs an endpoint builder: ```go builder := *endpoints.NewCDSEndpointBuilder(...) ``` This dereferences the `*EndpointBuilder` pointer returned by `NewCDSEndpointBuilder`, copying the entire struct (approximately 200 bytes, containing multiple strings, interfaces, slice headers, and map references) into a local variable. Later, `&builder` is passed to `eds.Cache.Get(&builder)` and `eds.Cache.Add(&builder, req, resource)`. Since the cache methods accept `XdsCacheEntry` interfaces, the local `builder` variable is proven to escape to the heap. This forces a second heap allocation of `EndpointBuilder` per iteration, on top of the allocation already performed inside `NewCDSEndpointBuilder`, plus the overhead of copying the struct. By keeping `builder` as a pointer (`builder := endpoints.NewCDSEndpointBuilder(...)`) and passing `builder` (not `&builder`), we completely eliminate both the struct copy and the double allocation.
Change to test: Avoid copying the EndpointBuilder struct by using the pointer returned by NewCDSEndpointBuilder directly instead of dereferencing it.
Where it lives
perfloop/istio · pilot/pkg/xds/eds.go
Evidence
ADS EDS full push with 100 cached endpoint clusters · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
111330 |
87082 |
−21.8% (−24234) |
−24315 to −24140 |
< −5567 |
PASSED |
allocs/op |
1142 |
1044 |
−8.7% (−99.5) |
−103 to −97 |
< −57.1 |
PASSED |
ADS EDS full push with 1,000 cached endpoint clusters · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
1141750 |
868339 |
−23.7% (−270557) |
−286022 to −254238 |
< −57088 |
PASSED |
allocs/op |
10303 |
9290 |
−9.8% (−1011) |
−1020 to −1005 |
< −515.1 |
PASSED |
ADS EDS partial push with 100 cached endpoint clusters · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
131144 |
106890 |
−18.5% (−24276) |
−24373 to −24150 |
< −6557 |
PASSED |
allocs/op |
1156 |
1055 |
−8.7% (−101) |
−104 to −97 |
< −57.8 |
PASSED |
ADS EDS partial push with 1,000 cached endpoint clusters · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
1511788 |
1234989 |
−18.3% (−276089) |
−293898 to −263159 |
< −75589 |
PASSED |
allocs/op |
10354 |
9342 |
−9.8% (−1014) |
−1028 to −1003 |
< −517.7 |
PASSED |
ADS EDS full push with 1 cached endpoint cluster · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
9137 |
8899 |
−2.6% (−239.5) |
−249 to −233 |
≤ 0 |
PASSED |
allocs/op |
135 |
134 |
−0.7% (−1) |
−1 to −1 |
≤ 0 |
PASSED |
ADS EDS partial push with 1 cached endpoint cluster · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
9389 |
9148 |
−2.6% (−241.5) |
−253 to −224 |
≤ 0 |
PASSED |
allocs/op |
127 |
126 |
−0.8% (−1) |
−1 to −1 |
≤ 0 |
PASSED |
ADS EDS full push with 1 uncached endpoint cluster · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
15606 |
15367 |
−1.6% (−242) |
−251 to −230 |
≤ 0 |
PASSED |
allocs/op |
238 |
237 |
−0.4% (−1) |
−1 to −1 |
≤ 0 |
PASSED |
ADS EDS full push with 100 uncached endpoint clusters · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
637413 |
612853 |
−3.9% (−24652) |
−24943 to −23849 |
≤ 0 |
PASSED |
allocs/op |
9195 |
9094 |
−1.1% (−100.5) |
−101 to −100 |
≤ 0 |
PASSED |
ADS EDS full push with 1,000 uncached endpoint clusters · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
6841566 |
6609787 |
−3.2% (−220976) |
−332261 to −160059 |
≤ 0 |
PASSED |
allocs/op |
89358 |
88358 |
−1.1% (−1000) |
−1002 to −999 |
≤ 0 |
PASSED |
ADS EDS partial push with 1 uncached endpoint cluster · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
15852 |
15609 |
−1.5% (−238) |
−257 to −235 |
≤ 0 |
PASSED |
allocs/op |
230 |
229 |
−0.4% (−1) |
−1 to −1 |
≤ 0 |
PASSED |
ADS EDS partial push with 100 uncached endpoint clusters · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
656782 |
632725 |
−3.7% (−24003) |
−24495 to −23544 |
≤ 0 |
PASSED |
allocs/op |
9204 |
9104 |
−1.1% (−100) |
−101 to −100 |
≤ 0 |
PASSED |
ADS EDS partial push with 1,000 uncached endpoint clusters · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
7214695 |
6915428 |
−4.3% (−308889) |
−376769 to −163623 |
≤ 0 |
PASSED |
allocs/op |
89388 |
88387 |
−1.1% (−1001) |
−1004 to −1000 |
≤ 0 |
PASSED |
ADS EDS full push with 1 endpoint cluster and disabled cache · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
13517 |
13284 |
−1.8% (−240) |
−251 to −224 |
≤ 0 |
PASSED |
allocs/op |
204 |
203 |
−0.5% (−1) |
−1 to −1 |
≤ 0 |
PASSED |
ADS EDS full push with 100 endpoint clusters and disabled cache · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
550731 |
526453 |
−4.4% (−24095) |
−24752 to −23763 |
≤ 0 |
PASSED |
allocs/op |
7952 |
7852 |
−1.3% (−100) |
−100 to −100 |
≤ 0 |
PASSED |
ADS EDS full push with 1,000 endpoint clusters and disabled cache · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
5884751 |
5623003 |
−4.7% (−276557) |
−328491 to −205040 |
≤ 0 |
PASSED |
allocs/op |
77287 |
76286 |
−1.3% (−1001) |
−1001 to −999 |
≤ 0 |
PASSED |
ADS EDS partial push with 1 endpoint cluster and disabled cache · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
13768 |
13532 |
−1.7% (−236.5) |
−254 to −224 |
≤ 0 |
PASSED |
allocs/op |
196 |
195 |
−0.5% (−1) |
−1 to −1 |
≤ 0 |
PASSED |
ADS EDS partial push with 100 endpoint clusters and disabled cache · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
570858 |
546444 |
−4.3% (−24352) |
−25094 to −23947 |
≤ 0 |
PASSED |
allocs/op |
7961 |
7861 |
−1.3% (−100) |
−101 to −100 |
≤ 0 |
PASSED |
ADS EDS partial push with 1,000 endpoint clusters and disabled cache · 10 sample pairs
| metric | baseline | candidate | paired median change | confidence range | required | result |
|---|---|---|---|---|---|---|
B/op |
6180853 |
5924550 |
−4% (−247069) |
−333200 to −234993 |
≤ 0 |
PASSED |
allocs/op |
77317 |
76316 |
−1.3% (−1001) |
−1003 to −999 |
≤ 0 |
PASSED |
Checks: 1 of 1 passed. Verification: no defect found.
Timeline
2026-07-01· Case opened