@@ -12,15 +12,29 @@ import (
1212 "net/http"
1313 "net/http/httputil"
1414 "net/url"
15- "strconv"
16- "strings"
15+ "runtime/debug"
1716 "sync"
1817 "sync/atomic"
1918 "time"
2019
2120 "github.com/julienschmidt/httprouter"
21+ "go4.org/strutil"
2222)
2323
24+ var transportClient = & http.Transport {
25+ Proxy : http .ProxyFromEnvironment ,
26+ DisableCompression : true ,
27+ Dial : (& net.Dialer {
28+ Timeout : 5 * time .Second ,
29+ }).Dial ,
30+ TLSHandshakeTimeout : 5 * time .Second ,
31+ }
32+
33+ var client = & http.Client {
34+ Timeout : time .Second * 5 ,
35+ Transport : transportClient ,
36+ }
37+
2438func main () {
2539 const (
2640 defaultPort = "3000"
@@ -32,16 +46,19 @@ func main() {
3246 // flags
3347 port := flag .String ("port" , defaultPort , defaultPortUsage )
3448 redirectURL := flag .String ("url" , defaultTarget , defaultTargetUsage )
35- cmdEndpoint := flag .String ("endpoint" , "/" , "Custom endpoint to send GCI-specific commands. For example, '/gci'" )
3649 yGen := flag .Uint64 ("ygen" , 0 , "Young generation size, in bytes." )
3750 tGen := flag .Uint64 ("tgen" , 0 , "Tenured generation size, in bytes." )
51+ printGC := flag .Bool ("print_gc" , true , "Whether to print gc information." )
3852 flag .Parse ()
3953
4054 if * yGen == 0 || * tGen == 0 {
4155 log .Fatalf ("Neither ygen nor tgen can be 0. ygen:%d tgen:%d" , * yGen , * tGen )
4256 }
4357
44- proxy := newProxy (* redirectURL , * cmdEndpoint , * yGen , * tGen )
58+ // Configuring Garbage Collector activity. Please take a look at the benchmark comment before changing this value.
59+ debug .SetGCPercent (400 )
60+
61+ proxy := newProxy (* redirectURL , * yGen , * tGen , * printGC )
4562 c := make (chan struct {}, 1 )
4663 router := httprouter .New ()
4764 router .HandlerFunc ("GET" , "/" , func (w http.ResponseWriter , r * http.Request ) {
@@ -55,9 +72,10 @@ func main() {
5572const (
5673 gciHeader = "gci"
5774 heapCheckHeader = "ch"
58- genSeparator = "|"
5975)
6076
77+ var genSeparator = []byte {124 } // character "|"
78+
6179type generation string
6280
6381func (g generation ) string () string {
@@ -73,11 +91,11 @@ type transport struct {
7391 isAvailable int32
7492 shed uint64
7593 target string
76- cmdEndpoint string
7794 waiter pendingWaiter
7895 window sampleWindow
7996 stGen1 sheddingThreshold
8097 stGen2 sheddingThreshold
98+ printGC bool
8199}
82100
83101func shedResponse (req * http.Request ) * http.Response {
@@ -94,29 +112,8 @@ func shedResponse(req *http.Request) *http.Response {
94112 }
95113}
96114
97- var transportClient = & http.Transport {
98- Dial : (& net.Dialer {
99- Timeout : 5 * time .Second ,
100- }).Dial ,
101- TLSHandshakeTimeout : 5 * time .Second ,
102- }
103- var client = & http.Client {
104- Timeout : time .Second * 5 ,
105- Transport : transportClient ,
106- }
107-
108115func (t * transport ) RoundTrip (request * http.Request ) (* http.Response , error ) {
109- if request .Body != nil {
110- buf , err := ioutil .ReadAll (request .Body )
111- if err != nil {
112- panic (err )
113- }
114- request .Body = ioutil .NopCloser (bytes .NewBuffer (buf ))
115- }
116116 if atomic .LoadInt32 (& t .isAvailable ) == 1 {
117- if request != nil && request .Body != nil {
118- request .Body .Close ()
119- }
120117 atomic .AddUint64 (& t .shed , 1 )
121118 return shedResponse (request ), nil
122119 }
@@ -141,7 +138,7 @@ func (t *transport) checkHeap() {
141138 arrived , finished := t .waiter .waitPending ()
142139 t .window .update (finished )
143140
144- req , err := http .NewRequest ("GET" , fmt . Sprintf ( "%s%s" , t .target , t . cmdEndpoint ) , nil )
141+ req , err := http .NewRequest ("GET" , t .target , nil )
145142 if err != nil {
146143 panic (fmt .Sprintf ("Err trying to build heap check request: %q\n " , err ))
147144 }
@@ -158,9 +155,9 @@ func (t *transport) checkHeap() {
158155 panic (fmt .Sprintf ("Could not read check heap response: %q" , err ))
159156 }
160157 resp .Body .Close ()
161- hs := strings .Split (string ( b ) , genSeparator )
158+ hs := bytes .Split (b , genSeparator )
162159 if len (hs ) > 1 { // If there is more than one generation, lets check the tenured and run the full gc if needed.
163- usedGen2 , err := strconv . ParseUint (hs [1 ], 10 , 64 )
160+ usedGen2 , err := strutil . ParseUintBytes (hs [1 ], 10 , 64 )
164161 if err != nil {
165162 panic (fmt .Sprintf ("Could not convert usedGen2 size to number: %q" , err ))
166163 }
@@ -169,7 +166,7 @@ func (t *transport) checkHeap() {
169166 return
170167 }
171168 }
172- usedGen1 , err := strconv . ParseUint (hs [0 ], 10 , 64 )
169+ usedGen1 , err := strutil . ParseUintBytes (hs [0 ], 10 , 64 )
173170 if err != nil {
174171 panic (fmt .Sprintf ("Could not convert usedGen1 size to number: %q" , err ))
175172 }
@@ -191,7 +188,7 @@ func shouldGC(pending, usedBytes, st uint64) bool {
191188}
192189
193190func (t * transport ) gc (gen generation ) {
194- req , err := http .NewRequest ("GET" , fmt . Sprintf ( "%s%s" , t .target , t . cmdEndpoint ) , nil )
191+ req , err := http .NewRequest ("GET" , t .target , nil )
195192 if err != nil {
196193 panic (fmt .Sprintf ("Err trying to build gc request: %q\n " , err ))
197194 }
@@ -211,7 +208,9 @@ func (t *transport) gc(gen generation) {
211208 ioutil .ReadAll (resp .Body )
212209 resp .Body .Close ()
213210 }
214- fmt .Printf ("%d,%s,%v\n " , start .Unix (), gen .string (), end .Sub (start ).Nanoseconds ()/ 1e6 )
211+ if t .printGC {
212+ fmt .Printf ("%d,%s,%v\n " , start .Unix (), gen .string (), end .Sub (start ).Nanoseconds ()/ 1e6 )
213+ }
215214}
216215
217216////////// PROXY
@@ -224,20 +223,20 @@ func (p *proxy) handle(w http.ResponseWriter, r *http.Request) {
224223 p .proxy .ServeHTTP (w , r )
225224}
226225
227- func newProxy (target , cmdEndpoint string , yGen , tGen uint64 ) * proxy {
226+ func newProxy (target string , yGen , tGen uint64 , printGC bool ) * proxy {
228227 url , _ := url .Parse (target )
229228 p := httputil .NewSingleHostReverseProxy (url )
230- p .Transport = newTransport (target , cmdEndpoint , yGen , tGen )
229+ p .Transport = newTransport (target , yGen , tGen , printGC )
231230 return & proxy {target : url , proxy : p }
232231}
233232
234- func newTransport (target , cmdEndpoint string , yGen , tGen uint64 ) * transport {
233+ func newTransport (target string , yGen , tGen uint64 , printGC bool ) * transport {
235234 return & transport {
236- target : target ,
237- cmdEndpoint : cmdEndpoint ,
238- window : newSampleWindow ( ),
239- stGen1 : newSheddingThreshold (time .Now ().UnixNano (), yGen ),
240- stGen2 : newSheddingThreshold ( time . Now (). UnixNano (), tGen ) ,
235+ target : target ,
236+ window : newSampleWindow () ,
237+ stGen1 : newSheddingThreshold ( time . Now (). UnixNano (), yGen ),
238+ stGen2 : newSheddingThreshold (time .Now ().UnixNano (), tGen ),
239+ printGC : printGC ,
241240 }
242241}
243242
0 commit comments