mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-30 17:53:21 -04:00 
			
		
		
		
	perf(kubernetes): optimize AutoPath slice allocation (#7323)
Pre-allocate slice capacity in AutoPath to eliminate unnecessary memory reallocations. This avoids slice growth when appending search domains and sentinel value. Benchmark shows significant performance improvement: - Before: 538.6 ns/op, 560 B/op, 13 allocs/op - After: 436.8 ns/op, 336 B/op, 11 allocs/op - Result: 19% faster, 40% less memory, 15% fewer allocations The optimization benefits Kubernetes clusters using autopath for server-side search path completion. Adds benchmark test to measure AutoPath performance. Signed-off-by: Ville Vesilehto <ville@vesilehto.fi>
This commit is contained in:
		| @@ -33,15 +33,12 @@ func (k *Kubernetes) AutoPath(state request.Request) []string { | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	search := make([]string, 3) | 	totalSize := 3 + len(k.autoPathSearch) + 1 // +1 for sentinel | ||||||
|  | 	search := make([]string, 0, totalSize) | ||||||
| 	if zone == "." { | 	if zone == "." { | ||||||
| 		search[0] = pod.Namespace + ".svc." | 		search = append(search, pod.Namespace+".svc.", "svc.", ".") | ||||||
| 		search[1] = "svc." |  | ||||||
| 		search[2] = "." |  | ||||||
| 	} else { | 	} else { | ||||||
| 		search[0] = pod.Namespace + ".svc." + zone | 		search = append(search, pod.Namespace+".svc."+zone, "svc."+zone, zone) | ||||||
| 		search[1] = "svc." + zone |  | ||||||
| 		search[2] = zone |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	search = append(search, k.autoPathSearch...) | 	search = append(search, k.autoPathSearch...) | ||||||
|   | |||||||
							
								
								
									
										77
									
								
								plugin/kubernetes/autopath_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								plugin/kubernetes/autopath_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | package kubernetes | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"testing" | ||||||
|  |  | ||||||
|  | 	"github.com/coredns/coredns/plugin/kubernetes/object" | ||||||
|  | 	"github.com/coredns/coredns/plugin/test" | ||||||
|  | 	"github.com/coredns/coredns/request" | ||||||
|  |  | ||||||
|  | 	"github.com/miekg/dns" | ||||||
|  | 	api "k8s.io/api/core/v1" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Mock data for benchmarks | ||||||
|  | var ( | ||||||
|  | 	mockPod = &object.Pod{ | ||||||
|  | 		Namespace: "test-namespace", | ||||||
|  | 	} | ||||||
|  | 	mockAutoPathSearch = []string{"example.com", "internal.example.com", "cluster.local"} | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // Mock API connector for testing | ||||||
|  | type mockAPIConnector struct{} | ||||||
|  |  | ||||||
|  | func (m *mockAPIConnector) PodIndex(ip string) []*object.Pod { | ||||||
|  | 	return []*object.Pod{mockPod} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Minimal implementation of other required methods | ||||||
|  | func (m *mockAPIConnector) ServiceList() []*object.Service                     { return nil } | ||||||
|  | func (m *mockAPIConnector) EndpointsList() []*object.Endpoints                 { return nil } | ||||||
|  | func (m *mockAPIConnector) ServiceImportList() []*object.ServiceImport         { return nil } | ||||||
|  | func (m *mockAPIConnector) SvcIndex(s string) []*object.Service                { return nil } | ||||||
|  | func (m *mockAPIConnector) SvcIndexReverse(s string) []*object.Service         { return nil } | ||||||
|  | func (m *mockAPIConnector) SvcExtIndexReverse(s string) []*object.Service      { return nil } | ||||||
|  | func (m *mockAPIConnector) SvcImportIndex(s string) []*object.ServiceImport    { return nil } | ||||||
|  | func (m *mockAPIConnector) EpIndex(s string) []*object.Endpoints               { return nil } | ||||||
|  | func (m *mockAPIConnector) EpIndexReverse(s string) []*object.Endpoints        { return nil } | ||||||
|  | func (m *mockAPIConnector) McEpIndex(s string) []*object.MultiClusterEndpoints { return nil } | ||||||
|  | func (m *mockAPIConnector) GetNodeByName(ctx context.Context, name string) (*api.Node, error) { | ||||||
|  | 	return nil, nil | ||||||
|  | } | ||||||
|  | func (m *mockAPIConnector) GetNamespaceByName(name string) (*object.Namespace, error) { | ||||||
|  | 	return nil, nil | ||||||
|  | } | ||||||
|  | func (m *mockAPIConnector) Run()                        {} | ||||||
|  | func (m *mockAPIConnector) HasSynced() bool             { return true } | ||||||
|  | func (m *mockAPIConnector) Stop() error                 { return nil } | ||||||
|  | func (m *mockAPIConnector) Modified(ModifiedMode) int64 { return 0 } | ||||||
|  |  | ||||||
|  | func BenchmarkAutoPath(b *testing.B) { | ||||||
|  | 	k := &Kubernetes{ | ||||||
|  | 		Zones:          []string{"cluster.local."}, | ||||||
|  | 		autoPathSearch: mockAutoPathSearch, | ||||||
|  | 		podMode:        podModeVerified, | ||||||
|  | 		opts: dnsControlOpts{ | ||||||
|  | 			initPodCache: true, | ||||||
|  | 		}, | ||||||
|  | 		APIConn: &mockAPIConnector{}, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Create a mock DNS request | ||||||
|  | 	req := &dns.Msg{} | ||||||
|  | 	req.SetQuestion("test.cluster.local.", dns.TypeA) | ||||||
|  |  | ||||||
|  | 	// Create a request state with a mock ResponseWriter | ||||||
|  | 	state := request.Request{W: &test.ResponseWriter{}, Req: req} | ||||||
|  |  | ||||||
|  | 	b.ReportAllocs() | ||||||
|  | 	b.ResetTimer() | ||||||
|  |  | ||||||
|  | 	for i := 0; i < b.N; i++ { | ||||||
|  | 		result := k.AutoPath(state) | ||||||
|  | 		_ = result | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user