Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Perf tests refactor and optimizations #1615

Merged
merged 5 commits into from
Feb 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
*.so
*.test
*.out
*.log

# ignore IDE files
.idea/*

# ignore executables (extensionless files)
Expand All @@ -13,16 +15,8 @@
!/examples/**/
!/examples/**/*.*

# test results
/tests/perf/grpc-perf/grpc-perf
/tests/perf/log
/tests/perf/logresult.zip
/tests/robot/variables/jozo_local_variables.robot

# vpp directory
# top level dirs
/vpp/

# exclude vendor
/vendor/

/.build/
/report/
21 changes: 17 additions & 4 deletions pkg/debug/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,23 @@ import (
"net/http"
_ "net/http/pprof"
"os"
"strconv"
"strings"

"github.com/pkg/profile"
)

const defaultServerAddr = ":1234"
const (
defaultServerAddr = ":1234"
defaultMemProfileRate = 1024
)

var (
profileMode = os.Getenv("DEBUG_PROFILE_MODE")
profilePath = os.Getenv("DEBUG_PROFILE_PATH")
debugServerAddr = os.Getenv("DEBUG_SERVER_ADDR")

profileMode = os.Getenv("DEBUG_PROFILE_MODE")
profilePath = os.Getenv("DEBUG_PROFILE_PATH")
profileMemRate = os.Getenv("DEBUG_PROFILE_MEMRATE")
)

