This is an automated email from the ASF dual-hosted git repository.

yuchanns pushed a commit to branch benchmark-go-binding
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit bd71aa13b25fa7770903dde01a8b01654e8e47d9
Author: Hanchin Hsieh <m...@yuchanns.xyz>
AuthorDate: Sat Jun 28 18:38:59 2025 +0800

    feat(bindings/go): add comprehensive benchmark testing with Makefile target 
and CI integration
    
    - Add 'bench' target to Go bindings Makefile for running performance 
benchmarks
    - Enhance benchmark tests to compare OpenDAL performance against AWS S3 SDK
    - Integrate benchmark execution into CI pipeline for S3 service testing
    - Update help documentation to include new benchmark target usage examples
---
 .../actions/test_behavior_binding_go/action.yaml   |   3 +
 bindings/go/Makefile                               |  13 +-
 bindings/go/tests/behavior_tests/benchmark_test.go | 150 ++++++++++++++++-----
 bindings/go/tests/behavior_tests/go.mod            |   4 +
 bindings/go/tests/behavior_tests/go.sum            |  14 +-
 bindings/go/tests/behavior_tests/scheme_test.go    |   3 +-
 6 files changed, 151 insertions(+), 36 deletions(-)

diff --git a/.github/actions/test_behavior_binding_go/action.yaml 
b/.github/actions/test_behavior_binding_go/action.yaml
index 21c9ef7e5..3f48d5674 100644
--- a/.github/actions/test_behavior_binding_go/action.yaml
+++ b/.github/actions/test_behavior_binding_go/action.yaml
@@ -47,6 +47,9 @@ runs:
               fi
               cp bindings/go/Makefile .
               make tests
+              if [ "${{ inputs.setup }}" == "0_minio_s3"]; then
+                make bench
+              fi
             env:
               OPENDAL_TEST: ${{ inputs.service }}
               CGO_ENABLE: 0
diff --git a/bindings/go/Makefile b/bindings/go/Makefile
index a415bc058..094b9356d 100644
--- a/bindings/go/Makefile
+++ b/bindings/go/Makefile
@@ -15,7 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-.PHONY: tests clean help check-env generate-services run-tests
+.PHONY: tests bench clean help check-env generate-services run-tests run-bench
 
 # Detect current OS and architecture
 OS := $(shell uname -s | tr '[:upper:]' '[:lower:]')
@@ -139,10 +139,19 @@ run-tests: generate-services
        @echo "Running behavior tests..."
        go test ./opendal/bindings/go/tests/behavior_tests -v -run TestBehavior
 
+# Run benchmarks
+run-bench: generate-services
+       @echo "Running benchmark tests..."
+       go test ./opendal/bindings/go/tests/behavior_tests -v -bench=. -run=^$$ 
-count=6 -benchmem
+
 # Main target: run all tests
 tests: check-env run-tests
        @echo "All tests completed successfully!"
 
+# Main target: run benchmarks only
+bench: check-env run-bench
+       @echo "All benchmarks completed successfully!"
+
 # Clean all generated files
 clean:
        @echo "Cleaning all generated files..."
@@ -157,6 +166,7 @@ clean:
 help:
        @echo "Available targets:"
        @echo "  tests        - Run all tests (requires OPENDAL_TEST 
environment variable)"
+       @echo "  bench        - Run benchmarks only (requires OPENDAL_TEST 
environment variable)"
        @echo "  clean        - Clean all generated files"
        @echo "  help         - Show this help message"
        @echo ""
@@ -165,4 +175,5 @@ help:
        @echo ""
        @echo "Example usage:"
        @echo "  OPENDAL_TEST=fs make tests"
+       @echo "  OPENDAL_TEST=fs make bench"
 
