mirror of https://github.com/perkeep/perkeep.git
client/android: instrument memory usage.
also try to GC and return memory to OS every 5 seconds, but that barely makes a dent in the real problem. more later. Change-Id: I2979e099121bdcb8578124b1c45714313cc2ec09
This commit is contained in:
parent
f4d9fab966
commit
0072a5b325
|
@ -33,11 +33,15 @@ import (
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"camlistore.org/pkg/blob"
|
"camlistore.org/pkg/blob"
|
||||||
"camlistore.org/pkg/blobserver"
|
"camlistore.org/pkg/blobserver"
|
||||||
|
"camlistore.org/pkg/osutil"
|
||||||
"camlistore.org/pkg/schema"
|
"camlistore.org/pkg/schema"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,6 +52,7 @@ var androidOutput, _ = strconv.ParseBool(os.Getenv("CAMPUT_ANDROID_OUTPUT"))
|
||||||
// child process and should report its output in the form that the
|
// child process and should report its output in the form that the
|
||||||
// Android uploader app expects.
|
// Android uploader app expects.
|
||||||
func IsChild() bool {
|
func IsChild() bool {
|
||||||
|
memOnce.Do(startMemGoroutine)
|
||||||
return androidOutput
|
return androidOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +98,17 @@ func (ni *namedInt) Incr(delta int64) {
|
||||||
Printf("STAT %s %d\n", ni.name, nv)
|
Printf("STAT %s %d\n", ni.name, nv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ni *namedInt) Set(v int64) {
|
||||||
|
ni.Lock()
|
||||||
|
if v == ni.val {
|
||||||
|
ni.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ni.val = v
|
||||||
|
ni.Unlock()
|
||||||
|
Printf("STAT %s %d\n", ni.name, v)
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
statDNSStart = &namedInt{name: "dns_start"}
|
statDNSStart = &namedInt{name: "dns_start"}
|
||||||
statDNSDone = &namedInt{name: "dns_done"}
|
statDNSDone = &namedInt{name: "dns_done"}
|
||||||
|
@ -109,6 +125,9 @@ var (
|
||||||
statBlobExisted = &namedInt{name: "blob_existed"}
|
statBlobExisted = &namedInt{name: "blob_existed"}
|
||||||
statFileUploaded = &namedInt{name: "file_uploaded"}
|
statFileUploaded = &namedInt{name: "file_uploaded"}
|
||||||
statFileExisted = &namedInt{name: "file_existed"}
|
statFileExisted = &namedInt{name: "file_existed"}
|
||||||
|
statMemReleased = &namedInt{name: "mem_heap_released"}
|
||||||
|
statMemAlloc = &namedInt{name: "mem_alloc"}
|
||||||
|
statMemRSS = &namedInt{name: "mem_rss"}
|
||||||
)
|
)
|
||||||
|
|
||||||
type statTrackingConn struct {
|
type statTrackingConn struct {
|
||||||
|
@ -212,7 +231,13 @@ func Dial(network, addr string) (net.Conn, error) {
|
||||||
statTCPFail.Incr(1)
|
statTCPFail.Incr(1)
|
||||||
return nil, fmt.Errorf("couldn't split %q", addr)
|
return nil, fmt.Errorf("couldn't split %q", addr)
|
||||||
}
|
}
|
||||||
c, err := net.Dial(network, net.JoinHostPort(androidLookupHost(host), port))
|
if OnAndroid() {
|
||||||
|
// Only do the Android DNS lookups when actually
|
||||||
|
// running on a device. We also run in "Android mode"
|
||||||
|
// (IsChild) in tests and interactive debugging.
|
||||||
|
host = androidLookupHost(host)
|
||||||
|
}
|
||||||
|
c, err := net.Dial(network, net.JoinHostPort(host, port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
statTCPFail.Incr(1)
|
statTCPFail.Incr(1)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -323,3 +348,26 @@ func (w writeUntilSliceFull) Write(p []byte) (n int, err error) {
|
||||||
*w.s = s
|
*w.s = s
|
||||||
return len(p), nil
|
return len(p), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var memOnce sync.Once
|
||||||
|
|
||||||
|
func startMemGoroutine() {
|
||||||
|
if !androidOutput {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
var ms runtime.MemStats
|
||||||
|
n := 0
|
||||||
|
for {
|
||||||
|
runtime.ReadMemStats(&ms)
|
||||||
|
statMemReleased.Set(int64(ms.HeapReleased))
|
||||||
|
statMemAlloc.Set(int64(ms.Alloc))
|
||||||
|
statMemRSS.Set(osutil.MemUsage())
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
n++
|
||||||
|
if n%5 == 0 {
|
||||||
|
debug.FreeOSMemory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
|
@ -188,7 +188,7 @@ func (c *Client) TransportForConfig(tc *TransportConfig) http.RoundTripper {
|
||||||
httpStats.VerboseLog = tc.Verbose
|
httpStats.VerboseLog = tc.Verbose
|
||||||
}
|
}
|
||||||
transport = httpStats
|
transport = httpStats
|
||||||
if android.OnAndroid() {
|
if android.IsChild() {
|
||||||
transport = &android.StatsTransport{transport}
|
transport = &android.StatsTransport{transport}
|
||||||
}
|
}
|
||||||
return transport
|
return transport
|
||||||
|
@ -816,7 +816,7 @@ func (c *Client) DialFunc() func(network, addr string) (net.Conn, error) {
|
||||||
trustedCerts := c.getTrustedCerts()
|
trustedCerts := c.getTrustedCerts()
|
||||||
if !c.useTLS() || (!c.InsecureTLS && len(trustedCerts) == 0) {
|
if !c.useTLS() || (!c.InsecureTLS && len(trustedCerts) == 0) {
|
||||||
// No TLS, or TLS with normal/full verification
|
// No TLS, or TLS with normal/full verification
|
||||||
if android.OnAndroid() {
|
if android.IsChild() {
|
||||||
return func(network, addr string) (net.Conn, error) {
|
return func(network, addr string) (net.Conn, error) {
|
||||||
return android.Dial(network, addr)
|
return android.Dial(network, addr)
|
||||||
}
|
}
|
||||||
|
@ -827,7 +827,7 @@ func (c *Client) DialFunc() func(network, addr string) (net.Conn, error) {
|
||||||
return func(network, addr string) (net.Conn, error) {
|
return func(network, addr string) (net.Conn, error) {
|
||||||
var conn *tls.Conn
|
var conn *tls.Conn
|
||||||
var err error
|
var err error
|
||||||
if android.OnAndroid() {
|
if android.IsChild() {
|
||||||
con, err := android.Dial(network, addr)
|
con, err := android.Dial(network, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
Loading…
Reference in New Issue