Hertz : 探究 dst 在 Get()/Post() 中的作用方式 - konakona
konakona
Dream Afar.
konakona

Hertz : 探究 dst 在 Get()/Post() 中的作用方式

先来看官方文档的说明,这是常人无法看懂的地步啊!🤣

https://blog.img.crazyphper.com/2024/08/image.png
几乎无法看懂 dst 到底能做什么!更别提理解它的存在意义了

最常见的做法是传入一个 nildst 里,连官网的示例也是如此。

本着追求卓越不断探索的精神,我深入研究了 Hertz 的底层代码,终于找到了问题的关键。现在让我带你一步步理解 dst 的作用。


深入分析 client.doRequestFollowRedirectsBuffer()

让我们直接分析doRequestFollowRedirectsBuffer()方法,Get()Post() 的形参 dst 最终会流经这个方法。

func doRequestFollowRedirectsBuffer(ctx context.Context, req *protocol.Request, dst []byte, url string, c Doer) (statusCode int, body []byte, err error) {
	resp := protocol.AcquireResponse()
	bodyBuf := resp.BodyBuffer()
	oldBody := bodyBuf.B
	bodyBuf.B = dst

	statusCode, _, err = DoRequestFollowRedirects(ctx, req, resp, url, defaultMaxRedirectsCount, c)

	// In HTTP2 scenario, client use stream mode to create a request and its body is in body stream.
	// In HTTP1, only client recv body exceed max body size and client is in stream mode can trig it.
	body = resp.Body()
	bodyBuf.B = oldBody
	protocol.ReleaseResponse(resp)

	return statusCode, body, err
}

是不是有点儿懵?乍看之下你可能会有以下疑问:

  • dst 传入后似乎没有被显性使用
  • bodyBuf.B 获得 dst 的值传递后,但在哪里使用了bodyBuf 呢?

关键点分析

关键在于 bodyBuf := resp.BodyBuffer() 会返回一个 *bytebufferpool.ByteBuffer。在这段代码中,dst 被传入并赋值给 bodyBuf.B。这是为了让响应的数据直接写入到外部供给的 dst 缓冲区,而不是使用默认的缓冲区。这种做法实际上是一种优化内存使用的策略 —— 知晓这一特性就好,通常来说在小型应用中我们也就用个 nil 🤣

赋值完成后,DoRequestFollowRedirects() 函数被调用,它负责处理请求和可能的重定向。尽管代码中没有直接操作 bodyBuf.B,但所有的响应数据都会被写入 bodyBuf.B,而此时 bodyBuf.B 引用了传入的 dst。这意味着 dst 已经在 DoRequestFollowRedirects() 的内部被利用

最后,代码将 bodyBuf.B 恢复为原来的 oldBody,这是为了确保函数调用结束后 resp.BodyBuffer() 的状态保持不变,以防后续操作依赖于其初始状态。

总结一下!

📖 dst 和 bodyBuf.B 没有被显式调用,但实际上,它们在 DoRequestFollowRedirects 函数内部起到了关键作用。

📖 通过将dst 赋值给 bodyBuf.B 来让数据写入外部缓冲区。这是一种内存优化策略。

什么情况/场景下有必要传dst 呢?

通常来说,小型程序或者不考虑复用缓冲区的程序 dst 只需要设为 nil,但在下面这些场景下传递外部缓冲区可以带来明显的优势:

  • 缓冲区复用:在循环或批量处理 HTTP 请求的场景中,复用一个缓冲区来存储响应数据可以避免每次请求都创建新的 []byte,从而显著降低内存使用和分配时间。
  • 高并发和大数据场景:在这些场景中,减少内存分配操作可以提高性能。
  • 性能优化需求:在性能要求极高的应用中,开发者可以通过显式管理内存分配和缓冲区来优化性能。通过传入 dst,可以更精细地控制内存的使用,避免不必要的内存分配和复制。
赞赏

团哥

文章作者

继续玩我的CODE,让别人说去。 低调,就是这么自信。

konakona

Hertz : 探究 dst 在 Get()/Post() 中的作用方式
为什么hertz的技术文档不能写好一点儿呢?
扫描二维码继续阅读
2024-08-11