Skip to main content
Glama
resolver_bench_test.go9.14 kB
package proto import ( "testing" ) // BenchmarkFindMessageByType benchmarks message type lookup func BenchmarkFindMessageByType(b *testing.B) { index := NewProtoIndex(testLogger()) // Create test messages for i := 0; i < 100; i++ { msg := &ProtoMessage{ Name: "Message" + string(rune(i)), FullName: "api.v1.Message" + string(rune(i)), Fields: []ProtoField{ {Name: "id", Type: "int32", Number: 1}, }, } index.messages[msg.FullName] = msg } b.ResetTimer() for i := 0; i < b.N; i++ { index.findMessageByType("Message50", "api.v1") } } // BenchmarkFindEnumByType benchmarks enum type lookup func BenchmarkFindEnumByType(b *testing.B) { index := NewProtoIndex(testLogger()) // Create test enums for i := 0; i < 100; i++ { enum := &ProtoEnum{ Name: "Enum" + string(rune(i)), FullName: "api.v1.Enum" + string(rune(i)), Values: []ProtoField{ {Name: "VALUE_0", Number: 0}, }, } index.enums[enum.FullName] = enum } b.ResetTimer() for i := 0; i < b.N; i++ { index.findEnumByType("Enum50", "api.v1") } } // BenchmarkResolveMessageTypesSimple benchmarks simple message resolution func BenchmarkResolveMessageTypesSimple(b *testing.B) { index := NewProtoIndex(testLogger()) // Create simple nested structure: A -> B msgB := &ProtoMessage{ Name: "B", FullName: "api.v1.B", Fields: []ProtoField{ {Name: "value", Type: "string", Number: 1}, }, } msgA := &ProtoMessage{ Name: "A", FullName: "api.v1.A", Fields: []ProtoField{ {Name: "b", Type: "B", Number: 1}, }, } index.messages["api.v1.A"] = msgA index.messages["api.v1.B"] = msgB b.ResetTimer() for i := 0; i < b.N; i++ { index.resolveMessageTypes(msgA, 10, nil) } } // BenchmarkResolveMessageTypesDeep benchmarks deep nested resolution func BenchmarkResolveMessageTypesDeep(b *testing.B) { index := NewProtoIndex(testLogger()) // Create deep nested structure: A -> B -> C -> D -> E msgE := &ProtoMessage{ Name: "E", FullName: "api.v1.E", Fields: []ProtoField{ {Name: "value", Type: "string", Number: 1}, }, } msgD := &ProtoMessage{ Name: "D", FullName: "api.v1.D", Fields: []ProtoField{ {Name: "e", Type: "E", Number: 1}, }, } msgC := &ProtoMessage{ Name: "C", FullName: "api.v1.C", Fields: []ProtoField{ {Name: "d", Type: "D", Number: 1}, }, } msgB := &ProtoMessage{ Name: "B", FullName: "api.v1.B", Fields: []ProtoField{ {Name: "c", Type: "C", Number: 1}, }, } msgA := &ProtoMessage{ Name: "A", FullName: "api.v1.A", Fields: []ProtoField{ {Name: "b", Type: "B", Number: 1}, }, } index.messages["api.v1.A"] = msgA index.messages["api.v1.B"] = msgB index.messages["api.v1.C"] = msgC index.messages["api.v1.D"] = msgD index.messages["api.v1.E"] = msgE b.ResetTimer() for i := 0; i < b.N; i++ { index.resolveMessageTypes(msgA, 10, nil) } } // BenchmarkResolveMessageTypesWide benchmarks wide message resolution (many fields) func BenchmarkResolveMessageTypesWide(b *testing.B) { index := NewProtoIndex(testLogger()) // Create wide structure: A has 10 fields, each pointing to a different message msgA := &ProtoMessage{ Name: "A", FullName: "api.v1.A", Fields: make([]ProtoField, 10), } for i := 0; i < 10; i++ { typeName := "Type" + string(rune('A'+i)) msgA.Fields[i] = ProtoField{ Name: "field" + string(rune('0'+i)), Type: typeName, Number: i + 1, } // Create the referenced message msg := &ProtoMessage{ Name: typeName, FullName: "api.v1." + typeName, Fields: []ProtoField{ {Name: "value", Type: "string", Number: 1}, }, } index.messages["api.v1."+typeName] = msg } index.messages["api.v1.A"] = msgA b.ResetTimer() for i := 0; i < b.N; i++ { index.resolveMessageTypes(msgA, 10, nil) } } // BenchmarkResolveMessageTypesCircular benchmarks circular reference resolution func BenchmarkResolveMessageTypesCircular(b *testing.B) { index := NewProtoIndex(testLogger()) // Create circular reference: A -> B -> A msgA := &ProtoMessage{ Name: "A", FullName: "api.v1.A", Fields: []ProtoField{ {Name: "b", Type: "B", Number: 1}, }, } msgB := &ProtoMessage{ Name: "B", FullName: "api.v1.B", Fields: []ProtoField{ {Name: "a", Type: "A", Number: 1}, }, } index.messages["api.v1.A"] = msgA index.messages["api.v1.B"] = msgB b.ResetTimer() for i := 0; i < b.N; i++ { index.resolveMessageTypes(msgA, 10, nil) } } // BenchmarkResolveServiceTypes benchmarks service type resolution func BenchmarkResolveServiceTypes(b *testing.B) { index := NewProtoIndex(testLogger()) // Create service with multiple RPCs service := &ProtoService{ Name: "UserService", FullName: "api.v1.UserService", RPCs: []ProtoRPC{ {Name: "GetUser", RequestType: "GetUserRequest", ResponseType: "GetUserResponse"}, {Name: "CreateUser", RequestType: "CreateUserRequest", ResponseType: "CreateUserResponse"}, {Name: "UpdateUser", RequestType: "UpdateUserRequest", ResponseType: "UpdateUserResponse"}, {Name: "DeleteUser", RequestType: "DeleteUserRequest", ResponseType: "DeleteUserResponse"}, }, } // Create request and response messages for _, rpc := range service.RPCs { reqMsg := &ProtoMessage{ Name: rpc.RequestType, FullName: "api.v1." + rpc.RequestType, Fields: []ProtoField{ {Name: "id", Type: "int32", Number: 1}, }, } index.messages["api.v1."+rpc.RequestType] = reqMsg respMsg := &ProtoMessage{ Name: rpc.ResponseType, FullName: "api.v1." + rpc.ResponseType, Fields: []ProtoField{ {Name: "user", Type: "User", Number: 1}, }, } index.messages["api.v1."+rpc.ResponseType] = respMsg } // Create User message user := &ProtoMessage{ Name: "User", FullName: "api.v1.User", Fields: []ProtoField{ {Name: "id", Type: "int32", Number: 1}, {Name: "name", Type: "string", Number: 2}, }, } index.messages["api.v1.User"] = user b.ResetTimer() for i := 0; i < b.N; i++ { index.resolveServiceTypes(service, 10) } } // BenchmarkGetMessageWithResolution benchmarks GetMessage with type resolution func BenchmarkGetMessageWithResolution(b *testing.B) { index := NewProtoIndex(testLogger()) // Create nested messages address := &ProtoMessage{ Name: "Address", FullName: "api.v1.Address", Fields: []ProtoField{ {Name: "street", Type: "string", Number: 1}, {Name: "city", Type: "string", Number: 2}, }, } user := &ProtoMessage{ Name: "User", FullName: "api.v1.User", Fields: []ProtoField{ {Name: "id", Type: "int32", Number: 1}, {Name: "name", Type: "string", Number: 2}, {Name: "address", Type: "Address", Number: 3}, }, } index.messages["api.v1.User"] = user index.messages["api.v1.Address"] = address b.ResetTimer() for i := 0; i < b.N; i++ { index.GetMessage("User", true, 10) } } // BenchmarkGetServiceWithResolution benchmarks GetService with type resolution func BenchmarkGetServiceWithResolution(b *testing.B) { index := NewProtoIndex(testLogger()) // Create service service := &ProtoService{ Name: "UserService", FullName: "api.v1.UserService", RPCs: []ProtoRPC{ {Name: "GetUser", RequestType: "GetUserRequest", ResponseType: "GetUserResponse"}, }, } request := &ProtoMessage{ Name: "GetUserRequest", FullName: "api.v1.GetUserRequest", Fields: []ProtoField{ {Name: "id", Type: "int32", Number: 1}, }, } response := &ProtoMessage{ Name: "GetUserResponse", FullName: "api.v1.GetUserResponse", Fields: []ProtoField{ {Name: "user", Type: "User", Number: 1}, }, } user := &ProtoMessage{ Name: "User", FullName: "api.v1.User", Fields: []ProtoField{ {Name: "id", Type: "int32", Number: 1}, {Name: "name", Type: "string", Number: 2}, }, } index.services["api.v1.UserService"] = service index.messages["api.v1.GetUserRequest"] = request index.messages["api.v1.GetUserResponse"] = response index.messages["api.v1.User"] = user b.ResetTimer() for i := 0; i < b.N; i++ { index.GetService("UserService", true, 10) } } // BenchmarkMessageToMap benchmarks message serialization func BenchmarkMessageToMap(b *testing.B) { index := NewProtoIndex(testLogger()) msg := &ProtoMessage{ Name: "User", FullName: "api.v1.User", Fields: []ProtoField{ {Name: "id", Type: "int32", Number: 1}, {Name: "name", Type: "string", Number: 2}, {Name: "email", Type: "string", Number: 3}, {Name: "age", Type: "int32", Number: 4}, {Name: "active", Type: "bool", Number: 5}, }, } b.ResetTimer() for i := 0; i < b.N; i++ { index.messageToMap(msg) } } // BenchmarkEnumToMap benchmarks enum serialization func BenchmarkEnumToMap(b *testing.B) { index := NewProtoIndex(testLogger()) enum := &ProtoEnum{ Name: "Status", FullName: "api.v1.Status", Values: []ProtoField{ {Name: "UNKNOWN", Number: 0}, {Name: "ACTIVE", Number: 1}, {Name: "INACTIVE", Number: 2}, {Name: "PENDING", Number: 3}, {Name: "DELETED", Number: 4}, }, } b.ResetTimer() for i := 0; i < b.N; i++ { index.enumToMap(enum) } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/umuterturk/mcp-proto'

If you have feedback or need assistance with the MCP directory API, please join our Discord server