update benchmark

This commit is contained in:
兔子 2025-08-21 21:37:21 +08:00
parent 67b0025f9c
commit 4e154cc17b
Signed by: b612
GPG Key ID: 99DD2222B612B612
3 changed files with 211 additions and 10 deletions

21
curl.go
View File

@ -277,7 +277,7 @@ type RequestOpts struct {
contentLength int64 // 人工设置
}
func (r *RequestOpts) ContentLength() int64 {
func (r *Request) ContentLength() int64 {
return r.contentLength
}
@ -286,24 +286,27 @@ func (r *RequestOpts) ContentLength() int64 {
// if the length is less than 0, it will not set the Content-Length header. chunked transfer encoding will be used instead.
// chunked transfer encoding may cause some servers to reject the request if they do not support it.
// Note that this function will not work if doRawRequest is true
func (r *RequestOpts) SetContentLength(contextLength int64) {
func (r *Request) SetContentLength(contextLength int64) *Request {
r.contentLength = contextLength
return r
}
func (r *RequestOpts) CustomTransport() bool {
func (r *Request) CustomTransport() bool {
return r.customTransport
}
func (r *RequestOpts) SetCustomTransport(customTransport bool) {
func (r *Request) SetCustomTransport(customTransport bool) *Request {
r.customTransport = customTransport
return r
}
func (r *RequestOpts) FileUploadRecallFn() func(filename string, upPos int64, total int64) {
func (r *Request) FileUploadRecallFn() func(filename string, upPos int64, total int64) {
return r.fileUploadRecallFn
}
func (r *RequestOpts) SetFileUploadRecallFn(FileUploadRecallFn func(filename string, upPos int64, total int64)) {
func (r *Request) SetFileUploadRecallFn(FileUploadRecallFn func(filename string, upPos int64, total int64)) *Request {
r.fileUploadRecallFn = FileUploadRecallFn
return r
}
func (r *Request) DialFn() func(ctx context.Context, network, addr string) (net.Conn, error) {
@ -338,13 +341,13 @@ func (r *Request) SetAutoCalcContentLengthNoError(autoCalcContentLength bool) *R
}
// BasicAuth returns the username and password provided in the request's Authorization header.
func (r *RequestOpts) BasicAuth() (string, string) {
func (r *Request) BasicAuth() (string, string) {
return r.basicAuth[0], r.basicAuth[1]
}
// SetBasicAuth sets the request's Authorization header to use HTTP Basic Authentication with the provided username and password.
// Note: If doRawRequest is true, this function will nolonger work
func (r *RequestOpts) SetBasicAuth(username, password string) *RequestOpts {
func (r *Request) SetBasicAuth(username, password string) *Request {
r.basicAuth = [2]string{username, password}
return r
}
@ -687,7 +690,7 @@ func (r *Request) SetDoRawRequest(doRawRequest bool) *Request {
}
// SkipTLSVerify returns whether the request will skip TLS verification.
func (r *RequestOpts) SkipTLSVerify() bool {
func (r *Request) SkipTLSVerify() bool {
return r.skipTLSVerify
}

View File

@ -90,7 +90,7 @@ func TestGetRequest(t *testing.T) {
}))
defer server.Close()
resp, err := Get(server.URL)
resp, err := Get(server.URL, WithSkipTLSVerify(true), WithHeader("hello", "world"), WithUserAgent("hello world"))
if err != nil {
t.Errorf("Unexpected error: %v", err)
}

198
curlbench_test.go Normal file
View File

@ -0,0 +1,198 @@
package starnet
import (
"fmt"
"net/http"
"net/http/httptest"
"runtime"
"testing"
)
// BenchmarkGetRequest 测试单个 GET 请求的性能
func BenchmarkGetRequest(b *testing.B) {
// 创建测试服务器
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte(`OK`))
}))
defer server.Close()
// 重置计时器,排除设置代码的影响
b.ResetTimer()
// 报告内存分配情况
b.ReportAllocs()
// 运行基准测试
for i := 0; i < b.N; i++ {
resp, err := Get(server.URL, WithSkipTLSVerify(true))
if err != nil {
b.Errorf("Unexpected error: %v", err)
}
body := resp.Body().String()
if body != "OK" {
b.Errorf("Expected OK, got %v", body)
}
}
}
// BenchmarkGetRequestWithHeaders 测试带请求头的 GET 请求性能
func BenchmarkGetRequestWithHeaders(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
// 验证请求头
if req.Header.Get("hello") != "world" {
rw.WriteHeader(http.StatusBadRequest)
return
}
rw.Write([]byte(`OK`))
}))
defer server.Close()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
resp, err := Get(server.URL,
WithSkipTLSVerify(true),
WithHeader("hello", "world"),
WithUserAgent("hello world"))
if err != nil {
b.Errorf("Unexpected error: %v", err)
}
body := resp.Body().String()
if body != "OK" {
b.Errorf("Expected OK, got %v", body)
}
}
}
// BenchmarkPostRequest 测试 POST 请求的性能
func BenchmarkPostRequest(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
// 读取并返回请求体
body := make([]byte, req.ContentLength)
req.Body.Read(body)
rw.Write(body)
}))
defer server.Close()
testData := "This is a test payload for POST request"
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
resp, err := Post(server.URL,
WithSkipTLSVerify(true),
WithBytes([]byte(testData)),
WithContentType("text/plain"))
if err != nil {
b.Errorf("Unexpected error: %v", err)
}
body := resp.Body().String()
if body != testData {
b.Errorf("Expected %s, got %v", testData, body)
}
}
}
// BenchmarkConcurrentRequests 测试并发请求性能
func BenchmarkConcurrentRequests(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte(`OK`))
}))
defer server.Close()
b.ResetTimer()
b.ReportAllocs()
// 运行并发基准测试
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
resp, err := Get(server.URL, WithSkipTLSVerify(true))
if err != nil {
b.Errorf("Unexpected error: %v", err)
}
body := resp.Body().String()
if body != "OK" {
b.Errorf("Expected OK, got %v", body)
}
}
})
}
// BenchmarkMemoryUsage 专门测试内存使用情况
func BenchmarkMemoryUsage(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Write([]byte(`OK`))
}))
defer server.Close()
// 禁用默认的测试时间,只关注内存分配
b.ReportAllocs()
var memStatsStart, memStatsEnd runtime.MemStats
runtime.GC()
runtime.ReadMemStats(&memStatsStart)
for i := 0; i < b.N; i++ {
resp, err := Get(server.URL, WithSkipTLSVerify(true))
if err != nil {
b.Errorf("Unexpected error: %v", err)
}
body := resp.Body().String()
if body != "OK" {
b.Errorf("Expected OK, got %v", body)
}
}
runtime.GC()
runtime.ReadMemStats(&memStatsEnd)
// 计算每次操作的平均内存分配
allocsPerOp := float64(memStatsEnd.Mallocs-memStatsStart.Mallocs) / float64(b.N)
bytesPerOp := float64(memStatsEnd.TotalAlloc-memStatsStart.TotalAlloc) / float64(b.N)
b.ReportMetric(allocsPerOp, "allocs/op")
b.ReportMetric(bytesPerOp, "bytes/op")
}
// BenchmarkDifferentResponseSizes 测试不同响应大小的性能
func BenchmarkDifferentResponseSizes(b *testing.B) {
// 测试不同大小的响应
responseSizes := []int{100, 1024, 10240, 102400} // 100B, 1KB, 10KB, 100KB
for _, size := range responseSizes {
// 生成指定大小的响应数据
responseData := make([]byte, size)
for i := 0; i < size; i++ {
responseData[i] = 'A'
}
b.Run(fmt.Sprintf("Size_%d", size), func(b *testing.B) {
server := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
rw.Write(responseData)
}))
defer server.Close()
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
resp, err := Get(server.URL, WithSkipTLSVerify(true))
if err != nil {
b.Errorf("Unexpected error: %v", err)
}
body := resp.Body().Bytes()
if len(body) != size {
b.Errorf("Expected size %d, got %d", size, len(body))
}
}
})
}
}