diff --git a/bindings/go/tests/behavior_tests/benchmark_test.go 
b/bindings/go/tests/behavior_tests/benchmark_test.go
index f38dabc5a..2becdc3b3 100644
--- a/bindings/go/tests/behavior_tests/benchmark_test.go
+++ b/bindings/go/tests/behavior_tests/benchmark_test.go
@@ -20,8 +20,17 @@
 package opendal_test
 
 import (
+       "bytes"
+       "fmt"
+       "io"
+       "os"
        "testing"
 
+       opendal "github.com/apache/opendal/bindings/go"
+       "github.com/aws/aws-sdk-go/aws"
+       "github.com/aws/aws-sdk-go/aws/credentials"
+       "github.com/aws/aws-sdk-go/aws/session"
+       "github.com/aws/aws-sdk-go/service/s3"
        "github.com/google/uuid"
 )
 
@@ -45,7 +54,92 @@ func (s Size) Bytes() uint64 {
        return uint64(s)
 }
 
-func runBenchmarkWrite(b *testing.B, size Size) {
+func (s Size) String() string {
+       switch {
+       case s >= MiB:
+               return fmt.Sprintf("%dMiB", s.Bytes()/MiB)
+       case s >= KiB:
+               return fmt.Sprintf("%dKiB", s.Bytes()/KiB)
+       default:
+               return fmt.Sprintf("%dB", s.Bytes())
+       }
+}
+
+var sizes = []Size{
+       fromKibibytes(4),
+       fromKibibytes(256),
+       fromMebibytes(4),
+       fromMebibytes(16),
+}
+
+type ReadWriter interface {
+       Write(path string, data []byte) error
+       Read(path string) ([]byte, error)
+
+       Name() string
+}
+
+type S3ReadWriter struct {
+       client *s3.S3
+}
+
+func NewS3ReadWriter() ReadWriter {
+       s3 := s3.New(session.Must(session.NewSession(&aws.Config{
+               Credentials: 
credentials.NewStaticCredentials(os.Getenv("OPENDAL_S3_ACCESS_KEY_ID"), 
os.Getenv("OPENDAL_S3_SECRET_ACCESS_KEY"), ""),
+               Endpoint:    aws.String(os.Getenv("OPENDAL_S3_ENDPOINT")),
+               Region:      aws.String(os.Getenv("OPENDAL_S3_BUCKET")),
+               DisableSSL:  aws.Bool(true),
+       })))
+       return &S3ReadWriter{
+               client: s3,
+       }
+}
+
+func (rw *S3ReadWriter) Write(path string, data []byte) error {
+       _, err := rw.client.PutObject(&s3.PutObjectInput{
+               Bucket: aws.String(os.Getenv("OPENDAL_S3_BUCKET")),
+               Key:    aws.String(path),
+               Body:   aws.ReadSeekCloser(bytes.NewReader(data)),
+       })
+       return err
+}
+
+func (rw *S3ReadWriter) Read(path string) ([]byte, error) {
+       resp, err := rw.client.GetObject(&s3.GetObjectInput{
+               Bucket: aws.String(os.Getenv("OPENDAL_S3_BUCKET")),
+               Key:    aws.String(path),
+       })
+       if err != nil {
+               return nil, err
+       }
+       defer resp.Body.Close()
+
+       data, err := io.ReadAll(resp.Body)
+       if err != nil {
+               return nil, err
+       }
+       return data, nil
+}
+
+func (rw *S3ReadWriter) Name() string {
+       return "AWS S3"
+}
+
+type OpenDALReadWriter struct {
+       *opendal.Operator
+}
+
+func NewOpenDALReadWriter(op *opendal.Operator) ReadWriter {
+       return &OpenDALReadWriter{
+               Operator: op,
+       }
+}
+
+func (rw *OpenDALReadWriter) Name() string {
+       return "OpenDAL"
+}
+
+func runBenchmarkWrite(b *testing.B, size Size, op ReadWriter) {
        path := uuid.NewString()
 
        data := genFixedBytes(uint(size.Bytes()))
@@ -60,23 +154,21 @@ func runBenchmarkWrite(b *testing.B, size Size) {
        }
 }
 
-func BenchmarkWrite4KiB(b *testing.B) {
-       runBenchmarkWrite(b, fromKibibytes(4))
-}
-
-func BenchmarkWrite256KiB(b *testing.B) {
-       runBenchmarkWrite(b, fromKibibytes(256))
-}
-
-func BenchmarkWrite4MiB(b *testing.B) {
-       runBenchmarkWrite(b, fromMebibytes(4))
-}
-
-func BenchmarkWrite16MiB(b *testing.B) {
-       runBenchmarkWrite(b, fromMebibytes(16))
+func BenchmarkWrite(b *testing.B) {
+       var ops = []ReadWriter{NewOpenDALReadWriter(op)}
+       if os.Getenv("OPENDAL_TEST") == "s3" {
+               ops = append(ops, NewS3ReadWriter())
+       }
+       for _, size := range sizes {
+               for _, op := range ops {
+                       b.Run(fmt.Sprintf("%s/%s", size, op.Name()), func(b 
*testing.B) {
+                               runBenchmarkWrite(b, size, op)
+                       })
+               }
+       }
 }
 
-func runBenchmarkRead(b *testing.B, size Size) {
+func runBenchmarkRead(b *testing.B, size Size, op ReadWriter) {
        path := uuid.NewString()
 
        data := genFixedBytes(uint(size.Bytes()))
@@ -97,18 +189,16 @@ func runBenchmarkRead(b *testing.B, size Size) {
        }
 }
 
-func BenchmarkRead4KiB(b *testing.B) {
-       runBenchmarkRead(b, fromKibibytes(4))
-}
-
-func BenchmarkRead256KiB(b *testing.B) {
-       runBenchmarkRead(b, fromKibibytes(256))
-}
-
-func BenchmarkRead4MiB(b *testing.B) {
-       runBenchmarkRead(b, fromMebibytes(4))
-}
-
-func BenchmarkRead16MiB(b *testing.B) {
-       runBenchmarkRead(b, fromMebibytes(16))
+func BenchmarkRead(b *testing.B) {
+       var ops = []ReadWriter{NewOpenDALReadWriter(op)}
+       if os.Getenv("OPENDAL_TEST") == "s3" {
+               ops = append(ops, NewS3ReadWriter())
+       }
+       for _, size := range sizes {
+               for _, op := range ops {
+                       b.Run(fmt.Sprintf("%s/%s", size, op.Name()), func(b 
*testing.B) {
+                               runBenchmarkRead(b, size, op)
+                       })
+               }
+       }
 }
diff --git a/bindings/go/tests/behavior_tests/go.mod 
b/bindings/go/tests/behavior_tests/go.mod
index fcaba00ec..e6662c2f3 100644
--- a/bindings/go/tests/behavior_tests/go.mod
+++ b/bindings/go/tests/behavior_tests/go.mod
@@ -22,6 +22,7 @@ go 1.22.5
 require (
        github.com/apache/opendal-go-services/fs v0.1.3
        github.com/apache/opendal/bindings/go v0.0.0-20240719044908-d9d4279b3a24
+       github.com/aws/aws-sdk-go v1.55.7
        github.com/google/uuid v1.6.0
        github.com/stretchr/testify v1.9.0
 )
@@ -29,9 +30,12 @@ require (
 require (
        github.com/davecgh/go-spew v1.1.1 // indirect
        github.com/ebitengine/purego v0.7.1 // indirect
+       github.com/jmespath/go-jmespath v0.4.0 // indirect
        github.com/jupiterrider/ffi v0.1.0-beta.9 // indirect
        github.com/klauspost/compress v1.17.10 // indirect
        github.com/pmezard/go-difflib v1.0.0 // indirect
        golang.org/x/sys v0.22.0 // indirect
        gopkg.in/yaml.v3 v3.0.1 // indirect
 )
+
+replace github.com/apache/opendal-go-services/fs => 
/Users/yuchanns/Coding/github/opendal_workspace/opendal-go-services/fs
diff --git a/bindings/go/tests/behavior_tests/go.sum 
b/bindings/go/tests/behavior_tests/go.sum
index d9f6957f1..c1473d33c 100644
--- a/bindings/go/tests/behavior_tests/go.sum
+++ b/bindings/go/tests/behavior_tests/go.sum
@@ -1,21 +1,25 @@
-github.com/apache/opendal-go-services/fs v0.1.3 
h1:k5pA73gKbQ3MHH2envsKhr1cec2spLm2tl/bCyU53j8=
-github.com/apache/opendal-go-services/fs v0.1.3/go.mod 
h1:7EnuyeXRuQh+L47rZ7y2OrhYJLlUYvgvFPItM98XJ5s=
-github.com/apache/opendal-go-services/memory v0.1.3 
h1:lUe4n4Y9AmwS6a1KV/ZTLyWLtWpRSSuNZHchcW2s+LQ=
-github.com/apache/opendal-go-services/memory v0.1.3/go.mod 
h1:vldOQuikErKA1wfGnqvjAYB9MON/PWTuFIulMCKIQqM=
 github.com/apache/opendal/bindings/go v0.0.0-20240719044908-d9d4279b3a24 
h1:2fAl+WS/lZMTtP6onlrmDbb3pltf+5xNTc0Aeu9nYWE=
 github.com/apache/opendal/bindings/go 
v0.0.0-20240719044908-d9d4279b3a24/go.mod 
h1:jyMN6M6h0jMDZitnjvB3KPobM+oZiESrFb3XUplLxhI=
+github.com/aws/aws-sdk-go v1.55.7 
h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE=
+github.com/aws/aws-sdk-go v1.55.7/go.mod 
h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
+github.com/davecgh/go-spew v1.1.0/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 
h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/ebitengine/purego v0.7.1 
h1:6/55d26lG3o9VCZX8lping+bZcmShseiqlh2bnUDiPA=
 github.com/ebitengine/purego v0.7.1/go.mod 
h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
 github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod 
h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/jmespath/go-jmespath v0.4.0 
h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
+github.com/jmespath/go-jmespath v0.4.0/go.mod 
h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1 
h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
+github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod 
h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
 github.com/jupiterrider/ffi v0.1.0-beta.9 
h1:HCeAPTsTFgwvcfavyJwy1L2ANz0c85W+ZE7LfzjZi3A=
 github.com/jupiterrider/ffi v0.1.0-beta.9/go.mod 
h1:sOp6VJGFaYyr4APi8gwy6g20QNHv5F8Iq1CVbtC900s=
 github.com/klauspost/compress v1.17.10 
h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0=
 github.com/klauspost/compress v1.17.10/go.mod 
h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
 github.com/pmezard/go-difflib v1.0.0 
h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod 
h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod 
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.9.0 
h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod 
h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/yuchanns/opendal-go-services v0.0.1 
h1:qeKv0mOhypQNm97g+u94DnijJK5bdEAp5pdjBGf8N7w=
@@ -24,5 +28,7 @@ golang.org/x/sys v0.22.0 
h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
 golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 
h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/bindings/go/tests/behavior_tests/scheme_test.go 
b/bindings/go/tests/behavior_tests/scheme_test.go
index 7702e1517..54134d8a0 100644
--- a/bindings/go/tests/behavior_tests/scheme_test.go
+++ b/bindings/go/tests/behavior_tests/scheme_test.go
@@ -16,12 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+// generated by github.com/apache/opendal/bindings/go
 
 package opendal_test
 
 import (
-       "github.com/apache/opendal-go-services/fs"
        opendal "github.com/apache/opendal/bindings/go"
+       "github.com/apache/opendal-go-services/fs"
 )
 
 // Add more schemes for behavior tests here.

Reply via email to