diff options
Diffstat (limited to 'benchmarks/s3ttfb/main.go')
-rw-r--r-- | benchmarks/s3ttfb/main.go | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/benchmarks/s3ttfb/main.go b/benchmarks/s3ttfb/main.go new file mode 100644 index 0000000..b5cf033 --- /dev/null +++ b/benchmarks/s3ttfb/main.go @@ -0,0 +1,214 @@ +package main + +import ( + "context" + "crypto/tls" + "fmt" + "io" + "io/ioutil" + "log" + "math/rand" + "net/http" + "net/http/httptrace" + "os" + "strconv" + "time" + + "github.com/google/uuid" + "github.com/minio/minio-go/v7" + "github.com/minio/minio-go/v7/pkg/credentials" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/s3" +) + +type PRNG struct { + rem int64 +} + +func (r *PRNG) Read(p []byte) (n int, err error) { + //log.Printf("rem=%d, buf=%d\n", r.rem, len(p)) + if int64(len(p)) > r.rem { + p = p[:r.rem] + } + + if int64(len(p)) > r.rem { + log.Fatal("LOGIC ERROR") + } + + n, err = rand.Read(p) + if err != nil { + return + } + r.rem -= int64(n) + if r.rem <= 0 { + err = io.EOF + //log.Printf("PRNG file has been fully read. rem=%d,n=%d,err=%s\n", r.rem, n, err) + } + return +} + +func main() { + var err error + fmt.Printf("nanoseconds\n") + + // Initial setup + _, isSSL := os.LookupEnv("SSL") + opts := minio.Options{ + Creds: credentials.NewStaticV4(os.Getenv("AWS_ACCESS_KEY_ID"), os.Getenv("AWS_SECRET_ACCESS_KEY"), ""), + Secure: isSSL, + } + + if region, ok := os.LookupEnv("AWS_REGION"); ok { + opts.Region = region + } + + if _, ok := os.LookupEnv("SSL_INSECURE"); ok { + opts.Transport = &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}} + } + + size := 1 * 1024 * 1024 // 1 MB + if env_size, ok := os.LookupEnv("SIZE"); ok { + size, err = strconv.Atoi(env_size) + if err != nil { + log.Fatal(err) + return + } + } + + repeat := 60 + if env_repeat, ok := os.LookupEnv("REPEAT"); ok { + repeat, err = strconv.Atoi(env_repeat) + if err != nil { + log.Fatal(err) + return + } + } + + mc, err := minio.New(os.Getenv("ENDPOINT"), &opts) + if err != nil { + log.Fatal("failed connect", err) + return + } + + // AWS SDK stuff + customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) { + return aws.Endpoint{ + PartitionID: "aws", + URL: "http://"+os.Getenv("ENDPOINT"), + SigningRegion: region, + }, nil + }) + + + cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithEndpointResolverWithOptions(customResolver)) + if err != nil { + log.Fatalf("failed to load configuration, %v", err) + } + + // Create an Amazon S3 service client + client := s3.NewFromConfig(cfg, func(opts *s3.Options) { + opts.UsePathStyle = true + }) + + + // Create Bucket + buck := uuid.New().String() + err = mc.MakeBucket(context.Background(), buck, minio.MakeBucketOptions{}) + if err != nil { + log.Fatal(err) + return + } + + // Send an object + prng := new(PRNG) + prng.rem = int64(size) + + + key := uuid.New().String() + _, err = mc.PutObject( + context.Background(), + buck, + key, + prng, + int64(size), + minio.PutObjectOptions{ContentType: "application/octet-stream"}, + ) + if err != nil { + log.Fatal("unable to upload our test object") + return + } + + for i := 0; i < repeat; i++ { + // Now, try to fetch it *repeat* times (assume no caching) + var elapsed time.Duration + + var start time.Time + trace := &httptrace.ClientTrace{ + GotFirstResponseByte: func() { elapsed = time.Since(start) }, + } + + start = time.Now() + /*object, err := mc.GetObject(httptrace.WithClientTrace(context.Background(), trace), buck, key, minio.GetObjectOptions{}) + if err != nil { + log.Fatal(err) + return + }*/ + + out, err := client.GetObject(httptrace.WithClientTrace(context.Background(), trace), &s3.GetObjectInput { + Bucket: aws.String(buck), + Key: aws.String(key), + }) + if err != nil { + log.Fatal(err) + return + } + object := out.Body + + + if _, err = io.Copy(ioutil.Discard, object) ; err != nil { + log.Fatal("failed getobject: ", err) + return + } + + fmt.Printf("%v\n", elapsed.Nanoseconds()) + //time.Sleep(10 * time.Second) + } +} + +/* +func timeGet(url string) { + req, _ := http.NewRequest("GET", url, nil) + + var start, connect, dns, tlsHandshake time.Time + + trace := &httptrace.ClientTrace{ + DNSStart: func(dsi httptrace.DNSStartInfo) { dns = time.Now() }, + DNSDone: func(ddi httptrace.DNSDoneInfo) { + fmt.Printf("DNS Done: %v\n", time.Since(dns)) + }, + + TLSHandshakeStart: func() { tlsHandshake = time.Now() }, + TLSHandshakeDone: func(cs tls.ConnectionState, err error) { + fmt.Printf("TLS Handshake: %v\n", time.Since(tlsHandshake)) + }, + + ConnectStart: func(network, addr string) { connect = time.Now() }, + ConnectDone: func(network, addr string, err error) { + fmt.Printf("Connect time: %v\n", time.Since(connect)) + }, + + GotFirstResponseByte: func() { + fmt.Printf("Time from start to first byte: %v\n", time.Since(start)) + }, + } + + req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace)) + start = time.Now() + if _, err := http.DefaultTransport.RoundTrip(req); err != nil { + log.Fatal(err) + } + fmt.Printf("Total time: %v\n", time.Since(start)) +} +*/ |