Re: [go-nuts] Memory Stats by runtime wrong ?

1,568 views
Skip to first unread message

Dave Cheney

unread,
May 25, 2013, 1:47:01 AM5/25/13
to Raheel Gupta, golang-nuts
Have a read of http://godoc.org/runtime#MemStats

TL;DR, you are looking at the amount of memory in use on the runtime's
heap, the Sys field is probably closer to what the sys internals tool
reports, but I wouldn't expect them to be 100% the same.

On Sat, May 25, 2013 at 3:34 PM, <rahe...@gmail.com> wrote:
> Hi,
>
> When I see the Memory stats of a program in Windows 7 64 Bit and compare the
> runtime Alloc memory, the memory usage reported by the system is way more.
> Here is my code :
> var m *runtime.MemStats = new(runtime.MemStats)
>
> runtime.ReadMemStats(m)
>
> log.Println("Memory", m.Alloc, m.StackInuse, m.HeapAlloc)
>
>
>
> Output :
>
> 2013/05/25 10:53:08 Memory 1577168 49152 1577168
> 1 - act : login -
> 2013/05/25 10:53:09 Memory 1907944 49152 1907944
> 2 - act : login -
> 2013/05/25 10:54:23 Memory 2182376 49152 2182376
> 3 - act : login -
> 2013/05/25 10:54:24 Memory 2183608 49152 2183608
> 4 - act : login -
> 2013/05/25 10:54:25 Memory 1607000 49152 1607000
> 5 - act : login -
> 2013/05/25 10:54:26 Memory 2771856 49152 2771856
> 6 - act : login -
> 2013/05/25 10:54:26 Memory 2442280 49152 2442280
> 7 - act : login -
> 2013/05/25 10:54:27 Memory 2473320 49152 2473320
> 8 - act : login -
> 2013/05/25 10:54:28 Memory 2193528 49152 2193528
> 9 - act : login -
> 2013/05/25 10:54:29 Memory 2484944 49152 2484944
> 10 - act : login -
> 2013/05/25 10:54:32 Memory 2485440 49152 2485440
> 11 - act : login -
> 2013/05/25 10:54:32 Memory 2773360 49152 2773360
> 12 - act : login -
> 2013/05/25 10:54:33 Memory 2796352 61440 2796352
>
>
>
> It shows only 1.5MB usage while the system shows something like 13.5 MB
>
> Now the system reports something complete different. Screenshot attached.
>
>
>
> Am I doing something wrong ? How to get the real memory usage ?
>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Dave Cheney

unread,
May 25, 2013, 2:23:10 AM5/25/13
to Raheel Gupta, golang-nuts
For efficiency, the runtime asks the operating system for memory in
large chunks, then manages the specific allocations from those large
chunks itself. Also, the runtime itself needs some memory for
bookkeeping, which is not counted towards the heap usage (Alloc), but
must be provided by the operating system (Sys).

On Sat, May 25, 2013 at 4:17 PM, <rahe...@gmail.com> wrote:
> Yes, that is showing nearly same figures :
> Code :
> var m *runtime.MemStats = new(runtime.MemStats)
>
> runtime.ReadMemStats(m)
>
> log.Println(1, "Memory", m.Sys, m.Alloc, m.StackInuse, m.HeapAlloc)
>
> 2013/05/25 11:36:03 Memory 11466708 1864744 49152 1864744
> 1 - act : login -
> 2013/05/25 11:36:09 Memory 11466708 2487208 49152 2487208
> 2 - act : login -
> 2013/05/25 11:36:27 Memory 12646356 2470384 49152 2470384
> 3 - act : login -
> 2013/05/25 11:36:28 Memory 12646356 641696 55296 641696
> 4 - act : login -
> 2013/05/25 11:44:34 Memory 12842964 2776632 67584 2776632
>
> Why is the Memory received from system so high compared to that of the
> actual requirement ?

Dave Cheney

unread,
May 25, 2013, 2:33:02 AM5/25/13
to Raheel Gupta, golang-nuts
As I explained, there is an initial overhead for the runtime itself, I
don't know the specific numbers by 8-10 mb sounds reasonable as this
is the bitmap for the first 512mb of heap. Then there is the fact that
the runtime will request a large amount of memory from the operating
system then manages it internally, so you will see memory in use, as
viewed by an external tool, increase in large steps. This stepping
occurs when the garbage collector is unable to free memory (ie, you're
using up more of the heap) and asks the operating system for a larger
allocation, by default, the GC will double the size of the allocation
every time.

On Sat, May 25, 2013 at 4:26 PM, <rahe...@gmail.com> wrote:
> Hi,
>
> But dont you think its taking like 10 times more memory than required ?
> I understand 1.5 - 2 times is good, but 10 times is a little way too much.
> Anyway to control it ?

Dave Cheney

unread,
May 25, 2013, 3:32:34 AM5/25/13
to Raheel Gupta, golang-nuts
> If I disable GC, will memory still be used in this manner ?

You cannot disable the GC in a Go program. You may turn it off via an
environment flag, but that means no memory will be freed by your
program.

> I would like that the application doesnt keep so much memory. Its actually
> wrong for our use.
> Even when its actually using very less memory the usage shoots upwards
> unnecessarily.

Can you please post a code sample that demonstrates this problem.

> If I disable GC, how can I free memory when its used by the variables ?
> Will it automatically be freed ?

If you disable garbage collection, no memory will be freed and your
process will grow without limit.

Dave Cheney

unread,
May 25, 2013, 3:54:04 AM5/25/13
to Raheel Gupta, golang-nuts
Again, could you please post a *complete* code sample that others can
run to attempt to reproduce your issue.

Also, it would have been a lot simpler, and a lot less time consuming,
if you had said at the start of this thread, "hey, I've written a
small webserver in Go and I think I have a memory leak. I've printed
out the values from runtime.MemStats and they appear to be increasing
without limit"

On Sat, May 25, 2013 at 5:46 PM, <rahe...@gmail.com> wrote:
> Here is the code which gets executed everytime I visit a page (I am using
> the http package)
>
> var m *runtime.MemStats = new(runtime.MemStats)
>
> runtime.ReadMemStats(m)
>
> log.Println(1, "Memory 1", m.Sys, m.Alloc, m.StackInuse, m.HeapAlloc)
>
> mtemp := make([][4096]byte, 32768)
>
> runtime.ReadMemStats(m)
>
> log.Println(1, "Memory 2", m.Sys, m.Alloc, m.StackInuse, m.HeapAlloc)
>
> mtemp = make([][4096]byte, 0)
>
> runtime.ReadMemStats(m)
>
> log.Println(1, "Memory 3", m.Sys, m.Alloc, m.StackInuse, m.HeapAlloc,
> len(mtemp))
>
> runtime.GC()
>
>
>
> Here is the output :
>
> 2013/05/25 13:09:31 81f60840 2112 33270
> 2013/05/25 13:09:34 Memory 1 11466708 2154464 49152 2154464
> 2013/05/25 13:09:34 Memory 2 162461652 134859288 49152 134859288
> 2013/05/25 13:09:34 Memory 3 162461652 134860680 49152 134860680 0
> 1 - act : login -
> 2013/05/25 13:09:42 Memory 1 200210388 171106904 49152 171106904
> 2013/05/25 13:09:42 Memory 2 351205332 269098136 49152 269098136
> 2013/05/25 13:09:42 Memory 3 351205332 269099400 49152 269099400 0
> 2 - act : login -
> 2013/05/25 13:09:52 Memory 1 351303636 305309728 49152 305309728
> 2013/05/25 13:09:52 Memory 2 502298580 439529856 49152 439529856
> 2013/05/25 13:09:52 Memory 3 502298580 439531120 49152 439531120 0
> 3 - act : login -
> 2013/05/25 13:09:54 Memory 1 502298580 439522504 49152 439522504
> 2013/05/25 13:09:54 Memory 2 700987348 573747496 49152 573747496
> 2013/05/25 13:09:54 Memory 3 700987348 573750112 49152 573750112 0
> 4 - act : login -
> 2013/05/25 13:09:55 Memory 1 701085652 573739768 49152 573739768
> 2013/05/25 13:09:55 Memory 2 885651412 707964760 49152 707964760
> 2013/05/25 13:09:55 Memory 3 885651412 707966216 49152 707966216 0
> 5 - act : login -
> 2013/05/25 13:10:03 Memory 1 885651412 707962128 49152 707962128
> 2013/05/25 13:10:03 Memory 2 1036810196 842189584 49152 842189584
> 2013/05/25 13:10:03 Memory 3 1036810196 842190848 49152 842190848 0
> 6 - act : login -
> 2013/05/25 13:10:15 Memory 1 1036810196 842184848 49152 842184848
> runtime: out of memory: cannot allocate 134217728-byte block (843055104 in
> use)
> fatal error: out of memory
> ......(Some lines of panic errors and tracebacks)
>
>
> I would like to get the usage back to near 3-4 MB after it uses the 128 MB
> I allocated. Any way to do it ?

Rémy Oudompheng

unread,
May 25, 2013, 6:51:28 AM5/25/13
to Raheel Gupta, golang-nuts
On 2013/5/25 <rahe...@gmail.com> wrote:
> Here is the code which gets executed everytime I visit a page (I am using
> the http package)
>
> var m *runtime.MemStats = new(runtime.MemStats)
>
> runtime.ReadMemStats(m)
>
> log.Println(1, "Memory 1", m.Sys, m.Alloc, m.StackInuse, m.HeapAlloc)
>
> mtemp := make([][4096]byte, 32768)
>
> runtime.ReadMemStats(m)
>
> log.Println(1, "Memory 2", m.Sys, m.Alloc, m.StackInuse, m.HeapAlloc)
>
> mtemp = make([][4096]byte, 0)
>
> runtime.ReadMemStats(m)
>
> log.Println(1, "Memory 3", m.Sys, m.Alloc, m.StackInuse, m.HeapAlloc,
> len(mtemp))
>
> runtime.GC()

You are just confusing the garbage collector for no reason. There are
limitations and memory usage will not drop unless you start tweaking
things manually, which is hard and not a good idea.

What is the thing you are actually trying to solve?

Also, copying the http package as you do in your example code just
makes things even more confusing and hard to understand. Why are you
doing this?

Rémy.

Michael Jones

unread,
May 25, 2013, 7:40:49 AM5/25/13
to rahe...@gmail.com, golang-nuts
Is there some confusion here between physical memory in use and virtual memory allocated?


On Sat, May 25, 2013 at 4:33 AM, <rahe...@gmail.com> wrote:
>> You are just confusing the garbage collector for no reason. There are
>> limitations and memory usage will not drop unless you start tweaking
>> things manually, which is hard and not a good idea.
>> What is the thing you are actually trying to solve?
I am trying to write a high performance server which handles a lot of Data and Connections and hence memory management is crucial.
I am not confused with the GC, but rather surprised of the absence of functions to free memory.
There are many applications which handle many connections and allocate memory according and after the connection is over, they free the memory.
Unfortunately I havent been able to do so in GO. Once you reach a certain memory usage in Go it will calculate and ask for memory from the system.
So if I allocate 128 MB, the Go runtime will ask the system for much more which defeats the purpose many times.
I simply want to achieve :
1) When I allocate X amount of memory, Go shouldnt ask for 2X or 3X from the system and if it does ask the higher amount of RAM from the system it should return it when not needed. Unfortunately the GC or the runtime isnt smart enough to understand that.
2) When I want to free the memory, I should be able to by some or the other way.
 
If I am writing a commercial product or even an open source one, people wouldnt like to see higher memory usage right ?
I would seriously like to request the "free" memory feature as you have in C/C++
 
The GC is great but having an additional explicit call to free memory is nothing wrong I believe.
 
>> Also, copying the http package as you do in your example code just
>> makes things even more confusing and hard to understand. Why are you
>> doing this?
 
Well in my actual codes I have made changes to it so that I can run my own server at the PORT at which the Web server is listening.
When the header is "MYHEADER" for the HTTP request instead of a GET / POST it will not be a http request and will be handled as my defined protocol. The changes in the http package is very less for that. Nonetheless the code I have posted is the original http package without my changes except the test.go
 
I have attached the test.go here again with the same issue. This time it uses the http package as is.
 
