mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-08-06 17:40:57 +00:00
615 lines
16 KiB
Go
615 lines
16 KiB
Go
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package httplib
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"forgejo.org/modules/proxy"
|
|
"forgejo.org/modules/setting"
|
|
)
|
|
|
|
func BenchmarkClientPoolGetClient(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
client := pool.GetClient("benchmark_test")
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkClientPoolConcurrentAccess(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
i := 0
|
|
for pb.Next() {
|
|
key := fmt.Sprintf("benchmark_key_%d", i%10)
|
|
client := pool.GetClient(key)
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
i++
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkClientPoolWithHTTPRequests(b *testing.B) {
|
|
// Create a test server
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("OK"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
client := pool.GetClient("http_benchmark")
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
resp, err := client.Get(server.URL)
|
|
if err != nil {
|
|
b.Fatalf("Failed to make HTTP request: %v", err)
|
|
}
|
|
resp.Body.Close()
|
|
if resp.StatusCode != http.StatusOK {
|
|
b.Fatalf("Expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkClientPoolWithTimeout(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
client := pool.GetClientWithTimeout("timeout_benchmark", 5*time.Second)
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkClientPoolWithTLS(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
tlsConfig := &tls.Config{InsecureSkipVerify: true}
|
|
client := pool.GetClientWithTLS("tls_benchmark", tlsConfig)
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkTraditionalHTTPClient(b *testing.B) {
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
MaxIdleConns: 100,
|
|
MaxIdleConnsPerHost: 10,
|
|
IdleConnTimeout: 60 * time.Second,
|
|
},
|
|
Timeout: 30 * time.Second,
|
|
}
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkClientPoolMemoryUsage(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
// Pre-create clients to test memory usage
|
|
clients := make([]*http.Client, 1000)
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
for j := 0; j < 1000; j++ {
|
|
clients[j] = pool.GetClient(fmt.Sprintf("memory_test_%d", j))
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkClientPoolConnectionReuse(b *testing.B) {
|
|
// Create a test server
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("OK"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
client := pool.GetClient("connection_reuse_benchmark")
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
resp, err := client.Get(server.URL)
|
|
if err != nil {
|
|
b.Fatalf("Failed to make HTTP request: %v", err)
|
|
}
|
|
resp.Body.Close()
|
|
if resp.StatusCode != http.StatusOK {
|
|
b.Fatalf("Expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkClientPoolMixedOperations(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
i := 0
|
|
for pb.Next() {
|
|
switch i % 4 {
|
|
case 0:
|
|
client := pool.GetClient(fmt.Sprintf("mixed_test_%d", i))
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
case 1:
|
|
client := pool.GetClientWithTimeout(fmt.Sprintf("mixed_timeout_%d", i), 5*time.Second)
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
case 2:
|
|
tlsConfig := &tls.Config{InsecureSkipVerify: true}
|
|
client := pool.GetClientWithTLS(fmt.Sprintf("mixed_tls_%d", i), tlsConfig)
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
case 3:
|
|
client := GetDefaultClient()
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
i++
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkClientPoolStressTest(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
// Create multiple goroutines to stress test the pool
|
|
var wg sync.WaitGroup
|
|
numGoroutines := 100
|
|
clientsPerGoroutine := 100
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
wg.Add(numGoroutines)
|
|
for g := 0; g < numGoroutines; g++ {
|
|
go func(goroutineID int) {
|
|
defer wg.Done()
|
|
for j := 0; j < clientsPerGoroutine; j++ {
|
|
key := fmt.Sprintf("stress_test_%d_%d", goroutineID, j)
|
|
client := pool.GetClient(key)
|
|
if client == nil {
|
|
b.Errorf("Expected non-nil client for key: %s", key)
|
|
}
|
|
}
|
|
}(g)
|
|
}
|
|
wg.Wait()
|
|
}
|
|
}
|
|
|
|
func BenchmarkClientPoolCloseAndRecreate(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
// Get some clients
|
|
client1 := pool.GetClient("close_test1")
|
|
client2 := pool.GetClient("close_test2")
|
|
|
|
if client1 == nil || client2 == nil {
|
|
b.Fatal("Expected non-nil clients")
|
|
}
|
|
|
|
// Close the pool
|
|
pool.Close()
|
|
|
|
// Get clients again (should be recreated)
|
|
client3 := pool.GetClient("close_test1")
|
|
client4 := pool.GetClient("close_test2")
|
|
|
|
if client3 == nil || client4 == nil {
|
|
b.Fatal("Expected non-nil clients after close")
|
|
}
|
|
}
|
|
}
|
|
|
|
// Direct comparison benchmarks - Old vs New behavior
|
|
|
|
func BenchmarkOldWayCreateClient(b *testing.B) {
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
// Old way: Create new client every time
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
Proxy: proxy.Proxy(),
|
|
MaxIdleConns: 100,
|
|
MaxIdleConnsPerHost: 10,
|
|
IdleConnTimeout: 60 * time.Second,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
ForceAttemptHTTP2: true,
|
|
},
|
|
Timeout: 30 * time.Second,
|
|
}
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkNewWayGetClient(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
// New way: Get client from pool
|
|
client := pool.GetClient("benchmark_comparison")
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkOldWayMultipleRequests(b *testing.B) {
|
|
// Create a test server
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("OK"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
// Old way: Create new client for each request
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
Proxy: proxy.Proxy(),
|
|
MaxIdleConns: 100,
|
|
MaxIdleConnsPerHost: 10,
|
|
IdleConnTimeout: 60 * time.Second,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
ForceAttemptHTTP2: true,
|
|
},
|
|
Timeout: 30 * time.Second,
|
|
}
|
|
|
|
resp, err := client.Get(server.URL)
|
|
if err != nil {
|
|
b.Fatalf("Failed to make HTTP request: %v", err)
|
|
}
|
|
resp.Body.Close()
|
|
if resp.StatusCode != http.StatusOK {
|
|
b.Fatalf("Expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkNewWayMultipleRequests(b *testing.B) {
|
|
// Create a test server
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("OK"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
client := pool.GetClient("multiple_requests_comparison")
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
// New way: Reuse client from pool
|
|
resp, err := client.Get(server.URL)
|
|
if err != nil {
|
|
b.Fatalf("Failed to make HTTP request: %v", err)
|
|
}
|
|
resp.Body.Close()
|
|
if resp.StatusCode != http.StatusOK {
|
|
b.Fatalf("Expected status 200, got %d", resp.StatusCode)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkOldWayConcurrentClients(b *testing.B) {
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
i := 0
|
|
for pb.Next() {
|
|
// Old way: Create different clients for different services
|
|
key := fmt.Sprintf("service_%d", i%10)
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
Proxy: proxy.Proxy(),
|
|
MaxIdleConns: 100,
|
|
MaxIdleConnsPerHost: 10,
|
|
IdleConnTimeout: 60 * time.Second,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
ForceAttemptHTTP2: true,
|
|
},
|
|
Timeout: 30 * time.Second,
|
|
}
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
_ = key // Use key to simulate different service types
|
|
i++
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkNewWayConcurrentClients(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
i := 0
|
|
for pb.Next() {
|
|
// New way: Get different clients from pool
|
|
key := fmt.Sprintf("service_%d", i%10)
|
|
client := pool.GetClient(key)
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
i++
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkOldWayWithTimeout(b *testing.B) {
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
// Old way: Create client with custom timeout
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
Proxy: proxy.Proxy(),
|
|
MaxIdleConns: 100,
|
|
MaxIdleConnsPerHost: 10,
|
|
IdleConnTimeout: 60 * time.Second,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
ForceAttemptHTTP2: true,
|
|
},
|
|
Timeout: 5 * time.Second, // Custom timeout
|
|
}
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkNewWayWithTimeout(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
// New way: Get client with custom timeout
|
|
client := pool.GetClientWithTimeout("timeout_comparison", 5*time.Second)
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkOldWayWithTLS(b *testing.B) {
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
// Old way: Create client with TLS config
|
|
tlsConfig := &tls.Config{InsecureSkipVerify: true}
|
|
client := &http.Client{
|
|
Transport: &http.Transport{
|
|
Proxy: proxy.Proxy(),
|
|
MaxIdleConns: 100,
|
|
MaxIdleConnsPerHost: 10,
|
|
IdleConnTimeout: 60 * time.Second,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
ForceAttemptHTTP2: true,
|
|
TLSClientConfig: tlsConfig,
|
|
},
|
|
Timeout: 30 * time.Second,
|
|
}
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkNewWayWithTLS(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
b.ResetTimer()
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
for pb.Next() {
|
|
// New way: Get client with TLS config
|
|
tlsConfig := &tls.Config{InsecureSkipVerify: true}
|
|
client := pool.GetClientWithTLS("tls_comparison", tlsConfig)
|
|
if client == nil {
|
|
b.Fatal("Expected non-nil client")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkOldWayMemoryUsage(b *testing.B) {
|
|
// Pre-create clients to test memory usage
|
|
clients := make([]*http.Client, 1000)
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
for j := 0; j < 1000; j++ {
|
|
// Old way: Create new client for each key
|
|
clients[j] = &http.Client{
|
|
Transport: &http.Transport{
|
|
Proxy: proxy.Proxy(),
|
|
MaxIdleConns: 100,
|
|
MaxIdleConnsPerHost: 10,
|
|
IdleConnTimeout: 60 * time.Second,
|
|
TLSHandshakeTimeout: 10 * time.Second,
|
|
ExpectContinueTimeout: 1 * time.Second,
|
|
ForceAttemptHTTP2: true,
|
|
},
|
|
Timeout: 30 * time.Second,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkNewWayMemoryUsage(b *testing.B) {
|
|
// Initialize settings for benchmarking
|
|
setting.HTTPClient.MaxIdleConns = 100
|
|
setting.HTTPClient.MaxIdleConnsPerHost = 10
|
|
setting.HTTPClient.IdleConnTimeout = 60 * time.Second
|
|
setting.HTTPClient.DefaultTimeout = 30 * time.Second
|
|
|
|
pool := GetGlobalClientPool()
|
|
|
|
// Pre-create clients to test memory usage
|
|
clients := make([]*http.Client, 1000)
|
|
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
for j := 0; j < 1000; j++ {
|
|
// New way: Get client from pool (shared instances)
|
|
clients[j] = pool.GetClient(fmt.Sprintf("memory_test_%d", j))
|
|
}
|
|
}
|
|
}
|