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)) } */