Browse Source

Update Go/fasthttp (use go modules, upgrade to pgx v4) (#5082)

* Update Go/fasthttp

* Add Go module configuration
* Upgrade to pgx v4 (fasthttp-postgresql)
* Batch update requests (fasthttp-postgresql)
* Remove jsonResponsePool, use a simple assignment as it's both faster and more realistic
* Do not copy a path string on routing

* Use the default NumCPU value if runtime.NumCPU returns 0
Vlad Glushchuk 5 years ago
parent
commit
3113f05ef9

+ 8 - 13
frameworks/Go/fasthttp/fasthttp-postgresql-prefork.dockerfile

@@ -1,21 +1,16 @@
-FROM golang:1.12
+FROM golang:1.13
 
-ADD ./ /fasthttp
 WORKDIR /fasthttp
 
-RUN mkdir bin
-ENV GOPATH /fasthttp
-ENV PATH ${GOPATH}/bin:${PATH}
+COPY ./src /fasthttp
 
-RUN rm -rf ./pkg/*
-RUN go get -d -u github.com/jackc/pgx
-RUN go get -d -u github.com/valyala/fasthttp/...
-RUN go get -u github.com/valyala/quicktemplate/qtc
+RUN go get github.com/valyala/quicktemplate/qtc
 RUN go get -u github.com/mailru/easyjson/...
+RUN go mod download
 
-RUN rm -f ./server-postgresql
-RUN go generate templates
+RUN go generate ./templates
+# RUN easyjson -pkg
 # RUN easyjson -all src/common/common.go
-RUN go build -gcflags='-l=4' server-postgresql
+RUN go build -o app-pg -gcflags='-l=4' -ldflags="-s -w" ./server-postgresql
 
-CMD ./server-postgresql -prefork
+CMD ./app-pg -prefork

+ 8 - 13
frameworks/Go/fasthttp/fasthttp-postgresql.dockerfile

@@ -1,21 +1,16 @@
-FROM golang:1.12
+FROM golang:1.13
 
-ADD ./ /fasthttp
 WORKDIR /fasthttp
 
-RUN mkdir bin
-ENV GOPATH /fasthttp
-ENV PATH ${GOPATH}/bin:${PATH}
+COPY ./src /fasthttp
 
-RUN rm -rf ./pkg/*
-RUN go get -d -u github.com/jackc/pgx
-RUN go get -d -u github.com/valyala/fasthttp/...
-RUN go get -u github.com/valyala/quicktemplate/qtc
+RUN go get github.com/valyala/quicktemplate/qtc
 RUN go get -u github.com/mailru/easyjson/...
+RUN go mod download
 
-RUN rm -f ./server-postgresql
-RUN go generate templates
+RUN go generate ./templates
+# RUN easyjson -pkg
 # RUN easyjson -all src/common/common.go
-RUN go build -gcflags='-l=4' server-postgresql
+RUN go build -o app-pg -gcflags='-l=4' -ldflags="-s -w" ./server-postgresql
 
-CMD ./server-postgresql
+CMD ./app-pg

+ 8 - 13
frameworks/Go/fasthttp/fasthttp-prefork.dockerfile

@@ -1,21 +1,16 @@
-FROM golang:1.12
+FROM golang:1.13
 
-ADD ./ /fasthttp
 WORKDIR /fasthttp
 
-RUN mkdir bin
-ENV GOPATH /fasthttp
-ENV PATH ${GOPATH}/bin:${PATH}
+COPY ./src /fasthttp
 
-RUN rm -rf ./pkg/*
-RUN go get -d -u github.com/go-sql-driver/mysql
-RUN go get -d -u github.com/valyala/fasthttp/...
-RUN go get -u github.com/valyala/quicktemplate/qtc
+RUN go get github.com/valyala/quicktemplate/qtc
 RUN go get -u github.com/mailru/easyjson/...
+RUN go mod download
 
-RUN rm -f ./server-mysql
-RUN go generate templates
+RUN go generate ./templates
+# RUN easyjson -pkg
 # RUN easyjson -all src/common/common.go
-RUN go build -gcflags='-l=4' server-mysql
+RUN go build -o app -gcflags='-l=4' -ldflags="-s -w" ./server-mysql
 
-CMD ./server-mysql -prefork
+CMD ./app -prefork

+ 8 - 13
frameworks/Go/fasthttp/fasthttp.dockerfile

@@ -1,21 +1,16 @@
-FROM golang:1.12
+FROM golang:1.13
 
-ADD ./ /fasthttp
 WORKDIR /fasthttp
 
-RUN mkdir bin
-ENV GOPATH /fasthttp
-ENV PATH ${GOPATH}/bin:${PATH}
+COPY ./src /fasthttp
 
-RUN rm -rf ./pkg/*
-RUN go get -d -u github.com/go-sql-driver/mysql
-RUN go get -d -u github.com/valyala/fasthttp/...
-RUN go get -u github.com/valyala/quicktemplate/qtc
+RUN go get github.com/valyala/quicktemplate/qtc
 RUN go get -u github.com/mailru/easyjson/...
+RUN go mod download
 
-RUN rm -f ./server-mysql
-RUN go generate templates
+RUN go generate ./templates
+# RUN easyjson -pkg
 # RUN easyjson -all src/common/common.go
-RUN go build -gcflags='-l=4' server-mysql
+RUN go build -o app -gcflags='-l=4' -ldflags="-s -w" ./server-mysql
 
-CMD ./server-mysql
+CMD ./app

+ 13 - 11
frameworks/Go/fasthttp/src/common/common.go

@@ -5,10 +5,10 @@ import (
 	"log"
 	"math/rand"
 	"net"
+	"runtime"
 	"sort"
-	"sync"
 
-	"templates"
+	"fasthttp/src/templates"
 
 	"github.com/valyala/fasthttp"
 )
@@ -27,9 +27,9 @@ type World struct {
 type Worlds []World
 
 func JSONHandler(ctx *fasthttp.RequestCtx) {
-	r := jsonResponsePool.Get().(*JSONResponse)
-	defer jsonResponsePool.Put(r)
-	r.Message = "Hello, World!"
+	r := JSONResponse{
+		Message: "Hello, World!",
+	}
 	rb, err := r.MarshalJSON()
 	if err != nil {
 		log.Println(err)
@@ -39,12 +39,6 @@ func JSONHandler(ctx *fasthttp.RequestCtx) {
 	ctx.Write(rb)
 }
 
-var jsonResponsePool = &sync.Pool{
-	New: func() interface{} {
-		return &JSONResponse{}
-	},
-}
-
 func PlaintextHandler(ctx *fasthttp.RequestCtx) {
 	ctx.SetContentType("text/plain")
 	ctx.WriteString("Hello, World!")
@@ -79,6 +73,14 @@ func GetListener(listenAddr string) net.Listener {
 	return ln
 }
 
+func NumCPU() int {
+	n := runtime.NumCPU()
+	if n == 0 {
+		n = 8
+	}
+	return n
+}
+
 func SortFortunesByMessage(fortunes []templates.Fortune) {
 	sort.Slice(fortunes, func(i, j int) bool { return fortunes[i].Message < fortunes[j].Message })
 }

+ 1 - 2
frameworks/Go/fasthttp/src/common/prefork.go

@@ -5,7 +5,6 @@ import (
 	"net"
 	"os"
 	"os/exec"
-	"runtime"
 )
 
 func DoPrefork(child bool, toBind string) net.Listener {
@@ -23,7 +22,7 @@ func DoPrefork(child bool, toBind string) net.Listener {
 		if err != nil {
 			log.Fatal(err)
 		}
-		children := make([]*exec.Cmd, runtime.NumCPU()/2)
+		children := make([]*exec.Cmd, NumCPU()/2)
 		for i := range children {
 			children[i] = exec.Command(os.Args[0], "-prefork", "-child")
 			children[i].Stdout = os.Stdout

+ 12 - 0
frameworks/Go/fasthttp/src/go.mod

@@ -0,0 +1,12 @@
+module fasthttp/src
+
+go 1.13
+
+require (
+	github.com/go-sql-driver/mysql v1.4.1
+	github.com/jackc/pgx/v4 v4.0.1
+	github.com/mailru/easyjson v0.7.0
+	github.com/shopspring/decimal v0.0.0-20190905144223-a36b5d85f337 // indirect
+	github.com/valyala/fasthttp v1.5.0
+	google.golang.org/appengine v1.6.2 // indirect
+)

+ 150 - 0
frameworks/Go/fasthttp/src/go.sum

@@ -0,0 +1,150 @@
+github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
+github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
+github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
+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/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
+github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
+github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
+github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
+github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
+github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
+github.com/jackc/chunkreader/v2 v2.0.0 h1:DUwgMQuuPnS0rhMXenUtZpqZqrR/30NWY+qQvTpSvEs=
+github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
+github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
+github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
+github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
+github.com/jackc/pgconn v1.0.1 h1:ZANo4pIkeHKIVD1cQMcxu8fwrwIICLblzi9HCjooZeQ=
+github.com/jackc/pgconn v1.0.1/go.mod h1:GgY/Lbj1VonNaVdNUHs9AwWom3yP2eymFQ1C8z9r/Lk=
+github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
+github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
+github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA=
+github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
+github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
+github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
+github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
+github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
+github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
+github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
+github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
+github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
+github.com/jackc/pgproto3/v2 v2.0.0 h1:FApgMJ/GtaXfI0s8Lvd0kaLaRwMOhs4VH92pwkwQQvU=
+github.com/jackc/pgproto3/v2 v2.0.0/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
+github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
+github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
+github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
+github.com/jackc/pgtype v1.0.1 h1:7GWB9n3DdnO3TIbj59wMAE9QcHPL4cy/Bbtk5P1Noow=
+github.com/jackc/pgtype v1.0.1/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0=
+github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
+github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
+github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
+github.com/jackc/pgx/v4 v4.0.1 h1:NNrG0MX2AVEJw1NNDYg+ixSXycCfWWKeqMuQHQkAngc=
+github.com/jackc/pgx/v4 v4.0.1/go.mod h1:NeQ64VJooukJGFLX2r01sJL/gRbKlpvsO2giBvjfgrY=
+github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/jackc/puddle v1.0.0 h1:rbjAshlgKscNa7j0jAM0uNQflis5o2XUogPMVAwtcsM=
+github.com/jackc/puddle v1.0.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
+github.com/klauspost/compress v1.8.2 h1:Bx0qjetmNjdFXASH02NSAREKpiaDwkO1DRZ3dV2KCcs=
+github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
+github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
+github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
+github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
+github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
+github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
+github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
+github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
+github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+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/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
+github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
+github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
+github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
+github.com/shopspring/decimal v0.0.0-20190905144223-a36b5d85f337 h1:Da9XEUfFxgyDOqUfwgoTDcWzmnlOnCGi6i4iPS+8Fbw=
+github.com/shopspring/decimal v0.0.0-20190905144223-a36b5d85f337/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
+github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
+github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasthttp v1.5.0 h1:dhq+O9pmNZFF6qAXpasMO1xSm7dL4qEz2ylfZN8BG9w=
+github.com/valyala/fasthttp v1.5.0/go.mod h1:eriCz9OhZjKCGfJ185a/IDgNl0bg9IbzfpcslMZXU1c=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
+github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
+go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7 h1:0hQKqeLdqlt5iIwVOBErRisrHJAN57yOiPRQItI20fU=
+golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.6.2 h1:j8RI1yW0SkI+paT6uGwMlrMI/6zwYA6/CFil8rxOzGI=
+google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

+ 5 - 3
frameworks/Go/fasthttp/src/server-mysql/server.go

@@ -6,12 +6,13 @@ import (
 	"log"
 	"net"
 	"runtime"
+	"unsafe"
 
 	_ "github.com/go-sql-driver/mysql"
 	"github.com/valyala/fasthttp"
 
-	"common"
-	"templates"
+	"fasthttp/src/common"
+	"fasthttp/src/templates"
 )
 
 const connectionString = "benchmarkdbuser:benchmarkdbpass@tcp(tfb-database:3306)/hello_world"
@@ -65,7 +66,7 @@ func main() {
 
 func mainHandler(ctx *fasthttp.RequestCtx) {
 	path := ctx.Path()
-	switch string(path) {
+	switch *(*string)(unsafe.Pointer(&path)) {
 	case "/plaintext":
 		common.PlaintextHandler(ctx)
 	case "/json":
@@ -183,4 +184,5 @@ func mustPrepare(db *sql.DB, query string) *sql.Stmt {
 		log.Fatalf("Error when preparing statement %q: %s", query, err)
 	}
 	return stmt
+	// ?
 }

+ 31 - 61
frameworks/Go/fasthttp/src/server-postgresql/server.go

@@ -1,27 +1,29 @@
 package main
 
 import (
+	"context"
 	"flag"
 	"fmt"
 	"log"
 	"net"
-	"runtime"
+	"unsafe"
 
-	"github.com/jackc/pgx"
+	pgx "github.com/jackc/pgx/v4"
+	"github.com/jackc/pgx/v4/pgxpool"
 	"github.com/valyala/fasthttp"
 
-	"common"
-	"templates"
+	"fasthttp/src/common"
+	"fasthttp/src/templates"
 )
 
 var (
-	worldSelectStmt   *pgx.PreparedStatement
-	worldUpdateStmt   *pgx.PreparedStatement
-	fortuneSelectStmt *pgx.PreparedStatement
-
-	db *pgx.ConnPool
+	db *pgxpool.Pool
 )
 
+const worldSelectSQL = "SELECT id, randomNumber FROM World WHERE id = $1"
+const worldUpdateSQL = "UPDATE World SET randomNumber = $1 WHERE id = $2"
+const fortuneSelectSQL = "SELECT id, message FROM Fortune"
+
 func main() {
 	bindHost := flag.String("bind", ":8080", "set bind host")
 	prefork := flag.Bool("prefork", false, "use prefork")
@@ -29,9 +31,9 @@ func main() {
 	flag.Parse()
 
 	var err error
-	maxConnectionCount := runtime.NumCPU() * 4
+	maxConnectionCount := common.NumCPU() * 4
 	if *child {
-		maxConnectionCount = runtime.NumCPU()
+		maxConnectionCount = common.NumCPU()
 	}
 	if db, err = initDatabase("tfb-database", "benchmarkdbuser", "benchmarkdbpass", "hello_world", 5432, maxConnectionCount); err != nil {
 		log.Fatalf("Error opening database: %s", err)
@@ -56,7 +58,7 @@ func main() {
 
 func mainHandler(ctx *fasthttp.RequestCtx) {
 	path := ctx.Path()
-	switch string(path) {
+	switch *(*string)(unsafe.Pointer(&path)) {
 	case "/plaintext":
 		common.PlaintextHandler(ctx)
 	case "/json":
@@ -75,8 +77,7 @@ func mainHandler(ctx *fasthttp.RequestCtx) {
 }
 
 func dbHandler(ctx *fasthttp.RequestCtx) {
-	var w common.World
-	fetchRandomWorld(&w)
+	w := fetchRandomWorld()
 	wb, err := w.MarshalJSON()
 	if err != nil {
 		log.Println(err)
@@ -90,7 +91,7 @@ func queriesHandler(ctx *fasthttp.RequestCtx) {
 	n := common.GetQueriesCount(ctx)
 	worlds := make([]common.World, n)
 	for i := 0; i < n; i++ {
-		fetchRandomWorld(&worlds[i])
+		worlds[i] = fetchRandomWorld()
 	}
 	wb, err := common.Worlds(worlds).MarshalJSON()
 	if err != nil {
@@ -102,7 +103,7 @@ func queriesHandler(ctx *fasthttp.RequestCtx) {
 }
 
 func fortuneHandler(ctx *fasthttp.RequestCtx) {
-	rows, err := db.Query("fortuneSelectStmt")
+	rows, err := db.Query(context.Background(), fortuneSelectSQL)
 	if err != nil {
 		log.Fatalf("Error selecting db data: %v", err)
 	}
@@ -129,27 +130,19 @@ func updateHandler(ctx *fasthttp.RequestCtx) {
 
 	worlds := make([]common.World, n)
 	for i := 0; i < n; i++ {
-		w := &worlds[i]
-		fetchRandomWorld(w)
-		w.RandomNumber = int32(common.RandomWorldNum())
+		worlds[i] = fetchRandomWorld()
+		worlds[i].RandomNumber = int32(common.RandomWorldNum())
 	}
 
 	// sorting is required for insert deadlock prevention.
 	common.SortWorldsByID(worlds)
 
-	txn, err := db.Begin()
-	if err != nil {
-		log.Fatalf("Error starting transaction: %s", err)
-	}
-
-	for i := 0; i < n; i++ {
-		w := &worlds[i]
-		if _, err = txn.Exec("worldUpdateStmt", w.RandomNumber, w.Id); err != nil {
-			log.Fatalf("Error updating world row %d: %s", i, err)
-		}
+	batch := pgx.Batch{}
+	for _, w := range worlds {
+		batch.Queue(worldUpdateSQL, w.RandomNumber, w.Id)
 	}
-	if err = txn.Commit(); err != nil {
-		log.Fatalf("Error when commiting world rows: %s", err)
+	if err := db.SendBatch(context.Background(), &batch).Close(); err != nil {
+		log.Fatalf("Error when closing a batch: %s", err)
 	}
 
 	wb, err := common.Worlds(worlds).MarshalJSON()
@@ -161,45 +154,22 @@ func updateHandler(ctx *fasthttp.RequestCtx) {
 	ctx.Write(wb)
 }
 
-func fetchRandomWorld(w *common.World) {
+func fetchRandomWorld() (w common.World) {
 	n := common.RandomWorldNum()
-	if err := db.QueryRow("worldSelectStmt", n).Scan(&w.Id, &w.RandomNumber); err != nil {
+	if err := db.QueryRow(context.Background(), worldSelectSQL, n).Scan(&w.Id, &w.RandomNumber); err != nil {
 		log.Fatalf("Error scanning world row: %s", err)
 	}
+	return w
 }
 
-func mustPrepare(db *pgx.Conn, name, query string) *pgx.PreparedStatement {
-	stmt, err := db.Prepare(name, query)
-	if err != nil {
-		log.Fatalf("Error when preparing statement %q: %s", query, err)
-	}
-	return stmt
-}
-
-func initDatabase(dbHost string, dbUser string, dbPass string, dbName string, dbPort uint16, maxConnectionsInPool int) (*pgx.ConnPool, error) {
-
+func initDatabase(dbHost string, dbUser string, dbPass string, dbName string, dbPort uint16, maxConnectionsInPool int) (*pgxpool.Pool, error) {
 	var successOrFailure string = "OK"
 
-	var config pgx.ConnPoolConfig
-
-	config.Host = dbHost
-	config.User = dbUser
-	config.Password = dbPass
-	config.Database = dbName
-	config.Port = dbPort
-
-	config.MaxConnections = maxConnectionsInPool
-
-	config.AfterConnect = func(conn *pgx.Conn) error {
-		worldSelectStmt = mustPrepare(conn, "worldSelectStmt", "SELECT id, randomNumber FROM World WHERE id = $1")
-		worldUpdateStmt = mustPrepare(conn, "worldUpdateStmt", "UPDATE World SET randomNumber = $1 WHERE id = $2")
-		fortuneSelectStmt = mustPrepare(conn, "fortuneSelectStmt", "SELECT id, message FROM Fortune")
-		return nil
-	}
+	dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s pool_max_conns=%d", dbHost, dbPort, dbUser, dbPass, dbName, maxConnectionsInPool)
 
 	fmt.Println("--------------------------------------------------------------------------------------------")
 
-	connPool, err := pgx.NewConnPool(config)
+	connPool, err := pgxpool.Connect(context.Background(), dsn)
 	if err != nil {
 		successOrFailure = "FAILED"
 		log.Println("Connecting to database ", dbName, " as user ", dbUser, " ", successOrFailure, ": \n ", err)
@@ -209,7 +179,7 @@ func initDatabase(dbHost string, dbUser string, dbPass string, dbName string, db
 		log.Println("Fetching one record to test if db connection is valid...")
 		var w common.World
 		n := common.RandomWorldNum()
-		if errPing := connPool.QueryRow("worldSelectStmt", n).Scan(&w.Id, &w.RandomNumber); errPing != nil {
+		if errPing := connPool.QueryRow(context.Background(), worldSelectSQL, n).Scan(&w.Id, &w.RandomNumber); errPing != nil {
 			log.Fatalf("Error scanning world row: %s", errPing)
 		}
 		log.Println("OK")