mirror of
https://github.com/gravitational/teleport.git
synced 2026-09-19 01:58:44 +08:00
This commit does the following: - Move existing smoke benchmark workflows to seperate workflow. - Add differential benchmark workflows - Split benchmarks into heavy and micro categories - Add make target arguments for benchmark time and count - Move smoketests to run only on PRs - Differential benchmarks run on merge queue Benchmarks above 1ms/op are considered heavy and should make use of iteration based benchtime to prevent the CI job from taking too much time. Benchmarks are skipped based on env vars, this is an alternative to splitting benchmark targets into seperate files with build tags. The smoke tests should be much faster and as such are set to run on PRs to ensure the targets are not broken in the change. The current parameters for differential benchmarks attempt to balance CI runner time and confidence for benchstat. Differential benchmarks determine the base commit to run the tests against, this happens within the same job to remove the runner to runner variance.
201 lines
5.4 KiB
Go
201 lines
5.4 KiB
Go
// Teleport
|
|
// Copyright (C) 2025 Gravitational, Inc.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package cache
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/gravitational/trace"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/gravitational/teleport/api/client/proto"
|
|
apidefaults "github.com/gravitational/teleport/api/defaults"
|
|
"github.com/gravitational/teleport/api/types"
|
|
)
|
|
|
|
// TestNodes tests nodes cache
|
|
func TestNodes(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
t.Run("GetNodes", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
p := newTestPack(t, ForProxy)
|
|
t.Cleanup(p.Close)
|
|
|
|
testResources(t, p, testFuncs[types.Server]{
|
|
newResource: func(name string) (types.Server, error) {
|
|
return NewServer(types.KindNode, name, "127.0.0.1:2022", apidefaults.Namespace), nil
|
|
},
|
|
create: withKeepalive(p.presenceS.UpsertNode),
|
|
list: getAllAdapter(func(ctx context.Context) ([]types.Server, error) {
|
|
return p.presenceS.GetNodes(ctx, apidefaults.Namespace)
|
|
}),
|
|
cacheGet: func(ctx context.Context, name string) (types.Server, error) {
|
|
return p.cache.GetNode(ctx, apidefaults.Namespace, name)
|
|
},
|
|
cacheList: getAllAdapter(func(ctx context.Context) ([]types.Server, error) { return p.cache.GetNodes(ctx, apidefaults.Namespace) }),
|
|
update: withKeepalive(p.presenceS.UpsertNode),
|
|
deleteAll: func(ctx context.Context) error {
|
|
return p.presenceS.DeleteAllNodes(ctx, apidefaults.Namespace)
|
|
},
|
|
}, withSkipPaginationTest())
|
|
})
|
|
|
|
t.Run("ListResources", func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
p := newTestPack(t, ForProxy)
|
|
t.Cleanup(p.Close)
|
|
|
|
testResources(t, p, testFuncs[types.Server]{
|
|
newResource: func(name string) (types.Server, error) {
|
|
return NewServer(types.KindNode, name, "127.0.0.1:2022", apidefaults.Namespace), nil
|
|
},
|
|
create: withKeepalive(p.presenceS.UpsertNode),
|
|
list: func(ctx context.Context, pageSize int, pageToken string) ([]types.Server, string, error) {
|
|
req := proto.ListResourcesRequest{
|
|
ResourceType: types.KindNode,
|
|
Limit: int32(pageSize),
|
|
StartKey: pageToken,
|
|
}
|
|
|
|
var out []types.Server
|
|
resp, err := p.presenceS.ListResources(ctx, req)
|
|
if err != nil {
|
|
return nil, "", trace.Wrap(err)
|
|
}
|
|
|
|
for _, s := range resp.Resources {
|
|
out = append(out, s.(types.Server))
|
|
}
|
|
|
|
return out, resp.NextKey, nil
|
|
},
|
|
cacheGet: func(ctx context.Context, name string) (types.Server, error) {
|
|
return p.cache.GetNode(ctx, apidefaults.Namespace, name)
|
|
},
|
|
cacheList: func(ctx context.Context, pageSize int, pageToken string) ([]types.Server, string, error) {
|
|
req := proto.ListResourcesRequest{
|
|
ResourceType: types.KindNode,
|
|
Limit: int32(pageSize),
|
|
StartKey: pageToken,
|
|
}
|
|
|
|
var out []types.Server
|
|
resp, err := p.cache.ListResources(ctx, req)
|
|
if err != nil {
|
|
return nil, "", trace.Wrap(err)
|
|
}
|
|
|
|
for _, s := range resp.Resources {
|
|
out = append(out, s.(types.Server))
|
|
}
|
|
|
|
return out, resp.NextKey, nil
|
|
},
|
|
update: withKeepalive(p.presenceS.UpsertNode),
|
|
deleteAll: func(ctx context.Context) error {
|
|
return p.presenceS.DeleteAllNodes(ctx, apidefaults.Namespace)
|
|
},
|
|
})
|
|
})
|
|
}
|
|
|
|
func BenchmarkGetMaxNodes(b *testing.B) {
|
|
if testing.Short() {
|
|
b.Skip("skipping heavy benchmark")
|
|
}
|
|
benchGetNodes(b, 1_000_000)
|
|
}
|
|
|
|
func benchGetNodes(b *testing.B, nodeCount int) {
|
|
p, err := newPack(b, ForAuth)
|
|
require.NoError(b, err)
|
|
defer p.Close()
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
createErr := make(chan error, 1)
|
|
|
|
go func() {
|
|
for range nodeCount {
|
|
server := NewServer(types.KindNode, uuid.New().String(), "127.0.0.1:2022", apidefaults.Namespace)
|
|
_, err := p.presenceS.UpsertNode(ctx, server)
|
|
if err != nil {
|
|
createErr <- err
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
|
|
timeout := time.After(time.Second * 90)
|
|
|
|
for i := range nodeCount {
|
|
select {
|
|
case event := <-p.eventsC:
|
|
if event.Type == RelativeExpiry {
|
|
continue
|
|
}
|
|
|
|
require.Equal(b, EventProcessed, event.Type)
|
|
case err := <-createErr:
|
|
b.Fatalf("failed to create node: %v", err)
|
|
case <-timeout:
|
|
b.Fatalf("timeout waiting for event, progress=%d", i)
|
|
}
|
|
}
|
|
|
|
b.ResetTimer()
|
|
|
|
b.Run("GetNodes", func(b *testing.B) {
|
|
for b.Loop() {
|
|
nodes, err := p.cache.GetNodes(ctx, apidefaults.Namespace)
|
|
require.NoError(b, err)
|
|
require.Len(b, nodes, nodeCount)
|
|
}
|
|
})
|
|
|
|
b.Run("ListResources", func(b *testing.B) {
|
|
for b.Loop() {
|
|
req := proto.ListResourcesRequest{
|
|
ResourceType: types.KindNode,
|
|
}
|
|
|
|
nodes := make([]types.ResourceWithLabels, 0, nodeCount)
|
|
for {
|
|
resp, err := p.cache.ListResources(ctx, req)
|
|
require.NoError(b, err)
|
|
|
|
req.StartKey = resp.NextKey
|
|
nodes = append(nodes, resp.Resources...)
|
|
|
|
if req.StartKey == "" {
|
|
break
|
|
}
|
|
}
|
|
|
|
require.Len(b, nodes, nodeCount)
|
|
}
|
|
})
|
|
|
|
}
|