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
 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 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 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
 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 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 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
 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 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 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
 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 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 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"
 	"log"
 	"math/rand"
 	"math/rand"
 	"net"
 	"net"
+	"runtime"
 	"sort"
 	"sort"
-	"sync"
 
 
-	"templates"
+	"fasthttp/src/templates"
 
 
 	"github.com/valyala/fasthttp"
 	"github.com/valyala/fasthttp"
 )
 )
@@ -27,9 +27,9 @@ type World struct {
 type Worlds []World
 type Worlds []World
 
 
 func JSONHandler(ctx *fasthttp.RequestCtx) {
 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()
 	rb, err := r.MarshalJSON()
 	if err != nil {
 	if err != nil {
 		log.Println(err)
 		log.Println(err)
@@ -39,12 +39,6 @@ func JSONHandler(ctx *fasthttp.RequestCtx) {
 	ctx.Write(rb)
 	ctx.Write(rb)
 }
 }
 
 
-var jsonResponsePool = &sync.Pool{
-	New: func() interface{} {
-		return &JSONResponse{}
-	},
-}
-
 func PlaintextHandler(ctx *fasthttp.RequestCtx) {
 func PlaintextHandler(ctx *fasthttp.RequestCtx) {
 	ctx.SetContentType("text/plain")
 	ctx.SetContentType("text/plain")
 	ctx.WriteString("Hello, World!")
 	ctx.WriteString("Hello, World!")
@@ -79,6 +73,14 @@ func GetListener(listenAddr string) net.Listener {
 	return ln
 	return ln
 }
 }
 
 
+func NumCPU() int {
+	n := runtime.NumCPU()
+	if n == 0 {
+		n = 8
+	}
+	return n
+}
+
 func SortFortunesByMessage(fortunes []templates.Fortune) {
 func SortFortunesByMessage(fortunes []templates.Fortune) {
 	sort.Slice(fortunes, func(i, j int) bool { return fortunes[i].Message < fortunes[j].Message })
 	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"
 	"net"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
-	"runtime"
 )
 )
 
 
 func DoPrefork(child bool, toBind string) net.Listener {
 func DoPrefork(child bool, toBind string) net.Listener {
@@ -23,7 +22,7 @@ func DoPrefork(child bool, toBind string) net.Listener {
 		if err != nil {
 		if err != nil {
 			log.Fatal(err)
 			log.Fatal(err)
 		}
 		}
-		children := make([]*exec.Cmd, runtime.NumCPU()/2)
+		children := make([]*exec.Cmd, NumCPU()/2)
 		for i := range children {
 		for i := range children {
 			children[i] = exec.Command(os.Args[0], "-prefork", "-child")
 			children[i] = exec.Command(os.Args[0], "-prefork", "-child")
 			children[i].Stdout = os.Stdout
 			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"
 	"log"
 	"net"
 	"net"
 	"runtime"
 	"runtime"
+	"unsafe"
 
 
 	_ "github.com/go-sql-driver/mysql"
 	_ "github.com/go-sql-driver/mysql"
 	"github.com/valyala/fasthttp"
 	"github.com/valyala/fasthttp"
 
 
-	"common"
-	"templates"
+	"fasthttp/src/common"
+	"fasthttp/src/templates"
 )
 )
 
 
 const connectionString = "benchmarkdbuser:benchmarkdbpass@tcp(tfb-database:3306)/hello_world"
 const connectionString = "benchmarkdbuser:benchmarkdbpass@tcp(tfb-database:3306)/hello_world"
@@ -65,7 +66,7 @@ func main() {
 
 
 func mainHandler(ctx *fasthttp.RequestCtx) {
 func mainHandler(ctx *fasthttp.RequestCtx) {
 	path := ctx.Path()
 	path := ctx.Path()
-	switch string(path) {
+	switch *(*string)(unsafe.Pointer(&path)) {
 	case "/plaintext":
 	case "/plaintext":
 		common.PlaintextHandler(ctx)
 		common.PlaintextHandler(ctx)
 	case "/json":
 	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)
 		log.Fatalf("Error when preparing statement %q: %s", query, err)
 	}
 	}
 	return stmt
 	return stmt
+	// ?
 }
 }

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

@@ -1,27 +1,29 @@
 package main
 package main
 
 
 import (
 import (
+	"context"
 	"flag"
 	"flag"
 	"fmt"
 	"fmt"
 	"log"
 	"log"
 	"net"
 	"net"
-	"runtime"
+	"unsafe"
 
 
-	"github.com/jackc/pgx"
+	pgx "github.com/jackc/pgx/v4"
+	"github.com/jackc/pgx/v4/pgxpool"
 	"github.com/valyala/fasthttp"
 	"github.com/valyala/fasthttp"
 
 
-	"common"
-	"templates"
+	"fasthttp/src/common"
+	"fasthttp/src/templates"
 )
 )
 
 
 var (
 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() {
 func main() {
 	bindHost := flag.String("bind", ":8080", "set bind host")
 	bindHost := flag.String("bind", ":8080", "set bind host")
 	prefork := flag.Bool("prefork", false, "use prefork")
 	prefork := flag.Bool("prefork", false, "use prefork")
@@ -29,9 +31,9 @@ func main() {
 	flag.Parse()
 	flag.Parse()
 
 
 	var err error
 	var err error
-	maxConnectionCount := runtime.NumCPU() * 4
+	maxConnectionCount := common.NumCPU() * 4
 	if *child {
 	if *child {
-		maxConnectionCount = runtime.NumCPU()
+		maxConnectionCount = common.NumCPU()
 	}
 	}
 	if db, err = initDatabase("tfb-database", "benchmarkdbuser", "benchmarkdbpass", "hello_world", 5432, maxConnectionCount); err != nil {
 	if db, err = initDatabase("tfb-database", "benchmarkdbuser", "benchmarkdbpass", "hello_world", 5432, maxConnectionCount); err != nil {
 		log.Fatalf("Error opening database: %s", err)
 		log.Fatalf("Error opening database: %s", err)
@@ -56,7 +58,7 @@ func main() {
 
 
 func mainHandler(ctx *fasthttp.RequestCtx) {
 func mainHandler(ctx *fasthttp.RequestCtx) {
 	path := ctx.Path()
 	path := ctx.Path()
-	switch string(path) {
+	switch *(*string)(unsafe.Pointer(&path)) {
 	case "/plaintext":
 	case "/plaintext":
 		common.PlaintextHandler(ctx)
 		common.PlaintextHandler(ctx)
 	case "/json":
 	case "/json":
@@ -75,8 +77,7 @@ func mainHandler(ctx *fasthttp.RequestCtx) {
 }
 }
 
 
 func dbHandler(ctx *fasthttp.RequestCtx) {
 func dbHandler(ctx *fasthttp.RequestCtx) {
-	var w common.World
-	fetchRandomWorld(&w)
+	w := fetchRandomWorld()
 	wb, err := w.MarshalJSON()
 	wb, err := w.MarshalJSON()
 	if err != nil {
 	if err != nil {
 		log.Println(err)
 		log.Println(err)
@@ -90,7 +91,7 @@ func queriesHandler(ctx *fasthttp.RequestCtx) {
 	n := common.GetQueriesCount(ctx)
 	n := common.GetQueriesCount(ctx)
 	worlds := make([]common.World, n)
 	worlds := make([]common.World, n)
 	for i := 0; i < n; i++ {
 	for i := 0; i < n; i++ {
-		fetchRandomWorld(&worlds[i])
+		worlds[i] = fetchRandomWorld()
 	}
 	}
 	wb, err := common.Worlds(worlds).MarshalJSON()
 	wb, err := common.Worlds(worlds).MarshalJSON()
 	if err != nil {
 	if err != nil {
@@ -102,7 +103,7 @@ func queriesHandler(ctx *fasthttp.RequestCtx) {
 }
 }
 
 
 func fortuneHandler(ctx *fasthttp.RequestCtx) {
 func fortuneHandler(ctx *fasthttp.RequestCtx) {
-	rows, err := db.Query("fortuneSelectStmt")
+	rows, err := db.Query(context.Background(), fortuneSelectSQL)
 	if err != nil {
 	if err != nil {
 		log.Fatalf("Error selecting db data: %v", err)
 		log.Fatalf("Error selecting db data: %v", err)
 	}
 	}
@@ -129,27 +130,19 @@ func updateHandler(ctx *fasthttp.RequestCtx) {
 
 
 	worlds := make([]common.World, n)
 	worlds := make([]common.World, n)
 	for i := 0; i < n; i++ {
 	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.
 	// sorting is required for insert deadlock prevention.
 	common.SortWorldsByID(worlds)
 	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()
 	wb, err := common.Worlds(worlds).MarshalJSON()
@@ -161,45 +154,22 @@ func updateHandler(ctx *fasthttp.RequestCtx) {
 	ctx.Write(wb)
 	ctx.Write(wb)
 }
 }
 
 
-func fetchRandomWorld(w *common.World) {
+func fetchRandomWorld() (w common.World) {
 	n := common.RandomWorldNum()
 	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)
 		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 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("--------------------------------------------------------------------------------------------")
 	fmt.Println("--------------------------------------------------------------------------------------------")
 
 
-	connPool, err := pgx.NewConnPool(config)
+	connPool, err := pgxpool.Connect(context.Background(), dsn)
 	if err != nil {
 	if err != nil {
 		successOrFailure = "FAILED"
 		successOrFailure = "FAILED"
 		log.Println("Connecting to database ", dbName, " as user ", dbUser, " ", successOrFailure, ": \n ", err)
 		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...")
 		log.Println("Fetching one record to test if db connection is valid...")
 		var w common.World
 		var w common.World
 		n := common.RandomWorldNum()
 		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.Fatalf("Error scanning world row: %s", errPing)
 		}
 		}
 		log.Println("OK")
 		log.Println("OK")