我是 GCP Pub/Sub 的新手,我尝试测试发布消息的基准。
我们有以下两种情况:
两种场景都会发布 6 条消息。
场景一:创建pubsubClient,然后向pubsub发布6条消息。之后杀死客户端。
场景2:对于每条消息,创建新的pubcubclient,消息发布后关闭客户端。
基准代码可以在下面找到:
func BenchmarkPublish(b *testing.B) {
os.Setenv("PUBSUB_EMULATOR_HOST", "localhost:8085")
ctx := context.Background()
client, err := pubsub.NewClient(ctx, ProjectID)
if err != nil {
log.Fatalln("can't create client: ", err)
}
defer client.Close()
topic := client.Topic(TopicID)
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, fruit := range fruits {
err := Publish(os.Stdout, ctx, TopicID, topic, fruit)
if err != nil {
log.Fatalln("can't publish message: ", err)
}
}
}
}
func BenchmarkPublishAndKillConnectionEachTime(b *testing.B) {
os.Setenv("PUBSUB_EMULATOR_HOST", "localhost:8085")
ctx := context.Background()
b.ResetTimer()
for i := 0; i < b.N; i++ {
for _, fruit := range fruits {
client, err := pubsub.NewClient(ctx, ProjectID)
if err != nil {
log.Fatalln("can't create client: ", err)
}
topic := client.Topic(TopicID)
err = Publish(os.Stdout, ctx, TopicID, topic, fruit)
if err != nil {
log.Fatalln("can't publish message: ", err)
}
client.Close()
}
}
}
这是发布功能:
func Publish(w io.Writer, ctx context.Context, topicID string, t *pubsub.Topic, msg string) error {
// projectID := "my-project-id"
// topicID := "my-topic"
// msg := "Hello World"
result := t.Publish(ctx, &pubsub.Message{
Data: []byte(msg),
})
id, err := result.Get(ctx)
if err != nil {
return fmt.Errorf("pubsub: result.Get: %w", err)
}
fmt.Fprintf(w, "Published a message; msg ID: %v\n", id)
return nil
}
在我看来,
BenchmarkPublish
应该比BenchmarkPublishAndKillConnectionEachTime
跑得更快。但实际上 BenchmarkPublish
速度较慢。
这是基准:
我的问题是为什么每次杀死连接的基准比使用单连接更好?在我看来,如果我们创建并关闭客户端,它应该消耗一些计算资源。因此,在所有发布操作完成之前,它应该比维护 PubsubClient 慢。
文档说:
Publish 异步向主题发布消息。消息是 根据主题的 PublishSettings 进行批量发送。 发布 永远不会阻塞。
[...]
Publish 创建用于批处理和发送消息的 goroutine。这些 goroutine 需要通过调用 t.Stop() 来停止。
这意味着你正在泄漏 goroutine,在第二种情况下比第一种情况更多。您没有比较发送时间,在第一个示例中发送将是批量的。