The output :
2013/05/25 16:41:20 1 Request : 1
2013/05/25 16:41:20 1 Memory 1 7927764 787184 43008 787184
2013/05/25 16:41:20 1 Memory 2 158922708 134634072 43008 134634072
2013/05/25 16:41:20 1 Memory 3 158922708 134635560 43008 134635560 0
2013/05/25 16:41:24 1 Request : 2
2013/05/25 16:41:24 1 Memory 1 158922708 134642456 43008 134642456
2013/05/25 16:41:24 1 Memory 2 309917652 268861448 43008 268861448
2013/05/25 16:41:24 1 Memory 3 309917652 268862712 43008 268862712 0
2013/05/25 16:41:26 1 Request : 3
2013/05/25 16:41:26 1 Memory 1 309917652 268860520 43008 268860520
2013/05/25 16:41:26 1 Memory 2 460912596 403079512 43008 403079512
2013/05/25 16:41:26 1 Memory 3 460912596 403080776 43008 403080776 0
2013/05/25 16:41:27 1 Request : 4
2013/05/25 16:41:27 1 Memory 1 460912596 268860520 43008 268860520
2013/05/25 16:41:27 1 Memory 2 460912596 403079512 43008 403079512
2013/05/25 16:41:27 1 Memory 3 460912596 403080776 43008 403080776 0
2013/05/25 16:41:29 1 Request : 5
2013/05/25 16:41:29 1 Memory 1 460912596 268860520 43008 268860520
2013/05/25 16:41:29 1 Memory 2 460912596 403079512 43008 403079512
2013/05/25 16:41:29 1 Memory 3 460912596 403080776 43008 403080776 0
2013/05/25 16:41:31 1 Request : 6
2013/05/25 16:41:31 1 Memory 1 460912596 268863904 49152 268863904
2013/05/25 16:41:31 1 Memory 2 460912596 403082896 49152 403082896
2013/05/25 16:41:31 1 Memory 3 460912596 403084160 49152 403084160 0
2013/05/25 16:41:32 1 Request : 7
2013/05/25 16:41:32 1 Memory 1 460912596 268861600 49152 268861600
2013/05/25 16:41:32 1 Memory 2 460912596 403080592 49152 403080592
2013/05/25 16:41:32 1 Memory 3 460912596 403081856 49152 403081856 0
2013/05/25 16:41:32 1 Request : 8
2013/05/25 16:41:32 1 Memory 1 460912596 268860200 49152 268860200
2013/05/25 16:41:32 1 Memory 2 460912596 403079192 49152 403079192
2013/05/25 16:41:32 1 Memory 3 460912596 403080456 49152 403080456 0
2013/05/25 16:41:32 1 Request : 9
2013/05/25 16:41:32 1 Memory 1 460912596 268860200 49152 268860200
2013/05/25 16:41:32 1 Request : 10
2013/05/25 16:41:32 1 Memory 2 460912596 403087512 49152 403087512
2013/05/25 16:41:32 1 Memory 1 460912596 403087472 49152 403087472
2013/05/25 16:41:32 1 Memory 2 664426452 537340296 61440 537340296
2013/05/25 16:41:32 1 Memory 3 664426452 537348080 61440 537348080 0
2013/05/25 16:41:32 1 Request : 11
2013/05/25 16:41:32 1 Memory 3 460912596 403098008 55296 403098008 0
2013/05/25 16:41:32 1 Memory 1 664426452 403122200 61440 403122200
2013/05/25 16:41:32 1 Request : 12
2013/05/25 16:41:32 1 Memory 1 664426452 537340240 61440 537340240
2013/05/25 16:41:32 1 Memory 2 664426452 537340280 61440 537340280
2013/05/25 16:41:32 1 Memory 2 849254356 671562496 67584 671562496
2013/05/25 16:41:32 1 Memory 3 849254356 671566296 67584 671566296 0
2013/05/25 16:41:32 1 Request : 13
2013/05/25 16:41:32 1 Memory 3 849254356 671564096 67584 671564096 0
2013/05/25 16:41:32 1 Memory 1 849254356 537339816 67584 537339816
2013/05/25 16:41:32 1 Memory 2 849254356 671551560 67584 671551560
2013/05/25 16:41:32 1 Memory 3 849254356 671552824 67584 671552824 0
2013/05/25 16:41:35 1 Request : 14
2013/05/25 16:41:35 1 Memory 1 849254356 537336216 67584 537336216
2013/05/25 16:41:35 1 Memory 2 849254356 671555208 67584 671555208
2013/05/25 16:41:35 1 Memory 3 849254356 671556472 67584 671556472 0
2013/05/25 16:41:35 1 Request : 15
2013/05/25 16:41:35 1 Memory 1 849254356 537335776 67584 537335776
2013/05/25 16:41:35 1 Memory 2 849254356 671554768 67584 671554768
2013/05/25 16:41:35 1 Memory 3 849254356 671556032 67584 671556032 0
2013/05/25 16:41:35 1 Request : 16
2013/05/25 16:41:35 1 Memory 1 849254356 537335776 67584 537335776
2013/05/25 16:41:35 1 Memory 2 849254356 671554768 67584 671554768
2013/05/25 16:41:35 1 Memory 3 849254356 671556032 67584 671556032 0
2013/05/25 16:41:35 1 Request : 17
2013/05/25 16:41:35 1 Memory 1 849254356 537335776 67584 537335776
2013/05/25 16:41:35 1 Memory 2 849254356 671554768 67584 671554768
2013/05/25 16:41:35 1 Memory 3 849254356 671556032 67584 671556032 0
2013/05/25 16:41:35 1 Request : 18
2013/05/25 16:41:35 1 Memory 1 849254356 537335776 67584 537335776
2013/05/25 16:41:35 1 Memory 2 849254356 671554768 67584 671554768
2013/05/25 16:41:35 1 Memory 3 849254356 671556032 67584 671556032 0
2013/05/25 16:41:36 1 Request : 19
2013/05/25 16:41:36 1 Memory 1 849254356 537335776 67584 537335776
2013/05/25 16:41:36 1 Memory 2 849254356 671554768 67584 671554768
2013/05/25 16:41:36 1 Memory 3 849254356 671556032 67584 671556032 0
2013/05/25 16:41:37 1 Request : 20
2013/05/25 16:41:37 1 Memory 1 849254356 537335776 67584 537335776
2013/05/25 16:41:37 1 Memory 2 849254356 671554768 67584 671554768
2013/05/25 16:41:37 1 Memory 3 849254356 671556032 67584 671556032 0
2013/05/25 16:41:37 1 Request : 21
2013/05/25 16:41:37 1 Memory 1 849254356 537334376 67584 537334376
2013/05/25 16:41:37 1 Request : 22
2013/05/25 16:41:37 1 Memory 1 849254356 671561056 67584 671561056
2013/05/25 16:41:37 1 Memory 2 849254356 671562320 67584 671562320
2013/05/25 16:41:37 1 Memory 3 1000249300 805781416 67584 805781416 0
2013/05/25 16:41:37 1 Memory 2 1000249300 805780136 67584 805780136
2013/05/25 16:41:37 1 Memory 3 1000249300 671552240 67584 671552240 0
2013/05/25 16:41:37 1 Request : 23
2013/05/25 16:41:37 1 Memory 1 1000249300 671552096 67584 671552096
2013/05/25 16:41:37 1 Request : 24
2013/05/25 16:41:37 1 Memory 1 1000249300 805778552 67584 805778552
2013/05/25 16:41:37 1 Memory 2 1000249300 805778656 67584 805778656
runtime: out of memory: cannot allocate 134217728-byte block (806354944 in use)
fatal error: out of memory
goroutine 14 [running]:
[fp=0x330414fc] runtime.throw(0x6c4445)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/runti
me/panic.c:473 +0x65
[fp=0x3304152c] runtime.mallocgc(0x8000000, 0x1, 0x1, 0x1)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/runti
me/zmalloc_windows_386.c:60 +0x308
[fp=0x3304154c] makeslice1(0x540c40, 0x8000, 0x8000, 0x33041580)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/runti
me/slice.c:61 +0x7f
[fp=0x3304156c] runtime.makeslice(0x540c40, 0x8000, 0x0, 0x8000, 0x0, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/runti
me/slice.c:34 +0x9c
[fp=0x33041690] main.API(0x123a26c0, 0x1237c500, 0x12382af0)
        C:/Users/Ronak/Desktop/test1/test.go:25 +0x273
[fp=0x330416a0] net/http.HandlerFunc.ServeHTTP(0x5e78b8, 0x123a26c0, 0x1237c500,
 0x12382af0)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1149 +0x3b
[fp=0x330416bc] net/http.(*ServeMux).ServeHTTP(0x1238cbe0, 0x123a26c0, 0x1237c50
0, 0x12382af0)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1416 +0xdc
[fp=0x330416dc] net/http.serverHandler.ServeHTTP(0x12379600, 0x123a26c0, 0x1237c
500, 0x12382af0)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1517 +0x120
[fp=0x330417d4] net/http.(*conn).serve(0x123c6af0)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1096 +0x652
[fp=0x330417d8] runtime.goexit()
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/runti
me/proc.c:1223
created by net/http.(*Server).Serve
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1564 +0x241
goroutine 1 [select]:
net.(*ioSrv).ExecIO(0x12330518, 0x123a24c0, 0x12392900, 0x0, 0x0, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/f
d_windows.go:236 +0x664
net.(*netFD).accept(0x123a4100, 0x5e793c, 0x0, 0x0, 0x0, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/f
d_windows.go:644 +0x325
net.(*TCPListener).AcceptTCP(0x12330db0, 0x3d0000, 0x409cfb, 0x409ebe)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/t
cpsock_posix.go:229 +0x41
net.(*TCPListener).Accept(0x12330db0, 0x0, 0x411bfe, 0x1238b044, 0x3235168c, ...
)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/t
cpsock_posix.go:239 +0x28
crypto/tls.(*listener).Accept(0x123d0780, 0x0, 0x0, 0x0, 0x0, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/crypt
o/tls/tls.go:46 +0x4d
net/http.(*Server).Serve(0x12379570, 0x123cf4a0, 0x123d0780, 0x0, 0x0, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1542 +0x6c
net/http.(*Server).ListenAndServeTLS(0x12379570, 0x5b25d8, 0xd, 0x5b25f8, 0xc, .
..)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1668 +0x207
net/http.ListenAndServeTLS(0x5a0208, 0x5, 0x5b25d8, 0xd, 0x5b25f8, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1630 +0x7a
main.main()
        C:/Users/Ronak/Desktop/test1/test.go:66 +0x17a
goroutine 2 [syscall]:
goroutine 4 [select]:
net.(*ioSrv).ExecIO(0x12330518, 0x123a24c0, 0x12392d80, 0x0, 0x0, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/f
d_windows.go:236 +0x664
net.(*netFD).accept(0x123ad000, 0x5e793c, 0x0, 0x0, 0x0, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/f
d_windows.go:644 +0x325
net.(*TCPListener).AcceptTCP(0x12330538, 0x438e01, 0x32364f24, 0x438e01)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/t
cpsock_posix.go:229 +0x41
net.(*TCPListener).Accept(0x12330538, 0x123cc280, 0x12330660, 0x123c6af0, 0x0, .
..)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/t
cpsock_posix.go:239 +0x28
net/http.(*Server).Serve(0x12379600, 0x123a24a0, 0x12330538, 0x0, 0x0, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1542 +0x6c
net/http.(*Server).ListenAndServe(0x12379600, 0x12379600, 0x0)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1532 +0x83
net/http.ListenAndServe(0x5a01f8, 0x5, 0x0, 0x0, 0x0, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1597 +0x5a
main.func┬╖001()
        C:/Users/Ronak/Desktop/test1/test.go:57 +0x39
created by main.main
        C:/Users/Ronak/Desktop/test1/test.go:63 +0x145
goroutine 5 [runnable]:
syscall.Syscall6(0x75ec9a8c, 0x5, 0xc0, 0x1237e800, 0x12330608, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/runti
me/zsyscall_windows_windows_386.c:97 +0x49
syscall.GetQueuedCompletionStatus(0xc0, 0x1237e800, 0x12330608, 0x12330600, 0xff
ffffff, ...)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/sysca
ll/zsyscall_windows_386.go:507 +0x7e
net.(*resultSrv).Run(0x12330510)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/f
d_windows.go:150 +0x11a
created by net.startServer
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/f
d_windows.go:285 +0xde
goroutine 13 [running]:
main.API(0x123a26c0, 0x1237c6c0, 0x123e0e70)
        C:/Users/Ronak/Desktop/test1/test.go:29 +0x439
net/http.HandlerFunc.ServeHTTP(0x5e78b8, 0x123a26c0, 0x1237c6c0, 0x123e0e70)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1149 +0x3b
net/http.(*ServeMux).ServeHTTP(0x1238cbe0, 0x123a26c0, 0x1237c6c0, 0x123e0e70)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1416 +0xdc
net/http.serverHandler.ServeHTTP(0x12379600, 0x123a26c0, 0x1237c6c0, 0x123e0e70)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1517 +0x120
net/http.(*conn).serve(0x123c6b40)
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1096 +0x652
created by net/http.(*Server).Serve
        C:/Users/ADMINI~1/AppData/Local/Temp/2/bindist664137607/go/src/pkg/net/h
ttp/server.go:1564 +0x241
exit status 2

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Michael T. Jones | Chief Technology Advocate  | m...@google.com |  +1 650-335-5765

Rémy Oudompheng

unread,
May 25, 2013, 7:54:41 AM5/25/13
to Raheel Gupta, golang-nuts
On 2013/5/25 <rahe...@gmail.com> wrote:
>>> You are just confusing the garbage collector for no reason. There are
>>> limitations and memory usage will not drop unless you start tweaking
>>> things manually, which is hard and not a good idea.
>>> What is the thing you are actually trying to solve?
> I am trying to write a high performance server which handles a lot of Data
> and Connections and hence memory management is crucial.
> I am not confused with the GC, but rather surprised of the absence of
> functions to free memory.

I am not saying that you are confused, I am saying that you make the
GC confused.

> There are many applications which handle many connections and allocate
> memory according and after the connection is over, they free the memory.

In which language?

> Unfortunately I havent been able to do so in GO. Once you reach a certain
> memory usage in Go it will calculate and ask for memory from the system.
> So if I allocate 128 MB, the Go runtime will ask the system for much more
> which defeats the purpose many times.
> I simply want to achieve :
> 1) When I allocate X amount of memory, Go shouldnt ask for 2X or 3X from the
> system and if it does ask the higher amount of RAM from the system it should
> return it when not needed. Unfortunately the GC or the runtime isnt smart
> enough to understand that.

People have worked hard to improve things. Do you have additional suggestions?

> 2) When I want to free the memory, I should be able to by some or the other
> way.

I have no idea how such a thing would be possible. Do you know how it
could be done? There are possibilities to free things automatically,
but dooing it manually contradicts the memory safety promise.

> If I am writing a commercial product or even an open source one, people
> wouldnt like to see higher memory usage right ?

People don't like memory usage, but not everyone actually cares
precisely. If people care enough about gaining a few megabytes of
memory, they will work on improving things.

> I would seriously like to request the "free" memory feature as you have in
> C/C++
>
> The GC is great but having an additional explicit call to free memory is
> nothing wrong I believe.

It's not about being wrong, but about being possible.

Rémy.

Rémy Oudompheng

unread,
May 25, 2013, 8:22:28 AM5/25/13
to Raheel Gupta, golang-nuts
On 2013/5/25 <rahe...@gmail.com> wrote:
>>> It's not about being wrong, but about being possible.
> Are you saying the people who maintain and develop GO couldnt add a simple
> function similar to C's "free" function ?
>

I think it violates memory safety of Go programs.

You seem to disagree: so please explain how such a function would be
implemented.

Rémy.

Michael Jones

unread,
May 25, 2013, 8:28:07 AM5/25/13
to rahe...@gmail.com, golang-nuts
The role of free() is implicit in Go's automatic memory management. 

If you are really eager to stop using unlinked Go allocations within Go's arena of memory allocated from the operating system, you can force a garbage collection. The result of a forced GC is not to reduce how much VM the OS has set for the Go runtime, but to reduce how much of that VM is physically active.

Thus my earlier question for you. Do you want to make sure that an object is not referenced (unlinked) so that the underlying real memory can be reused in future allocations (in which case just make sure there are no pointers to it) or do you want to try to force Go to tell the operating system "nevermind, I don't need so much potentially usable memory any more." There is no way to say the latter since in general there may be live allocations anywhere inside the VM range allocated by the operating system. 


On Sat, May 25, 2013 at 5:17 AM, <rahe...@gmail.com> wrote:
>> In which language?
C/C++. There are hundreds of servers written in c/c++ which handle lots of data across the network and their memory usage scales upwards and also scales downwards when not needed (independent of a GC)


>> People have worked hard to improve things. Do you have additional suggestions?
Yes, please add something similar to C/C++ "free" call. And also allow programmers to have the option to have the GC enabled or not. 


>>I have no idea how such a thing would be possible. Do you know how it
>>could be done? There are possibilities to free things automatically,
>>but dooing it manually contradicts the memory safety promise.
I think you are not getting what I am requesting sir. I simply look forward to a function like "free" in the C compiler to be implemented in GO.
It would be a great addition.
 
>> People don't like memory usage, but not everyone actually cares
>> precisely. If people care enough about gaining a few megabytes of
>> memory, they will work on improving things.
That is because they trust the programmers who develop the apps will be looking after that. How should I write an application in Go if the memory usage can literally cause the application to crash ?

>> It's not about being wrong, but about being possible.
Are you saying the people who maintain and develop GO couldnt add a simple function similar to C's "free" function ?
 

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Michael Jones

unread,
May 25, 2013, 8:31:08 AM5/25/13
to Raheel Gupta, golang-nuts

On Sat, May 25, 2013 at 5:28 AM, Michael Jones <m...@google.com> wrote:
to stop using

...by "to stop using" I mean "to make sure it is understood that this memory (holding some variable, array, etc.) no longer need be reserved for you because you'll not be accessing it again in any goroutine."

unread,
May 25, 2013, 8:32:20 AM5/25/13
to golan...@googlegroups.com, rahe...@gmail.com
On Saturday, May 25, 2013 11:14:13 AM UTC+2, rahe...@gmail.com wrote:
Here is the code attached. I am on a Windows 7 64 Bit OS but running the 32 Bit version of GO 1.1. Also my code uses mattns SQLite package with cgo.
 
In my package I have copied the http package of Go 1.1 and placed it in my folder. Actually the http package is my main code base. The file http/test.go has the main codes to get started. <snip>
There are many a times the memory utilization is much bad and at times it can survive even 50+ requests. 
Note : If you dont have pkg-config and sqlite3.dll you may comment out the SQLite code. But then it will not be a CGO compilation.

I am able to reproduce the issue on 32-bit linux and have identified one of its causes. It seems the issue can be fixed (unless it turns out there are other causes I haven't uncovered).

unread,
May 25, 2013, 9:26:42 AM5/25/13
to golan...@googlegroups.com, rahe...@gmail.com
On Saturday, May 25, 2013 1:33:24 PM UTC+2, rahe...@gmail.com wrote:
>> You are just confusing the garbage collector for no reason. There are
>> limitations and memory usage will not drop unless you start tweaking
>> things manually, which is hard and not a good idea.
>> What is the thing you are actually trying to solve?
I am trying to write a high performance server which handles a lot of Data and Connections and hence memory management is crucial.
I am not confused with the GC, but rather surprised of the absence of functions to free memory.
There are many applications which handle many connections and allocate memory according and after the connection is over, they free the memory.
Unfortunately I havent been able to do so in GO. Once you reach a certain memory usage in Go it will calculate and ask for memory from the system.
So if I allocate 128 MB, the Go runtime will ask the system for much more which defeats the purpose many times.

In my opinion, a more accurate formulation would be: The runtime is asking for additional 128 MB from the system.

When in a 32-bit mode, allocating large chunks of memory (more than 1 MB) increases the probability that the garbage collector will fail to free the large memory block. It is safer to allocate a larger number of smaller objects than to allocate a single huge object.
 
I simply want to achieve :
1) When I allocate X amount of memory, Go shouldnt ask for 2X or 3X from the system and if it does ask the higher amount of RAM from the system it should return it when not needed.

I believe you are asking too much from the language implementation. Automatic memory management (without reference counting) may be a more complicated problem than you currently think.

Maybe you are thinking about specific cases and then you are subconsciously extending conclusions from the specific cases to the most general case.

Unfortunately the GC or the runtime isnt smart enough to understand that.

It is also a compiler problem.

2) When I want to free the memory, I should be able to by some or the other way.

In a (safe) garbage collected language, the substitute for the C statement "free(p)" is "p=nil". "free(p)" would free the memory immediately, but it unsafe.

Today there does not exist any compiler+runtime of a safe garbage collected language that would be able to readily convert a standalone "p=nil" into the C-like "free(p)". Unless you are going to develop or to help to develop such a compiler+runtime you will need to accept this as a fact that you cannot change.

If I am writing a commercial product or even an open source one, people wouldnt like to see higher memory usage right ?
I would seriously like to request the "free" memory feature as you have in C/C++
 
The GC is great but having an additional explicit call to free memory is nothing wrong I believe.
 

Michael Jones

unread,
May 25, 2013, 9:30:20 AM5/25/13
to Raheel Gupta, golang-nuts
Mr/Ms Electron orbit reports discovery of a problem. That suggests that you may have some good news soon.

On the other point, it is like this:

Pretend that your (C/C++) program starts with no extra memory. Then you call malloc(X). What the friends-of-Malloc do is that ask the operating system to give your program some more memory. This is a major request, so instead of asking for X bytes, they ask for 100X or round X up to a megabyte, or some such. The result is a pool or arena from which malloc()/calloc/.. can service your future requests. 

If you never call free(), then when you make a future request of malloc() for at least one byte more than it can give, it goes back to the OS to ask for another chunk of memory. On the other hand, if you've finished using some of those earlier malloc(), and have called free() to say so, then malloc() will look through the "holes" in it's list of freed allocations and satisfy your request from there. If you use and free consistently, then the eventual state is that the operating system only ever gives malloc's infrastructure as much memory as your peak simultaneous need. It is not quite this tight, but that's the idea.

In Go, even without any way to explicitly free, the behavior is nearly identical. What's different is when the "free()" happens and who calls it. What happens is that each equivalent of malloc() allocates from the empty end of the memory arena until there is not enough free space left for the requested allocation. Then, before going to the OS to ask for more, it does a garbage collection. That is, there is a determination of the in-use status of every allocation in the existing pools. If any of these are no longer accessible (a pointer to them is not held in any active data structure) then the GC function does exactly what a C/C++ free() would do with that allocation -- marking it as available for reuse. After this epochal, universal, orgy of calling free() on absolutely proven without possibility of error former allocations, the equivalent of malloc() again tries to find room (from the newly freed former allocations) for your new request. If there is room, then the request is satisfied immediately. If not, then the OS is asked for more memory. 

In general these two approaches should use a similar amount of memory, but the way they use it is different. In the immediately-free-as-soon-as-possible world, the program infrequently gets to the "all full" situation, but when it does, it always needs to ask for more from the OS. In the keep-allocating-until-you-reach-the-end style of Go, the initial OS region is filled before the garbage collection process is initiated. If you could chart the memory activity levels, they would both show a sawtooth function for active allocations, but the C/C++ style would jump down in steps of individual allocations within an arena with the average level slowly increasing until the next arena-growth request of the OS, while the Go version would grow steadily to arena-size then take a single big jump down, then grow to the limit, and take a smaller jump down, and so on until such time as there was no more room and then the arena would be grown by request to the OS.

I, to, wish there was a way to free incrementally since there is often a clear boundary at which a set of prior allocation could be easily known to be recyclable. By having logical groupings the process could be more efficient. The problem is that unless the compiler can intuit this magically, the runtime cannot trust you when you say that some memory is now safe to free. The integrity of the entire system is predicated on there never being a single mistake, and since people often make mistakes with C/C++ free() calls, Go simply can't take your word for it.

On the virtual vs. real front, the arenas that free() and Go's allocators request from the OS are generally an arbitrary reservation in virtual memory space but until that memory is used, there is no real action in terms of real memory. For example, If I ask for a megabyte but touch a byte, that really means that certain data structure in the virtual memory hardware are updated by the OS to say "michael is allowed to write from here to here+1MB, and when he does, find some real memory for him to use." Even so, if I write 1 byte then it's 1 byte (actually, 1  VM page) that gets used in physical memory. If i'd asked for a gigabyte and just used a byte, only the internal page table data structures would be changed. The actual events in RAM would not be changed. However, the memory stats would change, and I suspect that people would be writing to the mailing list asking why their little program needed a GB in Go, a MB in C, and a byte in assembler. The truth is that they'd all be using "a byte" but just be variously generous about the size of their virtual reservations. That's why it is important to track actual physical memory use. (Subtly, it is also why the GC process should not wait until an arena is full. ;-)

Michael


On Sat, May 25, 2013 at 5:57 AM, <rahe...@gmail.com> wrote:

On Saturday, May 25, 2013 6:02:20 PM UTC+5:30, ⚛ wrote:
I am able to reproduce the issue on 32-bit linux and have identified one of its causes. It seems the issue can be fixed (unless it turns out there are other causes I haven't uncovered).
 
 
So what is the cause for the same ? How can it be fixed ?
 
>> Thus my earlier question for you. Do you want to make sure that an object is not referenced (unlinked) so that the
>> underlying real memory can be reused in future allocations (in which case just make sure there are no pointers to it) or
>> do you want to try to force Go to tell the operating system "nevermind, I don't need so much potentially usable memory
>> any more." There is no way to say the latter since in general there may be live allocations anywhere inside the
>> VM range allocated by the operating system.
 
I am not a big expert as you guys are :)
In C when you use the "free" command, what does that do ? Couldnt something similar be implemented in Go ?
At the moment, forcing the GC to run clears the memory usage by which I mean the MemStats.Alloc drops but the MemStats.Sys doesnt drop. I think both should drop. The runtime asks too much memory from the Operating system which causes the application to crash in my example (where the Private Bytes shoots as high as 1.1 GB the MemStats.Alloc also doesnt drop on Windows and grows alarmingly high). How should I prevent the application to crash in such a case ?
I have made sure there is no pointer to the slice and also the function finishes after making a call to GC. The code I am have posted uses the http package shipped with Go 1.1 (I have posted 2 examples : one where I make a copy of the HTTP package in my folder and the other where I simply use the http package from go's src folder)
Both tests results in crashing of the application because the memory used by the runtime never frees it.
 
@Micheal, please do test the package and let me know if my observations are wrong regarding the runtime and GC.
 

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

unread,
May 25, 2013, 9:33:27 AM5/25/13
to golan...@googlegroups.com, rahe...@gmail.com
On Saturday, May 25, 2013 2:57:09 PM UTC+2, rahe...@gmail.com wrote:

On Saturday, May 25, 2013 6:02:20 PM UTC+5:30, ⚛ wrote:
I am able to reproduce the issue on 32-bit linux and have identified one of its causes. It seems the issue can be fixed (unless it turns out there are other causes I haven't uncovered).
 
 
So what is the cause for the same ? How can it be fixed ?

I plan to submit a patch to golang-dev. Please wait a few days. 

Dave Cheney

unread,
May 26, 2013, 11:39:40 PM5/26/13
to rahe...@gmail.com, golan...@googlegroups.com, Raheel Gupta
With respect, you are confusing memory that Go reserves from the operating system with the heap usage inside a Go program. Currently, on windows platforms, Go cannot return unused heap memory to the operating system even when it is freed internally by the garbage collector. 



On 27/05/2013, at 13:33, rahe...@gmail.com wrote:

I tested a small piece of code in C++ (Qt 4.8) :
unsigned char * test = (unsigned char *)malloc(134217728);
this->sleep(10);
free(test);
 
This works like a beauty (I am sorry I am exaggerating at this point).
It takes 128 MB ram and when freed returns back to its original usage.
 
I would seriously like to Question the design of GO's memory management.
I have observed that the similar piece of code in GO will shoot the usage upto 450 MB 
and even after a considerable time it doesnt return the memory ?
I wonder if people will ever like to use go in such a case. The language is great, 
but its memory management is by far very unstable.
 
I have written considerable amount of code in GO for a project of mine 
spending nearly 6 months of sleepless nights.
Is there absolutely no way to reduce the memory usage ?
I am writing an enterprise application and such unpredicted memory usage will force me 
to port the code to QT/C++.
The main issue is that the application also CRASHES as the MemoryStats.Sys is 
only going upwards and never downwards.Please help me anybody, I really like GO, and dont want to shift.

andrey mirtchovski

unread,
May 26, 2013, 11:43:29 PM5/26/13
to rahe...@gmail.com, golang-nuts
> Please help me anybody

That's not how we spell Obi-Wan Kenobi around here.

HTH

Dan Kortschak

unread,
May 26, 2013, 11:44:30 PM5/26/13
to rahe...@gmail.com, golan...@googlegroups.com
I use Go to perform fairly memory intensive problems (at the moment I am
performing analyses on large sets of genomic sequence data - the
programs end up with 50GB allocated in internal data representations,
allocating and deallocating 100GB of input data). I've never had a
problem with memory handling.

Michael Jones

unread,
May 26, 2013, 11:56:55 PM5/26/13
to Dave Cheney, Raheel Gupta, golang-nuts

I mentioned the virtual != real point early on, but it did not attract the notice of the OP.

Tamás Gulácsi

unread,
May 27, 2013, 1:37:18 AM5/27/13
to golan...@googlegroups.com
Why do you allocate (and throw away) so much memory? If its a problem, use a leaky channel for buffer reuse.
Are you sure the gc can free that memory (not leaving pointers to it)?

Carlos Castillo

unread,
May 27, 2013, 3:49:49 AM5/27/13
to golan...@googlegroups.com, rahe...@gmail.com
Similarly, I've noticed that on OS X memory is never "Freed" either. Memory collected by either the Scavenger, or by runtime/debug.FreeOSMemory is added to the "Released" stats, but the "Sys" value doesn't shrink, nor does the OS get back any memory.

The only thing I notice after a large FreeOSMemory() Collection is that the memory moves from "Active Memory" to "Inactive Memory" in the system stats, which AFAIK means that go is telling the OS that it won't be using it for a while, so the OS is free to page it out if it needs memory. I think it still uses up swap space though, since the OS still must preserve the contents of the pages, as opposed to "Free" memory where the OS can use the page immediately.

Dave Cheney

unread,
May 27, 2013, 3:57:13 AM5/27/13
to Carlos Castillo, golan...@googlegroups.com, rahe...@gmail.com
Please do not confuse what Go is doing in telling the operating system that a page is not needed with the resulting reaction of the operating system. 

The Sys value is not affected by FreeOSMemory, it is a counter of pages requested from the operating system, not pages that hold active data. 

From my knowledge of the OS X vm system, marking a page as inactive is the correct behaviour. If OS X handles that badly, there isn't much user space can do about it. 

minux

unread,
May 27, 2013, 7:32:48 AM5/27/13
to Carlos Castillo, golan...@googlegroups.com, rahe...@gmail.com
On Mon, May 27, 2013 at 3:49 PM, Carlos Castillo <cook...@gmail.com> wrote:
Similarly, I've noticed that on OS X memory is never "Freed" either. Memory collected by either the Scavenger, or by runtime/debug.FreeOSMemory is added to the "Released" stats, but the "Sys" value doesn't shrink, nor does the OS get back any memory.
yes, Sys value won't even shrink. released memory will be accounted to Released
(note: only Unix systems support really releasing those memory to the OS).

The only thing I notice after a large FreeOSMemory() Collection is that the memory moves from "Active Memory" to "Inactive Memory" in the system stats, which AFAIK means that go is telling the OS that it won't be using it for a while, so the OS is free to page it out if it needs memory. I think it still uses up swap space though, since the OS still must preserve the contents of the pages, as opposed to "Free" memory where the OS can use the page immediately.
No, Go tells the kernel that it doesn't need the pages anymore, and the kernel is free to
*not* preserve its content and when Go uses those pages again, it's happy to get fresh
zero pages.

Those freed pages need not be backed by swap.

Carlos Castillo

unread,
May 27, 2013, 8:17:58 AM5/27/13
to minux, golang-nuts, rahe...@gmail.com
If it indeed is the case that no swap is needed to preserve the pages "released" by go, then the only real problem is perceptual.

I can write a C program that does a bunch of mallocs, followed by a bunch of frees, and if done correctly the OS reports that it has more "free" memory, and my program's "Real Memory" shrinks. The way go releases the memory, it's almost functionally identical (no swap use, easily re-claimed), but it is not "Free" memory, nor does my program's RSIZE shrink, unless the OS needs the memory.

Does this arrangement mean that the go runtime needs less effort (read: fewer / cheaper syscalls) to re-use the memory than for the original allocation?

PS: I never really had a problem myself with the way go manages memory, especially when I make the effort to make it easier for the garbage collector. I suspected most of the above, except the swap, which now makes go's decision look even better.
--
Carlos Castillo

minux

unread,
May 27, 2013, 8:25:45 AM5/27/13
to Carlos Castillo, golang-nuts, rahe...@gmail.com
On Mon, May 27, 2013 at 8:17 PM, Carlos Castillo <cook...@gmail.com> wrote:
If it indeed is the case that no swap is needed to preserve the pages "released" by go, then the only real problem is perceptual.
the OP talks about windows, where Go runtime lacks this functionality.

Does this arrangement mean that the go runtime needs less effort (read: fewer / cheaper syscalls) to re-use the memory than for the original allocation?
yes, i think so. in theory we can map those pages of memory as 0 permission (no read, no write, no execute),
but just hinting the OS that we've done with those pages (with madvise(1)) is easier and we don't need to do
anything special to reuse that memory (we only need to assume the memory might be zeroed or not, while new
memory allocated/mapped will always be zeroed.)

in fact, if we want to implement the functionality on windows, i'm afraid we do need to unmap (decommit) the
memory so that OS's private memory statistics for the process could be lowered.

Michael Jones

unread,
May 27, 2013, 9:42:08 AM5/27/13
to Carlos Castillo, minux, golang-nuts, rahe...@gmail.com
This is the real !=virtual issue. The memory statistic to track is "how much is available for other programs" and that is an OS statistic about the system rather than about the executing program.


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

minux

unread,
May 27, 2013, 12:23:55 PM5/27/13
to kevinc...@gmail.com, golan...@googlegroups.com, Carlos Castillo, rahe...@gmail.com


On Tue, May 28, 2013 at 12:11 AM, <kevinc...@gmail.com> wrote:

On Monday, May 27, 2013 8:25:45 AM UTC-4, minux wrote:

yes, i think so. in theory we can map those pages of memory as 0 permission (no read, no write, no execute),
but just hinting the OS that we've done with those pages (with madvise(1)) is easier and we don't need to do
anything special to reuse that memory (we only need to assume the memory might be zeroed or not, while new
memory allocated/mapped will always be zeroed.)

in fact, if we want to implement the functionality on windows, i'm afraid we do need to unmap (decommit) the
memory so that OS's private memory statistics for the process could be lowered.

That is a rather strange claim to make. What you describe as being done with madvise can be done on windows by using the MEM_RESET
flag for VirtualAlloc.  
I've tried that, but the private bytes counter doesn't change.

That flag means treat this memory region as though it were newly committed, and therefore will not get swapped to a pagefile, but will simply
be dropped if windows want to use the memory for something else. When you try to use the memory again, it might be zeroed, or might still
have the old values if the page was never ejected from physical memory.

Whether windows reflects this in any memory statistics, I don't know.
from my experiments, it is not reflected in memory statistics, so it's a not solution to
OP's problem. 

Dmitry Vyukov

unread,
May 27, 2013, 1:41:33 PM5/27/13
to minux, kevinc...@gmail.com, golang-nuts, Carlos Castillo, rahe...@gmail.com
On Mon, May 27, 2013 at 8:23 PM, minux <minu...@gmail.com> wrote:

On Monday, May 27, 2013 8:25:45 AM UTC-4, minux wrote:

yes, i think so. in theory we can map those pages of memory as 0 permission (no read, no write, no execute),
but just hinting the OS that we've done with those pages (with madvise(1)) is easier and we don't need to do
anything special to reuse that memory (we only need to assume the memory might be zeroed or not, while new
memory allocated/mapped will always be zeroed.)

in fact, if we want to implement the functionality on windows, i'm afraid we do need to unmap (decommit) the
memory so that OS's private memory statistics for the process could be lowered.

That is a rather strange claim to make. What you describe as being done with madvise can be done on windows by using the MEM_RESET
flag for VirtualAlloc.  
I've tried that, but the private bytes counter doesn't change.


Does VirtualFree(MEM_DECOMMIT) followed by VirtualAlloc(MEM_COMMIT) do?

 

That flag means treat this memory region as though it were newly committed, and therefore will not get swapped to a pagefile, but will simply
be dropped if windows want to use the memory for something else. When you try to use the memory again, it might be zeroed, or might still
have the old values if the page was never ejected from physical memory.

Whether windows reflects this in any memory statistics, I don't know.
from my experiments, it is not reflected in memory statistics, so it's a not solution to
OP's problem. 

--

minux

unread,
May 27, 2013, 1:47:49 PM5/27/13
to Dmitry Vyukov, kevinc...@gmail.com, golang-nuts, Carlos Castillo, rahe...@gmail.com
On Tue, May 28, 2013 at 1:41 AM, Dmitry Vyukov <dvy...@google.com> wrote:
On Mon, May 27, 2013 at 8:23 PM, minux <minu...@gmail.com> wrote:

On Monday, May 27, 2013 8:25:45 AM UTC-4, minux wrote:

yes, i think so. in theory we can map those pages of memory as 0 permission (no read, no write, no execute),
but just hinting the OS that we've done with those pages (with madvise(1)) is easier and we don't need to do
anything special to reuse that memory (we only need to assume the memory might be zeroed or not, while new
memory allocated/mapped will always be zeroed.)

in fact, if we want to implement the functionality on windows, i'm afraid we do need to unmap (decommit) the
memory so that OS's private memory statistics for the process could be lowered.

That is a rather strange claim to make. What you describe as being done with madvise can be done on windows by using the MEM_RESET
flag for VirtualAlloc.  
I've tried that, but the private bytes counter doesn't change.
Does VirtualFree(MEM_DECOMMIT) followed by VirtualAlloc(MEM_COMMIT) do?
Do you mean we write these two lines in runtime·SysUnused:
runtime·stdcall(runtime·VirtualFree, 3, v, (uintptr)0, (uintptr)MEM_RELEASE)
runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)(MEM_COMMIT|MEM_RESERVE), (uintptr)PAGE_EXECUTE_READWRITE);

Haven't tried that, seems a possible solution.
Will try tomorrow when i get to a windows machine.

Dmitry Vyukov

unread,
May 27, 2013, 1:55:36 PM5/27/13
to minux, kevinc...@gmail.com, golang-nuts, Carlos Castillo, rahe...@gmail.com
On Mon, May 27, 2013 at 9:47 PM, minux <minu...@gmail.com> wrote:
On Monday, May 27, 2013 8:25:45 AM UTC-4, minux wrote:

yes, i think so. in theory we can map those pages of memory as 0 permission (no read, no write, no execute),
but just hinting the OS that we've done with those pages (with madvise(1)) is easier and we don't need to do
anything special to reuse that memory (we only need to assume the memory might be zeroed or not, while new
memory allocated/mapped will always be zeroed.)

in fact, if we want to implement the functionality on windows, i'm afraid we do need to unmap (decommit) the
memory so that OS's private memory statistics for the process could be lowered.

That is a rather strange claim to make. What you describe as being done with madvise can be done on windows by using the MEM_RESET
flag for VirtualAlloc.  
I've tried that, but the private bytes counter doesn't change.
Does VirtualFree(MEM_DECOMMIT) followed by VirtualAlloc(MEM_COMMIT) do?
Do you mean we write these two lines in runtime·SysUnused:
runtime·stdcall(runtime·VirtualFree, 3, v, (uintptr)0, (uintptr)MEM_RELEASE)
runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)(MEM_COMMIT|MEM_RESERVE), (uintptr)PAGE_EXECUTE_READWRITE);


I mean MEM_DECOMMIT/MEM_COMMIT. Otherwise, another thread can allocate that memory in between MEM_RELEASE/MEM_RESERVE.

brainman

unread,
May 27, 2013, 7:30:03 PM5/27/13
to golan...@googlegroups.com, kevinc...@gmail.com, Carlos Castillo, rahe...@gmail.com
On Tuesday, 28 May 2013 02:23:55 UTC+10, minux wrote:

>> can be done on windows by using the MEM_RESET 
>> flag for VirtualAlloc. 
>I've tried that, but the private bytes counter doesn't change.

That is expected, because you are not uncommitting memory here. Commit charge still remains the way it is. You just telling the system that this memory does not need to be saved in swap file.

> Whether windows reflects this in any memory statistics, I don't know.
> from my experiments, it is not reflected in memory statistics ...

I have been playing with memory recently. You can do too. Here is something to start with http://play.golang.org/p/KjypOYjzTD. Also, you will need vmmap to see the effects.

> ... , so it's a not solution to OP's problem.

I suspect as much. But I don't really know what the problem is.

Alex

brainman

unread,
May 27, 2013, 9:00:27 PM5/27/13
to golan...@googlegroups.com, minux, Carlos Castillo, rahe...@gmail.com, kevinc...@gmail.com
On Tuesday, 28 May 2013 10:46:38 UTC+10, kevinc...@gmail.com wrote:
Thinking about things more.


I agree with most things you say about windows.

Just want to add that also "reserving" memory on windows counts towards commit charge count too. So even "reserving" virtual address space is not free on windows. The amount of commit charge is small proportionally to reserved size. But, if reservation is large, it will become more then noticeable. 64-bit go does reserves large chunks of memory, so it is another issue that needs to be resolved.

Alex

brainman

unread,
May 27, 2013, 9:38:06 PM5/27/13
to golan...@googlegroups.com, minux, Carlos Castillo, rahe...@gmail.com, kevinc...@gmail.com
On Tuesday, 28 May 2013 11:14:28 UTC+10, kevinc...@gmail.com wrote:

> Worrying about the extra page table contributions could come later if it even proves to be a realistic issue. ...

Oh, it is real alright. This program

package main

import (
        "time"
)

func main() {
        time.Sleep(time.Hour)
}

uses about 150MB of "committed" memory with 70MB of these attributed to "Page table" (I suspect it is effect of our "reserved" memory). For comparison, new "notepad" process takes about 40MB of "committed" memory. This is all on windows/amd64. windows/386 is not affected, because its memory reservations are small.

Alex

brainman

unread,
May 27, 2013, 11:19:11 PM5/27/13
to golan...@googlegroups.com, minux, Carlos Castillo, rahe...@gmail.com, kevinc...@gmail.com
On Tuesday, 28 May 2013 13:03:03 UTC+10, kevinc...@gmail.com wrote:

What I'm not sure is if pagetable size is realistically a problem. ...

It is for people who run many small (or large) Go programs simultaneously. Each process will have this overhead.

Alex 

minux

unread,
May 28, 2013, 7:02:31 AM5/28/13
to brainman, golan...@googlegroups.com, Carlos Castillo, rahe...@gmail.com, kevinc...@gmail.com
yeah, that's why we have a last-minute change to cap maximum heap size (thus the VM reservation)
to 32GiB instead of 128GiB as on other amd64 unix systems.

i don't think we can do anything about page table committed memory usage if we continue
to reserve that much memory.

minux

unread,
May 28, 2013, 2:10:18 PM5/28/13
to rahe...@gmail.com, golan...@googlegroups.com, Carlos Castillo, kevinc...@gmail.com

On Wed, May 29, 2013 at 2:08 AM, <rahe...@gmail.com> wrote:
I am not a real memory expert here and from what I understand I think people have somewhat managed to reproduce the bug that Go never returns the system memory to the OS. Is there any possibility to still be able to implement this in go 1.1 ?
perhaps you will have to wait for Go 1.2 (don't worry, only 6 months ahead).

Dave Cheney

unread,
May 29, 2013, 2:26:36 AM5/29/13
to Raheel Gupta, golang-nuts, Carlos Castillo, kevinc...@gmail.com
Go is an open source project, you can always build the source
yourself. http://golang.org/doc/install/source

On Wed, May 29, 2013 at 4:24 PM, <rahe...@gmail.com> wrote:
> I would like to test this before the official release so that we can start
> beta testing our own software.
> I wonder if I could be of any help as I do have all time access to all
> servers of Windows and Linux.
> And when will this patch be available ?
>
> On Tuesday, May 28, 2013 11:40:18 PM UTC+5:30, minux wrote
>>
>> perhaps you will have to wait for Go 1.2 (don't worry, only 6 months
>> ahead).
>

Dave Cheney

unread,
May 29, 2013, 2:45:57 AM5/29/13
to Raheel Gupta, golang-nuts, Carlos Castillo, kevinc...@gmail.com
> Yes, I am aware of that.
> But I am not aware of how to fix the issue.

Not to open old wounds, but you've still to convince us there is an issue.

> If anyone fixes this, please do let me know and I will test it.

The atom symbol recently comitted several changes to the garbage
collector which appear to be in response to your sample code.

At this point I think the best option is for you to raise an issue on
the issue tracker, golang.org/issue, and reference this discussion.

Dave Cheney

unread,
May 29, 2013, 3:03:21 AM5/29/13
to Raheel Gupta, golang-nuts, Carlos Castillo, kevinc...@gmail.com
>>> Not to open old wounds, but you've still to convince us there is an
>>> issue.
>
> But kevinc...@gmail.com did manage to reproduce the bug. If go ever reaches
> X amount of memory usage, it will never go down again. Arent you convinced
> this is wrong ?

I am not convinced, as I believe the behaviour is expected, as I
explained several times, Go programs on Windows do not return unused
memory to the Operating System. However I am not interested in my
view, only solving a potential bug.

> Which files were this comitted to ? I would like to check this. I am sorry
> but I really havent played with GO Source itself, hence I am asking you
> this.

This change, https://code.google.com/p/go/source/detail?r=e6c4fa4c0c25287077d7a6dfc25458ee96332715,
I think is the one Atom was referring to.

Dmitry Vyukov

unread,
May 29, 2013, 3:04:19 AM5/29/13
to Raheel Gupta, golang-nuts, Carlos Castillo, Kevin Cathcart
On Wed, May 29, 2013 at 10:56 AM, <rahe...@gmail.com> wrote:
>> Not to open old wounds, but you've still to convince us there is an issue.
 
But kevinc...@gmail.com did manage to reproduce the bug. If go ever reaches X amount of memory usage, it will never go down again. Arent you convinced this is wrong ?

What do you mean by "memory usage" here?
If you mean process virtual memory usage, then it's not a problem at all, this is what it's intended for.
If you mean resident memory, then OS can always take it back if needed w/o any support from Go runtime.




>> The atom symbol recently comitted several changes to the garbage
collector which appear to be in response to your sample code.
Which files were this comitted to ? I would like to check this. I am sorry but I really havent played with GO Source itself, hence I am asking you this.
--

brainman

unread,
May 29, 2013, 3:18:37 AM5/29/13
to golan...@googlegroups.com, Raheel Gupta, Carlos Castillo, Kevin Cathcart
On Wednesday, 29 May 2013 17:04:19 UTC+10, Dmitry Vyukov wrote:
On Wed, May 29, 2013 at 10:56 AM, <rahe...@gmail.com> wrote:
>> Not to open old wounds, but you've still to convince us there is an issue.
 
But kevinc...@gmail.com did manage to reproduce the bug. If go ever reaches X amount of memory usage, it will never go down again. Arent you convinced this is wrong ?

What do you mean by "memory usage" here?
If you mean process virtual memory usage, then it's not a problem at all, this is what it's intended for.
If you mean resident memory, then OS can always take it back if needed w/o any support from Go runtime.


Go "commits" memory to its process. Once "committed", Go does not releases that memory on windows. So OS cannot touch process "committed" memory, the best it can do is save it into swap file. If a Go program allocates a lot of memory for a small moment and the releases it, the memory will remain "commited" in the process until its death.


Alex

Dmitry Vyukov

unread,
May 29, 2013, 4:12:48 AM5/29/13
to Raheel Gupta, golang-nuts, Carlos Castillo, Kevin Cathcart
If Go frees that memory, pagecache will consume it. We must start by fixing pagecache in all OSes. 



On Wed, May 29, 2013 at 12:08 PM, <rahe...@gmail.com> wrote:
This is also the case in Linux. Even in linux the memory is not returned to the OS. As per my observations if a Go Program touches "X" MB or GB in Ram usage and even frees it by either the function exiting or you making the length of a slice to 0 again, the heap usage within the go program goes down after the GC. But the Ram it took from the OS is never ever returned. If the go program touches 1 GB in use, it will never return to the OS even though the MemStats report that the Alloc memory might be in 1-2 MBs. The remaining memory is held up by Go till the program quits.
 
To top it off, lets say if a program asks for 150 MB by making a byte slice of 150 MB, Go will ask nearly 2-3 times from the OS and hold it. Then lets say you remake the slice to a size of 0. When the size is made to 0, the memory usag reported by the Memstats.Alloc might be somewhere in KBs and the MemStats.Sys is nearly 300-450MB. When you remake the slice to a size of 150 MB, Go might (sometimes) still ask for more memory from the OS even though the it has 300-450 MB of unused memory. Eventually the application crashes saying it couldnt allocate more memory.
 
I have posted the codes in the earlier emails and anyone can test it. I found this behaviour on x86 and x86_64 versions of CentOS 6 and Windows 7.

Dmitry Vyukov

unread,
May 29, 2013, 4:44:49 AM5/29/13
to Raheel Gupta, golang-nuts, Carlos Castillo, Kevin Cathcart
There is no way to not return memory to OS. OS can take it back whenever it wants.


On Wed, May 29, 2013 at 12:36 PM, <rahe...@gmail.com> wrote:
I am not sure what you mean by that. Are you trying to say that this is the intended behaviour of Golang that if a go program asks for X amount of Memory then that go prog should never ever return that memory to the OS ? I find that pretty strange.

Dave Cheney

unread,
May 29, 2013, 5:20:30 AM5/29/13
to Raheel Gupta, golang-nuts, Carlos Castillo, Kevin Cathcart
On linux set the environment variable, GOGCTRACE=1, then look for
lines starting with svg, which indicate actions of the memory
scavenger. By default only wakes every 300 seconds to see if there are
any unpopulated heap pages which can be returned to the OS. It does
this by calling madvise, telling the OS that the memory backing that
virtual page is not needed and can be discarded _if_required_ (the
opposite of on demand paging).

This function has no direct analog on windows, so this facility is not
available on this platform.

On Wed, May 29, 2013 at 7:17 PM, <rahe...@gmail.com> wrote:
> Ok. By me writing "return to the OS" means that whatever method implied to
> mark the memory held by Go as "reusable" by the OS. ATM, the OS thinks the
> memory it gave to a GO program is in use. I have never seen the memory used
> by the go application being reused by the OS. Anyway to do that ?
>
> Also sir, did you try the code I have posted ?
> I have reported an issue here with the sample code to reproduce it :
> https://code.google.com/p/go/issues/detail?id=5584
>
> On Wednesday, May 29, 2013 2:14:49 PM UTC+5:30, Dmitry Vyukov wrote:
>>
>> There is no way to not return memory to OS. OS can take it back whenever
>> it wants
>

Dave Cheney

unread,
May 29, 2013, 8:50:57 AM5/29/13
to rahe...@gmail.com, golan...@googlegroups.com, Raheel Gupta, Carlos Castillo, Kevin Cathcart
You see the line where is says 0x80mb released? That is the best we can do. We tell the OS it is there if it needs it, and that is it. 



On 29/05/2013, at 22:47, rahe...@gmail.com wrote:

@Dave, here is the log.
The Golang app still doesnt let go of the extra ram it has.

gc1(1): 0+0+0 ms, 0 -> 0 MB 24 -> 26 (27-1) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
gc2(1): 0+0+0 ms, 0 -> 0 MB 4475 -> 411 (4504-4093) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
gc3(1): 0+0+0 ms, 0 -> 0 MB 5789 -> 413 (9883-9470) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
gc4(1): 0+0+0 ms, 0 -> 0 MB 5741 -> 414 (15212-14798) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
gc5(1): 0+0+0 ms, 0 -> 0 MB 5841 -> 414 (20640-20226) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
gc6(1): 0+0+0 ms, 0 -> 0 MB 5841 -> 414 (26068-25654) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:47:14 1 Request : 1
2013/05/29 11:47:14 1 Memory 1 7767920 619440 20480 619440
gc7(1): 0+0+0 ms, 128 -> 128 MB 2982 -> 493 (28637-28144) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:47:14 1 Memory 2 158762864 134692384 20480 134692384
2013/05/29 11:47:14 1 Memory 3 158762864 134692696 20480 134692696 0
gc8(1): 0+0+0 ms, 128 -> 0 MB 507 -> 499 (28652-28153) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:47:17 1 Request : 2
2013/05/29 11:47:17 1 Memory 1 158762864 491424 24576 491424
gc9(1): 0+0+0 ms, 128 -> 128 MB 579 -> 547 (28734-28187) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:47:20 1 Memory 2 158762864 134704544 24576 134704544
2013/05/29 11:47:20 1 Memory 3 158762864 134704632 24576 134704632 0
gc10(1): 0+0+0 ms, 128 -> 0 MB 559 -> 555 (28747-28192) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg0: inuse: 0, idle: 128, sys: 129, released: 0, consumed: 129 (MB)
2013/05/29 11:48:30 1 Request : 3
2013/05/29 11:48:30 1 Memory 1 158762864 531624 24576 531624
gc11(1): 0+0+0 ms, 128 -> 128 MB 625 -> 555 (28819-28264) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:30 1 Memory 2 158762864 134743256 24576 134743256
2013/05/29 11:48:30 1 Memory 3 158762864 134743344 24576 134743344 0
gc12(1): 0+0+0 ms, 128 -> 0 MB 567 -> 563 (28832-28269) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:30 1 Request : 4
2013/05/29 11:48:30 1 Memory 1 158762864 531824 24576 531824
gc13(1): 0+0+0 ms, 128 -> 128 MB 627 -> 555 (28898-28343) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:30 1 Memory 2 158762864 134743256 24576 134743256
2013/05/29 11:48:30 1 Memory 3 158762864 134743344 24576 134743344 0
gc14(1): 0+0+0 ms, 128 -> 0 MB 567 -> 563 (28911-28348) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:30 1 Request : 5
2013/05/29 11:48:30 1 Memory 1 158762864 531824 24576 531824
gc15(1): 0+0+0 ms, 128 -> 128 MB 627 -> 555 (28977-28422) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:30 1 Memory 2 158762864 134743256 24576 134743256
2013/05/29 11:48:30 1 Memory 3 158762864 134743344 24576 134743344 0
gc16(1): 0+0+0 ms, 128 -> 0 MB 567 -> 563 (28990-28427) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:30 1 Request : 6
2013/05/29 11:48:30 1 Memory 1 158762864 531824 24576 531824
gc17(1): 0+0+0 ms, 128 -> 128 MB 627 -> 555 (29056-28501) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Memory 2 158762864 134743256 24576 134743256
2013/05/29 11:48:31 1 Memory 3 158762864 134743344 24576 134743344 0
gc18(1): 0+0+0 ms, 128 -> 0 MB 567 -> 563 (29069-28506) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Request : 7
2013/05/29 11:48:31 1 Memory 1 158762864 532160 24576 532160
gc19(1): 0+0+0 ms, 128 -> 128 MB 629 -> 556 (29137-28581) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Memory 2 158762864 134743584 24576 134743584
2013/05/29 11:48:31 1 Memory 3 158762864 134743672 24576 134743672 0
gc20(1): 0+0+0 ms, 128 -> 0 MB 568 -> 564 (29150-28586) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Request : 8
2013/05/29 11:48:31 1 Memory 1 158762864 532488 24576 532488
gc21(1): 0+0+0 ms, 128 -> 128 MB 630 -> 559 (29218-28659) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Memory 2 158762864 134743928 24576 134743928
2013/05/29 11:48:31 1 Memory 3 158762864 134744016 24576 134744016 0
gc22(1): 0+0+0 ms, 128 -> 0 MB 571 -> 567 (29231-28664) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Request : 9
2013/05/29 11:48:31 1 Memory 1 158762864 532496 24576 532496
gc23(1): 0+0+0 ms, 128 -> 128 MB 632 -> 560 (29298-28738) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Memory 2 158762864 134744024 24576 134744024
2013/05/29 11:48:31 1 Memory 3 158762864 134744112 24576 134744112 0
gc24(1): 0+0+0 ms, 128 -> 0 MB 572 -> 568 (29311-28743) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Request : 10
2013/05/29 11:48:31 1 Memory 1 158762864 532592 24576 532592
gc25(1): 0+0+0 ms, 128 -> 128 MB 632 -> 559 (29377-28818) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Memory 2 158762864 134744016 24576 134744016
2013/05/29 11:48:31 1 Memory 3 158762864 134744104 24576 134744104 0
gc26(1): 0+0+0 ms, 128 -> 0 MB 571 -> 567 (29390-28823) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Request : 11
2013/05/29 11:48:31 1 Memory 1 158762864 532584 24576 532584
gc27(1): 0+0+0 ms, 128 -> 128 MB 631 -> 560 (29456-28896) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Memory 2 158762864 134744024 24576 134744024
2013/05/29 11:48:31 1 Memory 3 158762864 134744112 24576 134744112 0
gc28(1): 0+0+0 ms, 128 -> 0 MB 572 -> 568 (29469-28901) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:31 1 Request : 12
2013/05/29 11:48:31 1 Memory 1 158762864 532928 24576 532928
gc29(1): 0+0+0 ms, 128 -> 128 MB 634 -> 561 (29537-28976) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:32 1 Memory 2 158762864 134744352 24576 134744352
2013/05/29 11:48:32 1 Memory 3 158762864 134744440 24576 134744440 0
gc30(1): 0+0+0 ms, 128 -> 0 MB 573 -> 569 (29550-28981) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:32 1 Request : 13
2013/05/29 11:48:32 1 Memory 1 158762864 532920 24576 532920
gc31(1): 0+0+0 ms, 128 -> 128 MB 633 -> 562 (29616-29054) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:32 1 Memory 2 158762864 134744360 24576 134744360
2013/05/29 11:48:32 1 Memory 3 158762864 134744448 24576 134744448 0
gc32(1): 0+0+0 ms, 128 -> 0 MB 574 -> 570 (29629-29059) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:35 1 Request : 14
2013/05/29 11:48:35 1 Memory 1 158762864 532928 24576 532928
gc33(1): 0+0+0 ms, 128 -> 128 MB 634 -> 562 (29695-29133) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:35 1 Memory 2 158762864 134744360 24576 134744360
2013/05/29 11:48:35 1 Memory 3 158762864 134744448 24576 134744448 0
gc34(1): 0+0+0 ms, 128 -> 128 MB 574 -> 571 (29708-29137) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:35 1 Request : 15
2013/05/29 11:48:35 1 Memory 1 158762864 134750656 24576 134750656
2013/05/29 11:48:35 1 Memory 2 309757808 268968472 24576 268968472
2013/05/29 11:48:35 1 Memory 3 309757808 268968560 24576 268968560 0
gc35(1): 0+0+0 ms, 256 -> 256 MB 647 -> 572 (29786-29214) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:36 1 Request : 16
2013/05/29 11:48:36 1 Memory 1 309757808 268968720 24576 268968720
2013/05/29 11:48:36 1 Memory 2 460752752 403186536 24576 403186536
2013/05/29 11:48:36 1 Memory 3 460752752 403186624 24576 403186624 0
gc36(1): 0+0+0 ms, 384 -> 384 MB 650 -> 575 (29866-29291) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:36 1 Request : 17
2013/05/29 11:48:36 1 Memory 1 460752752 403186448 24576 403186448
2013/05/29 11:48:36 1 Memory 2 611747696 537404264 24576 537404264
2013/05/29 11:48:36 1 Memory 3 611747696 537404352 24576 537404352 0
gc37(1): 0+0+0 ms, 512 -> 384 MB 651 -> 575 (29944-29369) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:36 1 Request : 18
2013/05/29 11:48:36 1 Memory 1 611747696 403186448 24576 403186448
2013/05/29 11:48:37 1 Memory 2 611747696 537404264 24576 537404264
2013/05/29 11:48:37 1 Memory 3 611747696 537404352 24576 537404352 0
gc38(1): 0+0+0 ms, 512 -> 384 MB 651 -> 575 (30022-29447) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 19
2013/05/29 11:48:37 1 Memory 1 611747696 403278720 65536 403278720
2013/05/29 11:48:37 1 Memory 2 611747696 537496536 65536 537496536
2013/05/29 11:48:37 1 Memory 3 611747696 537496624 65536 537496624 0
gc39(1): 0+0+0 ms, 512 -> 384 MB 936 -> 729 (30385-29656) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 20
2013/05/29 11:48:37 1 Memory 1 611747696 403275424 65536 403275424
2013/05/29 11:48:37 1 Memory 2 611747696 537493240 65536 537493240
2013/05/29 11:48:37 1 Memory 3 611747696 537493328 65536 537493328 0
gc40(1): 0+0+0 ms, 512 -> 384 MB 783 -> 718 (30441-29723) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 21
2013/05/29 11:48:37 1 Memory 1 611747696 403277032 65536 403277032
2013/05/29 11:48:37 1 Memory 2 611747696 537494848 65536 537494848
2013/05/29 11:48:37 1 Memory 3 611747696 537494936 65536 537494936 0
gc41(1): 0+0+0 ms, 512 -> 384 MB 772 -> 707 (30497-29790) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 22
2013/05/29 11:48:37 1 Memory 1 611747696 403278640 65536 403278640
2013/05/29 11:48:37 1 Memory 2 611747696 537496456 65536 537496456
2013/05/29 11:48:37 1 Memory 3 611747696 537496544 65536 537496544 0
gc42(1): 0+0+0 ms, 512 -> 384 MB 761 -> 696 (30553-29857) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 23
2013/05/29 11:48:37 1 Memory 1 611747696 403280248 65536 403280248
2013/05/29 11:48:37 1 Memory 2 611747696 537498064 65536 537498064
2013/05/29 11:48:37 1 Memory 3 611747696 537498152 65536 537498152 0
gc43(1): 0+0+0 ms, 512 -> 384 MB 750 -> 679 (30609-29930) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 24
2013/05/29 11:48:37 1 Memory 1 611747696 403273568 65536 403273568
2013/05/29 11:48:37 1 Memory 2 611747696 537491384 65536 537491384
2013/05/29 11:48:37 1 Memory 3 611747696 537491472 65536 537491472 0
gc44(1): 0+0+0 ms, 512 -> 384 MB 733 -> 662 (30665-30003) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 25
2013/05/29 11:48:37 1 Memory 1 611747696 403266888 65536 403266888
2013/05/29 11:48:37 1 Memory 2 611747696 537484704 65536 537484704
2013/05/29 11:48:37 1 Memory 3 611747696 537484792 65536 537484792 0
gc45(1): 0+0+0 ms, 512 -> 384 MB 716 -> 645 (30721-30076) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 26
2013/05/29 11:48:37 1 Memory 1 611747696 403260208 65536 403260208
2013/05/29 11:48:37 1 Memory 2 611747696 537478024 65536 537478024
2013/05/29 11:48:37 1 Memory 3 611747696 537478112 65536 537478112 0
gc46(1): 0+0+0 ms, 512 -> 384 MB 699 -> 628 (30777-30149) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 27
2013/05/29 11:48:37 1 Memory 1 611747696 403253528 65536 403253528
2013/05/29 11:48:37 1 Memory 2 611747696 537471344 65536 537471344
2013/05/29 11:48:37 1 Memory 3 611747696 537471432 65536 537471432 0
gc47(1): 0+0+0 ms, 512 -> 384 MB 682 -> 611 (30833-30222) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 28
2013/05/29 11:48:37 1 Memory 1 611747696 403246848 65536 403246848
2013/05/29 11:48:37 1 Memory 2 611747696 537464664 65536 537464664
2013/05/29 11:48:37 1 Memory 3 611747696 537464752 65536 537464752 0
gc48(1): 0+0+0 ms, 512 -> 384 MB 665 -> 594 (30889-30295) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 11:48:37 1 Request : 29
2013/05/29 11:48:37 1 Memory 1 611747696 403240168 65536 403240168
2013/05/29 11:48:37 1 Memory 2 611747696 537457984 65536 537457984
2013/05/29 11:48:37 1 Memory 3 611747696 537458072 65536 537458072 0
gc49(1): 0+0+0 ms, 512 -> 384 MB 648 -> 577 (30945-30368) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg1: inuse: 384, idle: 128, sys: 513, released: 0, consumed: 513 (MB)
scvg2: inuse: 384, idle: 128, sys: 513, released: 0, consumed: 513 (MB)
gc50(1): 0+0+0 ms, 384 -> 384 MB 580 -> 526 (30949-30423) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg3: GC forced
scvg3: inuse: 384, idle: 128, sys: 513, released: 0, consumed: 513 (MB)
scvg4: inuse: 384, idle: 128, sys: 513, released: 0, consumed: 513 (MB)
gc51(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30950-30424) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg5: GC forced
scvg5: inuse: 384, idle: 128, sys: 513, released: 0, consumed: 513 (MB)
scvg6: 0x80 MB released
scvg6: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc52(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30951-30425) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg7: GC forced
scvg7: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg8: 0x0 MB released
scvg8: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc53(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30952-30426) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg9: GC forced
scvg9: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg10: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc54(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30953-30427) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg11: GC forced
scvg11: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg12: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc55(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30954-30428) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg13: GC forced
scvg13: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg14: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc56(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30955-30429) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg15: GC forced
scvg15: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg16: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc57(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30956-30430) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg17: GC forced
scvg17: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg18: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc58(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30957-30431) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg19: GC forced
scvg19: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg20: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc59(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30958-30432) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg21: GC forced
scvg21: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg22: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc60(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30959-30433) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg23: GC forced
scvg23: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg24: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc61(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30960-30434) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg25: GC forced
scvg25: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg26: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc62(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30961-30435) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg27: GC forced
scvg27: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg28: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc63(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30962-30436) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg29: GC forced
scvg29: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg30: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc64(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30963-30437) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg31: GC forced
scvg31: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg32: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc65(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30964-30438) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg33: GC forced
scvg33: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg34: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc66(1): 0+0+0 ms, 384 -> 384 MB 526 -> 526 (30965-30439) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg35: GC forced
scvg35: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg36: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
2013/05/29 12:24:51 1 Request : 30
2013/05/29 12:24:51 1 Memory 1 611747696 403218456 65536 403218456
2013/05/29 12:24:52 1 Memory 2 611747696 537436272 65536 537436272
2013/05/29 12:24:52 1 Memory 3 611747696 537436360 65536 537436360 0
gc67(1): 0+0+0 ms, 512 -> 384 MB 599 -> 571 (31040-30469) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 31
2013/05/29 12:24:52 1 Memory 1 611747696 403224336 65536 403224336
2013/05/29 12:24:52 1 Memory 2 611747696 537442152 65536 537442152
2013/05/29 12:24:52 1 Memory 3 611747696 537442240 65536 537442240 0
gc68(1): 0+0+0 ms, 512 -> 384 MB 649 -> 573 (31120-30547) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 32
2013/05/29 12:24:52 1 Memory 1 611747696 403224336 65536 403224336
2013/05/29 12:24:52 1 Memory 2 611747696 537442152 65536 537442152
2013/05/29 12:24:52 1 Memory 3 611747696 537442240 65536 537442240 0
gc69(1): 0+0+0 ms, 512 -> 384 MB 649 -> 573 (31198-30625) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 33
2013/05/29 12:24:52 1 Memory 1 611747696 403225064 65536 403225064
2013/05/29 12:24:52 1 Memory 2 611747696 537442880 65536 537442880
2013/05/29 12:24:52 1 Memory 3 611747696 537442968 65536 537442968 0
gc70(1): 0+0+0 ms, 512 -> 384 MB 670 -> 585 (31297-30712) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 34
2013/05/29 12:24:52 1 Memory 1 611747696 403224776 65536 403224776
2013/05/29 12:24:52 1 Memory 2 611747696 537442592 65536 537442592
2013/05/29 12:24:52 1 Memory 3 611747696 537442680 65536 537442680 0
gc71(1): 0+0+0 ms, 512 -> 384 MB 661 -> 585 (31375-30790) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 35
2013/05/29 12:24:52 1 Memory 1 611747696 403224776 65536 403224776
2013/05/29 12:24:52 1 Memory 2 611747696 537442592 65536 537442592
2013/05/29 12:24:52 1 Memory 3 611747696 537442680 65536 537442680 0
gc72(1): 0+0+0 ms, 512 -> 384 MB 661 -> 585 (31453-30868) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 36
2013/05/29 12:24:52 1 Memory 1 611747696 403225504 65536 403225504
2013/05/29 12:24:52 1 Memory 2 611747696 537443320 65536 537443320
2013/05/29 12:24:52 1 Memory 3 611747696 537443408 65536 537443408 0
gc73(1): 1+0+0 ms, 512 -> 384 MB 682 -> 597 (31552-30955) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 37
2013/05/29 12:24:52 1 Memory 1 611747696 403225552 65536 403225552
2013/05/29 12:24:52 1 Memory 2 611747696 537443368 65536 537443368
2013/05/29 12:24:52 1 Memory 3 611747696 537443456 65536 537443456 0
gc74(1): 0+0+0 ms, 512 -> 384 MB 675 -> 599 (31632-31033) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 38
2013/05/29 12:24:52 1 Memory 1 611747696 403226616 65536 403226616
2013/05/29 12:24:52 1 Memory 2 611747696 537444432 65536 537444432
2013/05/29 12:24:52 1 Memory 3 611747696 537444520 65536 537444520 0
gc75(1): 0+0+0 ms, 512 -> 384 MB 698 -> 613 (31733-31120) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 39
2013/05/29 12:24:52 1 Memory 1 611747696 403235344 65536 403235344
2013/05/29 12:24:52 1 Memory 2 611747696 537453160 65536 537453160
2013/05/29 12:24:52 1 Memory 3 611747696 537453248 65536 537453248 0
gc76(1): 0+0+0 ms, 512 -> 384 MB 716 -> 631 (31838-31207) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 40
2013/05/29 12:24:52 1 Memory 1 611747696 403235056 65536 403235056
2013/05/29 12:24:52 1 Memory 2 611747696 537452872 65536 537452872
2013/05/29 12:24:52 1 Memory 3 611747696 537452960 65536 537452960 0
gc77(1): 0+0+0 ms, 512 -> 384 MB 707 -> 631 (31916-31285) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 41
2013/05/29 12:24:52 1 Memory 1 611747696 403234208 65536 403234208
2013/05/29 12:24:52 1 Memory 2 611747696 537452024 65536 537452024
2013/05/29 12:24:52 1 Memory 3 611747696 537452112 65536 537452112 0
gc78(1): 0+0+0 ms, 512 -> 384 MB 684 -> 619 (31971-31352) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 42
2013/05/29 12:24:52 1 Memory 1 611747696 403233768 65536 403233768
2013/05/29 12:24:52 1 Memory 2 611747696 537451584 65536 537451584
2013/05/29 12:24:52 1 Memory 3 611747696 537451672 65536 537451672 0
gc79(1): 0+0+0 ms, 512 -> 384 MB 672 -> 607 (32026-31419) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 43
2013/05/29 12:24:52 1 Memory 1 611747696 403233328 65536 403233328
2013/05/29 12:24:52 1 Memory 2 611747696 537451144 65536 537451144
2013/05/29 12:24:52 1 Memory 3 611747696 537451232 65536 537451232 0
gc80(1): 0+0+0 ms, 512 -> 384 MB 660 -> 595 (32081-31486) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
2013/05/29 12:24:52 1 Request : 44
2013/05/29 12:24:52 1 Memory 1 611747696 403232888 65536 403232888
2013/05/29 12:24:52 1 Memory 2 611747696 537450704 65536 537450704
2013/05/29 12:24:52 1 Memory 3 611747696 537450792 65536 537450792 0
gc81(1): 0+0+0 ms, 512 -> 384 MB 648 -> 583 (32136-31553) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg37: inuse: 384, idle: 128, sys: 513, released: 0, consumed: 512 (MB)
scvg38: inuse: 384, idle: 128, sys: 513, released: 0, consumed: 512 (MB)
gc82(1): 0+0+0 ms, 384 -> 384 MB 586 -> 532 (32140-31608) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg39: GC forced
scvg39: inuse: 384, idle: 128, sys: 513, released: 0, consumed: 512 (MB)
scvg40: inuse: 384, idle: 128, sys: 513, released: 0, consumed: 512 (MB)
gc83(1): 0+0+0 ms, 384 -> 384 MB 532 -> 532 (32141-31609) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg41: GC forced
scvg41: inuse: 384, idle: 128, sys: 513, released: 0, consumed: 512 (MB)
scvg42: 0x80 MB released
scvg42: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc84(1): 0+0+0 ms, 384 -> 384 MB 532 -> 532 (32142-31610) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg43: GC forced
scvg43: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg44: 0x0 MB released
scvg44: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc85(1): 0+0+0 ms, 384 -> 384 MB 532 -> 532 (32143-31611) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg45: GC forced
scvg45: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg46: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc86(1): 0+0+0 ms, 384 -> 384 MB 532 -> 532 (32144-31612) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg47: GC forced
scvg47: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg48: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc87(1): 0+0+0 ms, 384 -> 384 MB 532 -> 532 (32145-31613) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg49: GC forced
scvg49: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg50: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc88(1): 0+0+0 ms, 384 -> 384 MB 532 -> 532 (32146-31614) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg51: GC forced
scvg51: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg52: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc89(1): 0+0+0 ms, 384 -> 384 MB 532 -> 532 (32147-31615) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg53: GC forced
scvg53: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
scvg54: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)
gc90(1): 0+0+0 ms, 384 -> 384 MB 532 -> 532 (32148-31616) objects, 0(0) handoff, 0(0) steal, 0/0/0 yields
scvg55: GC forced
scvg55: inuse: 384, idle: 128, sys: 513, released: 128, consumed: 384 (MB)

This time even the memory stats doesnt show that the Memstats.Alloc falls. Previously it used to reduce once the request was over and the MemStats.Sys showed the memory it had. Ironically this time both showed that the memory was in use whereas the example code clearly has the function exiting after it makes the slice len to "0" zero.

Kevin Cathcart

unread,
May 29, 2013, 9:14:29 AM5/29/13
to Dave Cheney, rahe...@gmail.com, golan...@googlegroups.com, Carlos Castillo
I have a specific change proposal in mind, more concerete than what I previously mentioned. I will write it up soon-ish (hopefully this evening), file an issue, and discuss the proposal with the language developers, in the appropriate venue for such discussions.

Technically yes, the current behavior is by design. I hope to introduce an improved design that is really only a relatively minor variation of the current design, and should improve the behavior under Windows, and probably
also several other operating systems.

Dave Cheney

unread,
May 29, 2013, 9:14:51 AM5/29/13
to rahe...@gmail.com, golan...@googlegroups.com, rahe...@gmail.com, Carlos Castillo, Kevin Cathcart
As I have explained several times, we _signal_ to the OS that we do not need the contents of the memory page. This means if we touch that page later on, we cannot guarantee the contents of the page. From Go's point of view the contents of the page are unneeded, and the operating system is free to give that page to another process without saving the contents to a swap file. However when we touch that page again, as it is still within the address range of the heap, the operating system must back that page with real memory. 

This is why the virt number does not change. You should not use the virt number as a counter to say 'my program is using this many pages of ram', it simply does not work like that on modern unix systems. 

Dave



On 29/05/2013, at 23:08, rahe...@gmail.com wrote:

From the tool htop when I see the results the "VIRT" memory is 1066M and "RES" is 260M
After the release of 0x80 MB VIRT is still the same and RES falls to 131M
However, shouldnt the "RES" fall to something in BYTES ? As the slice was destroyed.
Why is that not happening ?
 
And my go Prog has the highest VIRT memory on the whole system, which I do feel is strange. I am not sure and dont find any logical reasons as to why should GO react this way.

On Wednesday, May 29, 2013 6:20:57 PM UTC+5:30, Dave Cheney wrote:
You see the line where is says 0x80mb released? That is the best we can do. We tell the OS it is there if it needs it, and that is it.

--

unread,
May 29, 2013, 9:17:52 AM5/29/13
to golan...@googlegroups.com, rahe...@gmail.com, Carlos Castillo, Kevin Cathcart
On Wednesday, May 29, 2013 3:08:04 PM UTC+2, rahe...@gmail.com wrote: 
And my go Prog has the highest VIRT memory on the whole system, which I do feel is strange. I am not sure and dont find any logical reasons as to why should GO react this way.

The reason for high VIRT memory has to do with performance of the Go runtime. The runtime implementation could be modified so that Go programs have VIRT close to RES, but this would make certain operations slower.

Dave Cheney

unread,
May 29, 2013, 9:31:36 AM5/29/13
to rahe...@gmail.com, golan...@googlegroups.com, Carlos Castillo, Kevin Cathcart
The scavenger can only free pages that are completely unused. The Go GC is non compacting so a single byte allocated on a page will pin that page. The scavenger reclaimed 128mb, which was the amount you allocated in your sample code (from memory), so it looks like it is working as intended. 



On 29/05/2013, at 23:29, rahe...@gmail.com wrote:

I know that VIRT is not the real memory usage.
I was just making a point here that some people who would land up using software written in Go might get confused IF they dont know what the VIRT means.
 
But on the much important point, the RES Memory still remain at 130 - 260M as reported by MemStats.Alloc. Shouldnt that drop ?

On Wednesday, May 29, 2013 6:44:51 PM UTC+5:30, Dave Cheney wrote:
This is why the virt number does not change. You should not use the virt number as a counter to say 'my program is using this many pages of ram', it simply does not work like that on modern unix systems. 

--
Message has been deleted

Raheel Gupta

unread,
May 29, 2013, 10:50:01 AM5/29/13
to ⚛, golang-nuts, Carlos Castillo, Kevin Cathcart
func API() {
...
mtemp = nil
go func() { runtime.GC() }()
}
 
Tried the above code. Still the same.
 
>>I have a patch prepared in the queue that enables API() to reach 0 MB of allocated memory after runtime.GC() is called from a Go func. It isn't a 100% fix, but it works in many cases.
 
Will this work on windows as well ?
Also does calling runtime.GC() cause any specific overhead on the applications CPU usage ?

Stephen Gutekanst

unread,
May 30, 2013, 8:00:06 PM5/30/13
to golan...@googlegroups.com, Dmitry Vyukov, kevinc...@gmail.com, Carlos Castillo, rahe...@gmail.com
Hi, sorry if I missed this already in the conversation, but,

Did you ever find out result of if this lowers the private bytes counter or not?

Thanks,
Stephen

minux

unread,
May 31, 2013, 3:25:27 AM5/31/13
to Stephen Gutekanst, golan...@googlegroups.com, Dmitry Vyukov, kevinc...@gmail.com, Carlos Castillo, rahe...@gmail.com
On Fri, May 31, 2013 at 8:00 AM, Stephen Gutekanst <stephen....@gmail.com> wrote:
Did you ever find out result of if this lowers the private bytes counter or not?
As explained later in this thread, it won't lower the private bytes counter.

FYI, the patch is:
diff -r 85353b4dc2d4 src/pkg/runtime/mem_windows.c
--- a/src/pkg/runtime/mem_windows.c     Thu May 30 21:32:20 2013 -0700
+++ b/src/pkg/runtime/mem_windows.c     Fri May 31 15:23:57 2013 +0800
@@ -11,6 +11,7 @@
 enum {
        MEM_COMMIT = 0x1000,
        MEM_RESERVE = 0x2000,
+       MEM_DECOMMIT = 0x4000,
        MEM_RELEASE = 0x8000,

        PAGE_EXECUTE_READWRITE = 0x40,
@@ -31,8 +32,10 @@
 void
 runtime·SysUnused(void *v, uintptr n)
 {
-       USED(v);
-       USED(n);
+       runtime·stdcall(runtime·VirtualFree, 3, v, (uintptr)0, (uintptr)MEM_DECOMMIT);
+       runtime·stdcall(runtime·VirtualAlloc, 4, v, n, (uintptr)(MEM_COMMIT|MEM_RESERVE), (uintptr)PAGE_EXECUTE_READWRITE);
+       //USED(v);
+       //USED(n);
 }

 void

Carlos Castillo

unread,
May 31, 2013, 7:45:36 AM5/31/13
to Raheel Gupta, golang-nuts, Stephen Gutekanst, Dmitry Vyukov, kevinc...@gmail.com
For the current state of go:

Linux (w/Overcommit): SysUnused marks memory found by scavenger/FreeOSMemory as unused, so OS can take it easily when it needs memory.
When OS needs memory: No swapping needed for when the OS takes or returns unused memory, and it is taken first, so it's essentially as fast and available as "Free" memory.  According to comments earlier in the thread: Overcommit causes numbers to shrink immediately instead of when memory is taken from go.

Others (Darwin, BSDs, Linux w/o overcommit, etc...): SysUnused is implemented, thus the "released" memory is cheap to re-use by the OS.
When OS needs memory: No Swapping, better OS decisions, but no shrinking numbers except when OS takes pages from go.

Windows: SysUnused does nothing. Go does not use the memory again, unless it needs more memory later.
When OS needs memory: Swapping when the OS takes and returns pages, the page choice for swapping is less informed, and no shrinking numbers until the memory is taken.

Stop worrying about the private bytes. If SysUnused in go is working correctly, it's an almost meaningless statistic. For getting SysUnused working in Windows, the issue https://code.google.com/p/go/issues/detail?id=4960 already exists.

Personal Observations regarding minux's patch:
  • Unless the patch is guaranteed to not fail (ie: the sequence of VirtualFree/VirtualAlloc will always succeed and give the same addresses back), you are trading away stability since a failure of SysUnused can cause unexpected crashes. 
  • The cost of the dealloc/realloc is most-likely greater than the current behaviour, so your programs will be slightly slower if they aren't being paged in / out.
  • Your programs will still use the same amount of memory at their peak, because the patch has changed nothing in the operation of the garbage collector, nor in your code's memory access patterns.
  • This patch will also not fix any crashes you may have had in 32-bit EXEs that were caused by running out of address space because of the previous point.
Enjoy.


On Fri, May 31, 2013 at 2:22 AM, <rahe...@gmail.com> wrote:
So there is still no way to lower the private bytes in windows right ?



--
Carlos Castillo

minux

unread,
May 31, 2013, 8:27:17 AM5/31/13
to Carlos Castillo, Raheel Gupta, golang-nuts, Stephen Gutekanst, Dmitry Vyukov, kevinc...@gmail.com
On Fri, May 31, 2013 at 7:45 PM, Carlos Castillo <cook...@gmail.com> wrote:
Personal Observations regarding minux's patch:
In case that I didn't make it clear, that patch isn't intended to be used (or I'd just mail a CL). 
It won't solve the problem (as i said in the reply).
I just posted as a clue for people how *not* to implement SysUnused on windows.
(another bad example, as I explained earlier in this thread, is using MEM_RESET in attempt to reduce private bytes
counter)
  • Unless the patch is guaranteed to not fail (ie: the sequence of VirtualFree/VirtualAlloc will always succeed and give the same addresses back), you are trading away stability since a failure of SysUnused can cause unexpected crashes. 
It won't fail as I understand it (unless you're using syscall to free arbitrary memory address or using cgo to do the same).
The VirtualFree will simply decommit the memory region (and that region will still be reserved), and then that region is
immediately re-committed, so it's effectively a way to hint the OS that content in those memory pages are not needed
any more.
And certainly, this is a very inefficient way to zero the memory region.
  • The cost of the dealloc/realloc is most-likely greater than the current behaviour, so your programs will be slightly slower if they aren't being paged in / out.
Are you implying that I suggest people use the patch? I certainly don't mean that.
  • Your programs will still use the same amount of memory at their peak, because the patch has changed nothing in the operation of the garbage collector, nor in your code's memory access patterns.
the same applies to all uses of runtime.SysUnused, it won't change the GC or the memory access patterns of your program.
  • This patch will also not fix any crashes you may have had in 32-bit EXEs that were caused by running out of address space because of the previous point.
again, i didn't say it will fix the problem. and what's more, runtime.SysUnused on other system won't fix the "running out of address space"
problem either. That's an entirely different problem.

minux

unread,
May 31, 2013, 8:31:41 AM5/31/13
to rahe...@gmail.com, golan...@googlegroups.com, Stephen Gutekanst, Dmitry Vyukov, kevinc...@gmail.com, Carlos Castillo
On Fri, May 31, 2013 at 5:22 PM, <rahe...@gmail.com> wrote:
So there is still no way to lower the private bytes in windows right ?
there is, for example, we can decommit the memory region in SysUnused and remove
the memory region from free list. But that will take more efforts to do than the current
madvise(2) approach used on unix systems and it surely will incur more overheads.

On Friday, May 31, 2013 12:55:27 PM UTC+5:30, minux wrote:
--

Carlos Castillo

unread,
May 31, 2013, 5:31:47 PM5/31/13
to minux, Raheel Gupta, golang-nuts, Stephen Gutekanst, Dmitry Vyukov, Kevin Cathcart
I wasn't trying to criticize the patch directly, I was trying to dissuade Raheel from trying to use it, as well as give him/her reasons why even a correct patch or one which actually frees the memory, will not fix most the problems listed in this thread.
--
Carlos Castillo

unread,
Jun 4, 2013, 2:40:20 AM6/4/13
to golan...@googlegroups.com, Stephen Gutekanst, Dmitry Vyukov, kevinc...@gmail.com, Carlos Castillo, rahe...@gmail.com
On Tuesday, June 4, 2013 8:18:36 AM UTC+2, rahe...@gmail.com wrote:
I am not sure about the patch as I am not a memory expert.
Has there been any progress on this regard ?

Tip of Go source code repository includes some simple patches which ameliorate the out-of-memory panics by a little bit.

unread,
Jun 4, 2013, 6:06:58 AM6/4/13
to golan...@googlegroups.com, Stephen Gutekanst, Dmitry Vyukov, kevinc...@gmail.com, Carlos Castillo, rahe...@gmail.com
Have you tried splitting the large allocation into multiple smaller allocations or rethinking parts of the algorithm? If you did, what was the result? If you didn't, why?

On Tuesday, June 4, 2013 11:58:00 AM UTC+2, rahe...@gmail.com wrote:
I will try it, but I have also started porting to QT just in case to avoid further delays of our project.
I wished the memory management was better, it would save me 3-4 weeks of time. I will still keep testing the sources if it meets our expectations of memory consumption.
Go is great but memeory still needs to be worked upon greatly :)

brainman

unread,
Jun 4, 2013, 6:18:30 AM6/4/13
to golan...@googlegroups.com
If you don't want to use Go memory manager for critical parts of your program, you don't have to. You could easily allocate memory form OS directly. You just have to be careful how you using it.

Alex

unread,
Jun 4, 2013, 6:47:34 AM6/4/13
to golan...@googlegroups.com, Stephen Gutekanst, Dmitry Vyukov, kevinc...@gmail.com, Carlos Castillo, rahe...@gmail.com
Try http://golang.org/pkg/syscall/#Mmap and http://golang.org/pkg/syscall/#Munmap.

On Tuesday, June 4, 2013 12:41:46 PM UTC+2, rahe...@gmail.com wrote:
I did break my code into using smaller allocations and trying to use that only.
The issue is with simultaneous access. My server is a web server as well as a sort of a File Transfer Server.
Now I have a restore operation which can restore files of any size. This operation is designed to access only 2500 blocks of 4K (which is nearly equal to 10MB) at a time and then send the data across the network or write it to servers disk depending on the admins choice.
So firstly GO will eat up nearly 30 to 40 MB of ram as I store 10MB in memory (Dave Cheney said this is the expected behaviour). This memory is never freed from GO and the Private Bytes in Windows shoots higher. If there is a Concurrent access, the ram shoots upto 100-200MB of usage for a simple server which should be operating in 30-50 MB of Ram. Also the memory (MemStats.Alloc) doesnt go down even though the function exits. You can check the behaviour in my example posted above. Though Go mentions that memory should be freed after a function exits when there are no pointers to the data remaining, but in my example using the http package it doesnt do so (it increases the Alloc counts unexpectedly and randomly on further requests).
So my apps Ram consumption shoots to atleast 50MB+ for a restore of a 10MB file. Lets say if there are 3 concurrent requests for 10MB+ Files, my server will be using 200MB of ram which will not go down even when the job is finished.
This makes the application unfit to be shipped to customers.

brainman

unread,
Jun 4, 2013, 6:57:21 AM6/4/13
to golan...@googlegroups.com
As I said before, you can ask OS to provide memory directly. Then you could free it back to OS once you are done with that. You don't disable Go memory manager, you use it as normal. But for large things use OS provided memory.

Alex

Gerard

unread,
Jun 4, 2013, 8:19:06 AM6/4/13
to golan...@googlegroups.com, rahe...@gmail.com

On Tuesday, June 4, 2013 1:36:26 PM UTC+2, rahe...@gmail.com wrote:
Using Mmap I can use it for data which is in sequence. Unfortunately my data is broken into bits and pieces of 4K.
I have to use functionality of map[blocknum][4096]byte

That's easy. Just define a method / function and return a sub-slice e.g.

func SubSlice(block []byte, blocknum int) []byte {
    return block[blocknum*4096:blocknum+1*4096]
}

Carlos Castillo

unread,
Jun 7, 2013, 8:40:52 AM6/7/13
to Raheel Gupta, golang-nuts
Anything in the syscall package is platform dependent. Windows doesn't have the Mmap call, you need to use other functions. I'm not an expert on the Windows API, so I'm not sure which function you need (you're looking to allocate/deallocate anonymous memory right?).

BTW, thinking back to the various hints that you've been giving about you're project, it's using a map[blocknum][4096]byte somewhere inside it. The impression I've got is that you are running some sort of server that looks to be serving a large file, and (here's me guessing) the client asks for a (possibly random) sequence of 4K blocks, and the map is used to hold in memory the contents of the file and serve the requests.

If the contents of blocknum N in the map are the bytes N*4096 to (N+1)*4096 of a file, then a low memory solution (4K * number of active requests) is possible. If I'm off the mark, then never mind.


On Fri, Jun 7, 2013 at 5:10 AM, <rahe...@gmail.com> wrote:
Hi,
 
I was trying the MMAP option as well. Is the Mmap option not available on Windows ?

On Tuesday, June 4, 2013 4:27:21 PM UTC+5:30, brainman wrote:
As I said before, you can ask OS to provide memory directly. Then you could free it back to OS once you are done with that. You don't disable Go memory manager, you use it as normal. But for large things use OS provided memory.

Alex

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/7V_zICSxngo/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Carlos Castillo

Tamás Gulácsi

unread,
Jun 7, 2013, 9:38:57 AM6/7/13
to golan...@googlegroups.com

Tamás Gulácsi

unread,
Jun 7, 2013, 9:41:10 AM6/7/13
to golan...@googlegroups.com

Carlos Castillo

unread,
Jun 7, 2013, 2:37:09 PM6/7/13
to Raheel Gupta, golang-nuts
So, is your map based code essentially attempting to speed up: http://play.golang.org/p/s6O04tJ3cl ?


On Fri, Jun 7, 2013 at 6:37 AM, <rahe...@gmail.com> wrote:
Actually my software is designed to use the least amount of memory as per the file being served.
There is a CAP of 2500 Blocks of 4K if the file is greater than 10MB. If the file being served is less than 2500 blocks it will create the map of only that size. So if a 100MB file is to be served it would be done in 10MB of ram and 10 loops.
But the problem with GO is that it takes 30-40 MB and never releases it.
 
@brainman and "atom" symbol, any ideas how to use Mmap on windows in Go ?
Is there an implementation for the same in Go for windows ?
 
I get the following errors :
undefined: syscall.Mmap
undefined: syscall.PROT_READ
undefined: syscall.MAP_ANON

On Friday, June 7, 2013 6:10:52 PM UTC+5:30, Carlos Castillo wrote:
Anything in the syscall package is platform dependent. Windows doesn't have the Mmap call, you need to use other functions. I'm not an expert on the Windows API, so I'm not sure which function you need (you're looking to allocate/deallocate anonymous memory right?).

BTW, thinking back to the various hints that you've been giving about you're project, it's using a map[blocknum][4096]byte somewhere inside it. The impression I've got is that you are running some sort of server that looks to be serving a large file, and (here's me guessing) the client asks for a (possibly random) sequence of 4K blocks, and the map is used to hold in memory the contents of the file and serve the requests.

If the contents of blocknum N in the map are the bytes N*4096 to (N+1)*4096 of a file, then a low memory solution (4K * number of active requests) is possible. If I'm off the mark, then never mind.


 

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/7V_zICSxngo/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Carlos Castillo

Carlos Castillo

unread,
Jun 7, 2013, 2:48:09 PM6/7/13
to Raheel Gupta, golang-nuts
Run godoc locally to find out the syscall documentation for your current system (I'm assuming Windows here).

Run "godoc -http :6060" then open a browser to http://localhost:6060/pkg/syscall

If you are on a linux (or darwin) machine, and want to see the documentation for windows:
"GOOS=windows godoc -http :6060"


On Fri, Jun 7, 2013 at 10:39 AM, <rahe...@gmail.com> wrote:
But what is the equivalent of this in Golang ?

On Friday, June 7, 2013 7:11:10 PM UTC+5:30, Tamás Gulácsi wrote:
Start here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366556(v=vs.85).aspx

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/7V_zICSxngo/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Carlos Castillo

Tamás Gulácsi

unread,
Jun 7, 2013, 2:50:03 PM6/7/13
to golan...@googlegroups.com

Carlos Castillo

unread,
Jun 7, 2013, 3:10:02 PM6/7/13
to Tamás Gulácsi, golang-nuts
I'm not sure if the OP is attempting to memory map a file, or to map anonymous memory (ie: a lower-level malloc). In UNIX-like environments mmap can do both, depending on the parameters to mmap, while on Windows they may be separate calls.

If the former, then your suggestions are correct (and syscall contains CreateFileMapping/MapViewOfFile), if the latter, I think the OP is looking for how to do the following in Go: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366803(v=vs.85).aspx

I couldn't find VirtualAlloc/VirtualFree in go's syscall package. But they can probably be called using sycall.LazyDLL/LazyProc, but that is way outside my area of expertise.



On Fri, Jun 7, 2013 at 11:50 AM, Tamás Gulácsi <tgula...@gmail.com> wrote:
--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/7V_zICSxngo/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.





--
Carlos Castillo

Tamás Gulácsi

unread,
Jun 7, 2013, 3:33:20 PM6/7/13
to golan...@googlegroups.com
@carlos: I don't know for sure, but as I understand, OP want to serve some huge files by 4Kb blocks with as little RSS as possible, as fast as possible. That's why I think an mmap on the file would be a perfect solution - toss the problem on the OS side :)

@rahe: Why is the ReadAt slow? Have you benchmarked that? I mean Open the file just once (thus cache the handle), and use ReadAt as needed - your OS should do the caching for you! (At least Linux does use all available RAM as file cache).

A third solution could be to have an n Mb temp file (or anonymous/virtual region) mmap-ed, and used as a cache - but this is just sidestepping the GC.

Carlos Castillo

unread,
Jun 7, 2013, 3:38:58 PM6/7/13
to Raheel Gupta, golang-nuts
On Fri, Jun 7, 2013 at 12:13 PM, <rahe...@gmail.com> wrote:
Will test it. I did google quite alot but I was actually trying to search for syscall MMAP from the go package itself.

On Saturday, June 8, 2013 12:20:03 AM UTC+5:30, Tamás Gulácsi wrote:
JFGI ( https://www.google.com/search?q=go+mmap+windows&ie=utf-8&oe=utf-8&aq=t )!

https://github.com/edsrzf/mmap-go

 
 
>> So, is your map based code essentially attempting to speed up: http://play.golang.org/p/s6O04tJ3cl
 
I cant use that, its probably very slow !

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/7V_zICSxngo/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

So, you haven't tried it out? If your only issue is that "it's probably very slow", it still solves your memory "issue", and gives us an better idea what you are trying to do.

I only posted something that was dreadfully simple so you could understand what I was asking. A more efficient version would be using a type similar to: http://play.golang.org/p/O3jkIhq0HE , since it only opens the file once for a set of requests.

If necessary you could then use PreloadChunk to tell the OS to put the requested 10MB into it's cache, which does not show up in your program's private bytes. 

--
Carlos Castillo

Tamás Gulácsi

unread,
Jun 7, 2013, 5:00:07 PM6/7/13
to golan...@googlegroups.com
What about cgo? I mean this still just sidestepping the GC, but see http://play.golang.org/p/u71rG7ALFi

brainman

unread,
Jun 7, 2013, 9:49:38 PM6/7/13
to golan...@googlegroups.com, rahe...@gmail.com
On Friday, 7 June 2013 22:10:34 UTC+10, rahe...@gmail.com wrote:

> ... Is the Mmap option not available on Windows ?

No, Mmap is not available on Windows. Windows provides its own ways to allocate memory. There are many different ways to do it, and I don't know what you need, so I cannot advise. But, for example, one way is to use VirtualAlloc / VirtualFree functions (it is most low level, but most flexible way). I have been playing with those recently http://play.golang.org/p/KjypOYjzTD. Feel free to use my code, but you must read Microsoft documentation so you know how to use them.

Alex
Reply all
Reply to author
Forward
0 new messages