--
You received this message because you are subscribed to the Google Groups "golang-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-dev+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
On Wed, Jun 29, 2016 at 8:35 AM, Kyle Stanly <thei...@gmail.com> wrote:
> 3) Is it possible for the GC to reclaim memory allocated in
> runtime/malloc.go? I feel I'm having an issue wherein data is being
> collected even if it is collectable (I.E, if I log the move of objects from
> one place to another, as in transfer ownership, sometimes they disappear
> entirely. Logs show them being moved [I keep track of both address and
> contents of the object] but never again after being moved, and it is
> inconsistent, as not all moved objected disappear...).
Yes, the GC reclaims memory allocated by the mallocgc function. All
user program allocations and most runtime allocations go through that
function.
If you think that reachable memory is being collected the obvious
first thing to check is the type. The garbage collector is sensitive
to types; storing a pointer value as a uintptr type will break it.
5) Is there a reason why memory cannot escape the heap during escape
analysis? How precisely does the "noescape" function prevent it from
escaping? Does the '//go:noescape' annotation rely on this function as well?
I don't really understand the question. Either I misunderstand it or
you misunderstand what escape analysis does. The //go:noescape
comment tells the compiler that pointers passed to a function do not
escape. This is used for functions written in assembler.
If you think that reachable memory is being collected the obvious
first thing to check is the type. The garbage collector is sensitive
to types; storing a pointer value as a uintptr type will break it.
type bucketChain struct { next *bucketChain flags uintptr /* Two extra fields can be accessed through the use of unsafe.Pointer, needed because we take each key and value by value, (if it is a indirectKey, then we just store the pointer) and can
vary in size. Use cdataOffset to obtain key, and cdataOffset + t.keysize to obtain value */}
type bucketChain struct { next *bucketChain flags uintptr key keyType // or *keyType
value valType // or *valType}
5) Is there a reason why memory cannot escape the heap during escape
analysis? How precisely does the "noescape" function prevent it from
escaping? Does the '//go:noescape' annotation rely on this function as well?
I don't really understand the question. Either I misunderstand it or
you misunderstand what escape analysis does. The //go:noescape
comment tells the compiler that pointers passed to a function do not
escape. This is used for functions written in assembler.Apologies, I'm making a lot of typos lately. I meant "why can't memory escape to the heap during the runtime", but it got jumbled in with "due to escape analysis". For example, if I try to allocate something by allocating it on the stack, and then explicitly return a pointer to that, the escape analysis would cause it to be allocated on the heap (or so I think).
If you think that reachable memory is being collected the obvious
first thing to check is the type. The garbage collector is sensitive
to types; storing a pointer value as a uintptr type will break it.This is a rather crucial piece of information I may be looking over. For some reason the types created in reflect.go (the ones I created explicitly... I guess I'll have to create another CL, but it'd be rather long overall) have the wrong size. I.E, it thinks the size of a particular linked node (custom) is 32 bytes when it is 48 bytes (I use fixed types I know the size of), so I explicitly do the math myself.The thing is, I used the same compile-time tricks runtime/hashmap.go does with it's 'bmap' structure, the structure only contains it's concrete variables, but the compile-type maintains the actual size and structure. To give an example
type bucketChain struct {next *bucketChainflags uintptr/*Two extra fields can be accessed through the use of unsafe.Pointer, needed because we takeeach key and value by value, (if it is a indirectKey, then we just store the pointer) and can
vary in size. Use cdataOffset to obtain key, and cdataOffset + t.keysize to obtain value*/}In the compiler it is encoded as such...
type bucketChain struct {next *bucketChainflags uintptrkey keyType // or *keyType
value valType // or *valType}
However, unfortunately, the above is only enough for two pointers (as next and flags are pointer-aligned, so they're 16 bytes on my system; if keyType and valType were pointer types, they'd be another 16, hence 32 bytes in total). The funny thing is that the compiler correctly acknowledges keyType and valType as 16-bytes... but this is probably getting confusing without code to look at as I could have done something else wrong instead.I'm trying to solve this problem on my own however so I don't need to rely on asking questions, but if the type is wrong, it's possible that the GC would interpret it differently than from how I expect.
type node struct { next *node }
type root struct { n *node }
r1 -> n1
r2 -> n2
// swap
r1 -> n2
r2 -> n1
The garbage collector cares about the "size" and "ptrdata" fields of the type, and of course its pointer bitmap in "gcdata". If any of those are wrong, it could fail to trace pointers.
b := mallocgc(16 + t.keysize + t.valuesize, t.nodetype, true)
For example: At this point I was allocating like such...
b := mallocgc(16 + t.keysize + t.valuesize, t.nodetype, true)Would it only scan and reclaim data up to t.nodetype.size and leak the data allocated after?
The garbage collector cares about the "size" and "ptrdata" fields of the type, and of course its pointer bitmap in "gcdata". If any of those are wrong, it could fail to trace pointers.I suppose it was my fault for trying to step-over the issue by just explicitly using mallocgc to allocate enough. Even if the GC wasn't collecting my node early, the data itself could have been, since it wouldn't scan that far after it... Would it even be able to reclaim the memory allocated after the "size"?For example: At this point I was allocating like such...
b := mallocgc(16 + t.keysize + t.valuesize, t.nodetype, true)Would it only scan and reclaim data up to t.nodetype.size and leak the data allocated after?
--
if nodetype == t || nodetype2 == t || nodetype3 ==3 || ... { return "nodetype" }