go-whatsapp: QR Code benchmark generate memory problem!
Hello, I have this function served via swagger
func ScanQr(params profile.ScanQrParams) middleware.Responder {
qr := make(chan string)
errCh := make(chan error)
go func() {
sessionID := params.SessionID.String()
handler, err := wa.Login(qr, params.ProxyURL, sessionID)
if err != nil {
errCh <- err
}
wa.Connections[sessionID] = handler
}()
select {
case err := <-errCh:
errText := err.Error()
return profile.NewScanQrDefault(500).WithPayload(&models.Error{
Code: 500,
Message: &errText,
})
case qrText := <-qr:
return profile.NewScanQrOK().WithPayload(&models.QRCode{
Base64: qrText,
})
}
}
I tried to flood the function with 50 requests to understand what will be going on if we have 50 users online asking for the QR… Well, i got a server panic a VERY LONG error but I will add the deader of the error.
runtime: out of memory: cannot allocate 26214400-byte block (3927212032 in use)
fatal error: out of memory
runtime stack:
runtime.throw(0x87ae49f, 0xd)
/usr/local/go/src/runtime/panic.go:774 +0x6a
runtime.largeAlloc(0x1900000, 0x8090101, 0xe740ed20)
/usr/local/go/src/runtime/malloc.go:1140 +0x108
runtime.mallocgc.func1()
/usr/local/go/src/runtime/malloc.go:1033 +0x39
runtime.systemstack(0x9588700)
/usr/local/go/src/runtime/asm_386.s:399 +0x53
runtime.mstart()
/usr/local/go/src/runtime/proc.go:1146
goroutine 2083 [running]:
runtime.systemstack_switch()
/usr/local/go/src/runtime/asm_386.s:360 fp=0x9c1397c sp=0x9c13978 pc=0x8098d00
runtime.mallocgc(0x1900000, 0x86dc340, 0x87ef801, 0x84cc9a40)
/usr/local/go/src/runtime/malloc.go:1032 +0x6a8 fp=0x9c139d0 sp=0x9c1397c pc=0x8052508
runtime.makeslice(0x86dc340, 0x1900000, 0x1900000, 0xe74b9cb8)
/usr/local/go/src/runtime/slice.go:49 +0x4f fp=0x9c139e4 sp=0x9c139d0 pc=0x8085acf
bufio.NewReaderSize(...)
/usr/local/go/src/bufio/bufio.go:56
github.com/gorilla/websocket.newConn(0x88e4140, 0x1232000, 0x0, 0x1900000, 0xa00000, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
/root/go/pkg/mod/github.com/gorilla/websocket@v1.4.2/conn.go:293 +0x2e1 fp=0x9c13a4c sp=0x9c139e4 pc=0x85a56d1
github.com/gorilla/websocket.(*Dialer).DialContext(0x950c340, 0x88df800, 0x950cfc0, 0x87b9975, 0x19, 0x8d96fc68, 0x0, 0x0, 0x0, 0x0)
/root/go/pkg/mod/github.com/gorilla/websocket@v1.4.2/client.go:327 +0xc6f fp=0x9c13be4 sp=0x9c13a4c pc=0x85a2def
github.com/gorilla/websocket.(*Dialer).Dial(0x950c340, 0x87b9975, 0x19, 0x8d96fc68, 0x8d96fccc, 0x84dc65e, 0x0, 0x0)
/root/go/pkg/mod/github.com/gorilla/websocket@v1.4.2/client.go:106 +0x4d fp=0x9c13c10 sp=0x9c13be4 pc=0x85a1fad
github.com/Rhymen/go-whatsapp.(*Conn).connect(0x9a253b0, 0x0, 0x0)
/root/go/pkg/mod/github.com/!rhymen/go-whatsapp@v0.1.1-0.20200408093540-2f227c53b44f/conn.go:163 +0x1a1 fp=0x9c13d34 sp=0x9c13c10 pc=0x85b8601
github.com/Rhymen/go-whatsapp.NewConn(0xf8475800, 0xd, 0x87bc8dd, 0x1d, 0x121cdb8)
/root/go/pkg/mod/github.com/!rhymen/go-whatsapp@v0.1.1-0.20200408093540-2f227c53b44f/conn.go:125 +0x119 fp=0x9c13d5c sp=0x9c13d34 pc=0x85b8229
bitbucket.org/rockyOO7/wa-api/whatsapp.NewConn(0x0, 0x98ff6f8, 0x0, 0x0)
/home/beshoo/go-wapi/wa/whatsapp/main.go:164 +0x1b8 fp=0x9c13dcc sp=0x9c13d5c pc=0x8606438
bitbucket.org/rockyOO7/wa-api/whatsapp.Login(0x19223580, 0x0, 0x97f0f90, 0x24, 0x807903e, 0x87ef7e8, 0x1)
/home/beshoo/go-wapi/wa/whatsapp/main.go:182 +0x7d fp=0x9c13fac sp=0x9c13dcc pc=0x86064cd
bitbucket.org/rockyOO7/wa-api/api.ScanQr.func1(0xd177aa00, 0x0, 0x97f0f90, 0x24, 0x19223580, 0x192235c0)
/home/beshoo/go-wapi/wa/api/profile.go:24 +0x4d fp=0x9c13fd8 sp=0x9c13fac pc=0x861cdad
Now let us see what is going on, on the main.go:164*
func NewConn(proxyURLString *string) (*wa.Conn, error) {
var err error
var wac *wa.Conn
var timeout = time.Duration(*timeoutInt) * time.Second
log.Infof("TimeOutFlag: %v , TimeOut: %v", *timeoutInt,timeout)
if proxyURLString != nil {
proxyURL, err := url.Parse(*proxyURLString)
if err != nil {
return nil, err
}
proxy := http.ProxyURL(proxyURL)
wac, err = wa.NewConnWithProxy(timeout, proxy)
} else {
wac, err = wa.NewConn(timeout) //<========== main.go:164
}
if err != nil {
wac.Disconnect()
return nil, err
}
return wac, nil
}
and profile.go:24
func ScanQr(params profile.ScanQrParams) middleware.Responder {
qr := make(chan string)
errCh := make(chan error)
go func() {
sessionID := params.SessionID.String()
handler, err := wa.Login(qr, params.ProxyURL, sessionID) // <<========= profile.go:24
if err != nil {
errCh <- err
}
wa.Connections[sessionID] = handler
}()
select {
case err := <-errCh:
errText := err.Error()
return profile.NewScanQrDefault(500).WithPayload(&models.Error{
Code: 500,
Message: &errText,
})
case qrText := <-qr:
return profile.NewScanQrOK().WithPayload(&models.QRCode{
Base64: qrText,
})
}
}
and the Login function which triggered by the QR scaner profile.go:24
func Login(qr chan string, proxyURL *strfmt.URI, sessionID string) (*WaHandler, error) {
var proxyURLString *string
if proxyURL != nil {
temp := proxyURL.String()
proxyURLString = &temp
}
var wac, err = NewConn(proxyURLString) // <=========== main.go:182
if err != nil {
return nil, err
}
.....................
}
Well, how can we handle suchtype of memory problem?
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 17 (7 by maintainers)
No, i am saying the WA Version with
wac.SetClientVersion(2, 2017, 6)Ok, we should test it a little bit more before opening a PR, like Send messages, receiving too. But glad too know it might fix the memory issue!