aboutsummaryrefslogtreecommitdiff
path: root/benchmarks/s3ttfb/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'benchmarks/s3ttfb/main.go')
-rw-r--r--benchmarks/s3ttfb/main.go214
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))
+}
+*/