type Debug struct {
Expand Down Expand Up @@ -58,11 +64,18 @@ func (d *Debug) Stop() {
func (d *Debug) runProfiling() {
var profiling func(*profile.Profile)

memRate := defaultMemProfileRate
if profileMemRate != "" {
if x, err := strconv.Atoi(profileMemRate); err == nil {
memRate = x
}
}

switch strings.ToLower(profileMode) {
case "cpu":
profiling = profile.CPUProfile
case "mem":
profiling = profile.MemProfile
profiling = profile.MemProfileRate(memRate)
case "mutex":
profiling = profile.MutexProfile
case "block":
Expand Down
46 changes: 31 additions & 15 deletions pkg/models/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,20 @@ type KnownModel struct {

goType reflect.Type
protoName string

// cache
keyPrefix *string
modelName *string
}

// Spec returns model specification for the model.
func (m KnownModel) Spec() *Spec {
func (m *KnownModel) Spec() *Spec {
spec := m.spec
return &spec
}

// ModelDescriptor returns descriptor for the model.
func (m KnownModel) ModelDetail() *generic.ModelDetail {
// ModelDetail returns descriptor for the model.
func (m *KnownModel) ModelDetail() *generic.ModelDetail {
return &generic.ModelDetail{
Spec: m.Spec().Proto(),
ProtoName: m.ProtoName(),
Expand All @@ -51,35 +55,47 @@ func (m KnownModel) ModelDetail() *generic.ModelDetail {
}

// NewInstance creates new instance value for model type.
func (m KnownModel) NewInstance() proto.Message {
func (m *KnownModel) NewInstance() proto.Message {
return reflect.New(m.goType.Elem()).Interface().(proto.Message)
}

// ProtoName returns proto message name registered with the model.
func (m KnownModel) ProtoName() string {
func (m *KnownModel) ProtoName() string {
if m.protoName == "" {
m.protoName = proto.MessageName(m.NewInstance())
}
return m.protoName
}

// NameTemplate returns name template for the model.
func (m KnownModel) NameTemplate() string {
func (m *KnownModel) NameTemplate() string {
return m.nameTemplate
}

// GoType returns go type for the model.
func (m KnownModel) GoType() string {
func (m *KnownModel) GoType() string {
return m.goType.String()
}

// Path returns path for the model.
func (m KnownModel) Name() string {
return m.spec.ModelName()
// Name returns name for the model.
func (m *KnownModel) Name() string {
if m.modelName == nil {
modelName := m.spec.ModelName()
m.modelName = &modelName
}
return *m.modelName
}

// KeyPrefix returns key prefix for the model.
func (m KnownModel) KeyPrefix() string {
func (m *KnownModel) KeyPrefix() string {
if m.keyPrefix == nil {
keyPrefix := m.getKeyPrefix()
m.keyPrefix = &keyPrefix
}
return *m.keyPrefix
}

func (m *KnownModel) getKeyPrefix() string {
keyPrefix := m.spec.KeyPrefix()
if m.nameFunc == nil {
keyPrefix = strings.TrimSuffix(keyPrefix, "/")
Expand All @@ -89,7 +105,7 @@ func (m KnownModel) KeyPrefix() string {

// ParseKey parses the given key and returns item name
// or returns empty name and valid as false if the key is not valid.
func (m KnownModel) ParseKey(key string) (name string, valid bool) {
func (m *KnownModel) ParseKey(key string) (name string, valid bool) {
name = strings.TrimPrefix(key, m.KeyPrefix())
if name == key || (name == "" && m.nameFunc != nil) {
name = strings.TrimPrefix(key, m.Name())
Expand All @@ -104,20 +120,20 @@ func (m KnownModel) ParseKey(key string) (name string, valid bool) {
}

// IsKeyValid returns true if given key is valid for this model.
func (m KnownModel) IsKeyValid(key string) bool {
func (m *KnownModel) IsKeyValid(key string) bool {
_, valid := m.ParseKey(key)
return valid
}

// StripKeyPrefix returns key with prefix stripped.
func (m KnownModel) StripKeyPrefix(key string) string {
func (m *KnownModel) StripKeyPrefix(key string) string {
if name, valid := m.ParseKey(key); valid {
return name
}
return key
}

func (m KnownModel) instanceName(x proto.Message) (string, error) {
func (m *KnownModel) instanceName(x proto.Message) (string, error) {
if m.nameFunc == nil {
return "", nil
}
Expand Down
8 changes: 8 additions & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
log/
logresult.zip

reports/

/robot/variables/jozo_local_variables.robot

/perf/grpc-perf/grpc-perf
1 change: 0 additions & 1 deletion tests/perf/.gitignore

This file was deleted.

27 changes: 21 additions & 6 deletions tests/perf/grpc-perf/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/ligato/cn-infra/infra"
"github.com/ligato/cn-infra/logging"
"github.com/namsral/flag"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"

"go.ligato.io/vpp-agent/v3/proto/ligato/configurator"
Expand Down Expand Up @@ -80,7 +81,8 @@ func main() {

// GRPCStressPlugin makes use of the remoteclient to locally CRUD ipsec tunnels and routes.
type GRPCStressPlugin struct {
infra.PluginDeps
infra.PluginName
Log *logrus.Logger

conns []*grpc.ClientConn

Expand All @@ -90,14 +92,20 @@ type GRPCStressPlugin struct {
func NewGRPCStressPlugin() *GRPCStressPlugin {
p := &GRPCStressPlugin{}
p.SetName("grpc-stress-test-client")
p.Setup()
p.Log = logrus.New()
p.Log.SetFormatter(&logrus.TextFormatter{
ForceColors: true,
EnvironmentOverrideColors: true,
})
return p
}

// Init initializes plugin.
func (p *GRPCStressPlugin) Init() error {
return nil
}
func (p *GRPCStressPlugin) Close() error {
return nil
}

// Dialer for unix domain socket
func dialer(socket, address string, timeoutVal time.Duration) func(string, time.Duration) (net.Conn, error) {
Expand Down Expand Up @@ -216,9 +224,16 @@ func (p *GRPCStressPlugin) runAllClients() {

p.Log.Debugf("Waiting for clients..")
p.wg.Wait()

took := time.Since(t).Round(time.Microsecond * 100)
p.Log.Infof("All clients done, took: %v", took)
took := time.Since(t)
perSec := float64(*numTunnels) / took.Seconds()

p.Log.Infof("All clients done!")
p.Log.Infof("----------------------------------------")
p.Log.Infof(" -> Took: %.3fs", took.Seconds())
p.Log.Infof(" -> Clients: %d", *numClients)
p.Log.Infof(" -> Requests: %d", *numTunnels)
p.Log.Infof(" -> PERFORMANCE: %.1f req/sec", perSec)
p.Log.Infof("----------------------------------------")

for i := 0; i < *numClients; i++ {
if err := p.conns[i].Close(); err != nil {
Expand Down
31 changes: 22 additions & 9 deletions tests/perf/perf_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ agent_info="${REPORT_DIR}/agent-info.txt"
cpuprof="${REPORT_DIR}/cpu.pprof"
memprof="${REPORT_DIR}/mem.pprof"

rest_addr="${REST_ADDR:-http://127.0.0.1:9191}"

# -------
# test
# -------

function run_test() {
# create report directory
rm -vrf ${REPORT_DIR}/*
rm -vrf ${REPORT_DIR}/* 2>/dev/null
mkdir --mode=777 -p ${REPORT_DIR}

perftest $* 2>&1 | tee $log_report
Expand All @@ -45,8 +47,9 @@ function perftest() {
local requests="$2"

echo "================================================================================"
echo " PERF-TEST: $perftest - ${requests} requests"
echo " -> ${REPORT_DIR}"
echo " PERF TEST: $perftest"
echo " - num requests: ${requests}"
echo " - report dir: ${REPORT_DIR}"
echo "================================================================================"

prepare_test
Expand Down Expand Up @@ -116,8 +119,14 @@ function perftest() {
stop_vpp

echo -n "-> processing profiles.. "
[ -r "$cpuprof" ] && go tool pprof -dot "$cpuprof" | dot -Tsvg -o "$REPORT_DIR/cpu-profile.svg"
[ -r "$memprof" ] && go tool pprof -alloc_space -dot "$memprof" | dot -Tsvg -o "$REPORT_DIR/mem-profile.svg"
set +e
if [ -r "$cpuprof" ]; then
go tool pprof -dot "$cpuprof" | dot -Tsvg -o "$REPORT_DIR/cpu-profile.svg"
fi
if [ -r "$memprof" ]; then
go tool pprof -alloc_space -dot "$memprof" | dot -Tsvg -o "$REPORT_DIR/mem-profile.svg"
fi
set -e

echo
}
Expand All @@ -129,7 +138,7 @@ function prepare_test() {

#[[ -e "./$_test" ]] || {
echo "-> compiling test client $_test.."
go build -o "$_test_client/$_test" -v "$_test_client"
go build -o "$_test_client/$_test" "$_test_client"
#}
}

Expand Down Expand Up @@ -235,7 +244,7 @@ function vppcli() {
# vpp-agent
# -------------

wait_agent_boot=5
wait_agent_boot=10

function start_agent() {
local _agent="$(which vpp-agent)"
Expand All @@ -247,7 +256,11 @@ function start_agent() {
$_agent > "$log_agent" 2>&1 &
pid_agent="$!"
timeout "${wait_agent_boot}" grep -q "Agent started" <(tail -qF $log_agent) || {
fail "timeout!"
echo "AGENT LOG:"
echo "---"
tail "$log_agent"
echo "---"
fail "TIMEOUT!"
}
echo "ok! (PID:${pid_agent})"
}
Expand Down Expand Up @@ -287,7 +300,7 @@ function check_agent() {
}

function agentrest() {
local url="http://localhost:9191/$1"
local url="$rest_addr/$1"

echo "----------------------------------------------------"
echo "GET $url"
Expand Down