> Is memory management type automatic reference counting being
> considered or is garbage collection the best way to Go?
We've considered a reference counting approach in the past. We've moved
away from it because of the problem of cycles. The effect of cycles is
that you have a lot of reference counting overhead, and then you need a
full garbage collector anyhow. The full garbage collector will probably
be invoked less often--but on the other hand you have reference counting
overhead. At least for now we're going for the more straightforward
approach.
Ian
I can't detect it.
--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/blog
http://niemeyer.net/twitter
> Is there any option to manage memory manually in Go?
>
> /johan
>
I believe you can solids your own array of objects (eg byte if you want), and then hand them out to code that wants it, and track when they are done w it, etc.
Gc will still run, but everything will be referenced by the pool manager.
Getting mem management right isn't all that easy, though, and gets worse in concurrent environments. I'm pretty sure this falls into the "if you don't want hc, you don't want go".
John
The same arguments can be made for programming using just
NAND gates, which can be summarized on just a post-it note.
It turns out that, compared to writing programs using NAND gates,
when I write programs in Go, I can write the program in less time,
the program is more likely to be correct, and the program is easier
to debug and fix if not. It is true that the program is slower and
less predictable than if I'd written it using just NAND gates, and
not having to think about NAND gates probably does make me
lazy and unaware at some level. For the programs I am writing,
the advantages of using Go outweigh the disadvantages of not
using NAND gates.
Of course, programmers and programming environments differ,
so if you find that NAND gates are a better fit for your work,
no one here is going to force you to use Go.
Russ
Russ
Michael T. Jones
Chief Technology Advocate, Google Inc.
1600 Amphitheatre Parkway, Mountain View, California 94043
Email: m...@google.com Mobile: 650-335-5765 Fax: 650-649-1938
Organizing the world's information to make it universally accessible and useful
...
> The classic solution is from Lisp where the allocation always belongs to the
> language runtime and the application only "leases" it. You see something
> akin in Java where the runtime exists in perpetuity outside of the threads
> that "lease" it. Same with kernel allocations in an OS. This same spirit is
> in the Go runtime because since the allocating goroutine may not live to
> free the allocation and the intended receiver on the other side of the
> channel may never see it, only the runtime is persistent enough to handle
> it. What is missing from the Go model (and which I suggested but was
> rebuffed ;-) was the ability to hint to the GC system. It could look like a
> free() and what it would do is simply say that you are done with the memory.
> I thought that might help by indicating the semantic situation. The reason
> that was dismissed is because the GC could not trust me about the memory
> being unreferenced. It would have to stop the world to see if I was telling
> the truth, which is the same as calling some form of "DoAGlobalGCRIghtNow()"
> and that is already a possibility. The alternative to that would be for the
> compiler to perform an escape analysis on the allocation and then either
> allocate it in the stack and release it on exit from scope, at return, or
> allocate it and release it on exit from scope or return. Either would work
> magically and would not need me to hint. Thus the hinting is redundant
> either way. It seemed like a good answer.
>
> Michael
The only thing it is missing is the ability to sometimes say:
myObject.ReallyBigBuffer = nil
In python you can at least play a trick if you know that reallyBigBuffer
is only accessed via myObject, so you can set it to None. And
technically, any other code that would try to access it as
myObject.ReallyBigBuffer[10]
Will now crash, because None doesn't support indexing. You could do
something similar as:
myObject.ReallyBigBuffer = make([]byte,0,0)
In CPython, because of the ref counting, that does let you dealloc
memory. And it is a shame that you'd have to walk all memory just to
purge the one big buffer you are now done with.
Then again, I also ran into this problem:
def do_something(big_string):
write(big_string)
# I'm done, with it, how can I get rid of it so I can do
# Without peaking at 2 big_strings...
return read(1024*1024*1024)
You basically have to artificially wrap your strings so that you can set
an attribute of the object to None, because otherwise the string is
still referenced by the stack.
Anyway, I understand not being able to trust hinting, but if you ever
end up managing a big buffer with a soft lifetime, it is nice to say
"yeah, I really am done with that now".
I imagine that if a variable can be put on the stack, it doesn't access
huge amounts of memory. The issue is a large buffer that lasts for a few
functions, but not for the whole lifetime of the process.
John
=:->
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAk4DkBkACgkQJdeBCYSNAAOsBgCdE6O0D1Ur04hlTjZS2Tin4u1Q
0T0AnjFIWzqNK9A7z0OH9bf3aIdQgkQA
=aWuo
-----END PGP SIGNATURE-----
look that list of issues.. how much of them are about memory leak?
with things getting out of control they ended creating a memory
inspection tool like valgrind.. just to be able to detect this
problem..
http://blog.chromium.org/2011/06/testing-chromium-addresssanitizer-fast.html
Measure now how much effort ..enginnering.. time and money has to be spent..
while in a personal level.. i dont mind about using manual
memory(doing a lot of c++ right now)..
in a big team with a big project this could be a source of headache..
and painful hours..
Wish all you want.
When did the Really Bad Idea list overflow?
ron
Of course manual management sacrifices safety. But in time critical
applications, such as in finance, that is a tradeoff I must make. It
would be nice if Go would have had this as an OPTION for such
applications. This would have been a great replacement for C, which is
tough on productivity.
Go is better for time critical applications than Java.
If its reliability in the real-time sense then C is not enough either i
guess since you'd need a real-time OS as well. Perhaps this has changed
but afaik the normal OS's don't really qualify for this.
The gc call in the jvm is just a hint though, the implementation may
ignore it.
I hope and think that Go will surpass the JVM in performance since the
programming model is far superior, at least compared to Java but similar
to other takes such as Scala.
/ Henrik
Michael T. Jones
Chief Technology Advocate, Google Inc.
Email: m...@google.com Mobile: 650-335-5765 Fax: 650-649-1938
Organizing the world's information to make it universally accessible and useful
Sure, why not? What's special about the reflection package? It might
have to be revised, but there's nothing fundamental that prevents a
copying collector.
- Evan
There's nothing in the reflect API that would keep a garbage
collector from moving objects. Obviously the implementation
might assume a non-moving collector (although I think it assumes
much less than you think) but the implementation is, well,
implementation-specific no matter what. Such is the nature of
reflect.
Russ
Part of your code not being safe when you use unsafe is that
it might break if assumptions you are making no longer hold.
One of the purposes of the 'unsafe.Pointer' type is to make
it clear to the garbage collector that this holds a pointer that
needs to be fixed up if data gets moved. It should be possible
to write code that imports unsafe but still works with a compacting
collector, as long as you use unsafe.Pointer for all the pointers
you're holding.
Russ
>> One of the purposes of the 'unsafe.Pointer' type is to make
>> it clear to the garbage collector that this holds a pointer that
>> needs to be fixed up if data gets moved. It should be possible
>> to write code that imports unsafe but still works with a compacting
>> collector, as long as you use unsafe.Pointer for all the pointers
>> you're holding.
>>
>
> Please correct me if I am wrong, but it seems that this rule is not
> always respected even in the actual code of "reflect/value.go". And if
> it is, then it is rather difficult to prove this by just inspecting
> the code. Furthermore, it seems that there will be always some
> calculations requiring intermediate pointer representation as
> uintptr's (is it legal now to add an integer to an unsafe.Pointer?)
It is perhaps worth noting that the current GC used by 6g/8g does not
take place at arbitrary moments.
> To assist developers, C# provides the relatively high-level language
> feature; furthermore, the language specification contains the
> appropriate recommendations regarding use of unsafe pointers. Is there
> anything comparable in Go?
>
> C# guarantees that once an unsafe pointer is pinned with the "fixed"
> statement, all calculations based on this pointer are valid within the
> statement body regardless the data types of intermediate results. I
> don't see how a similar guarantee can be provided by just reporting Go
> unsafe pointers to the garbage collector.
This seems to me to be mixing levels: an implementation detail is
driving a language feature.
In any case, no Go implementation is going to introduce a compacting
collector which breaks programs in the ways you are discussing. Until
somebody tries seriously to write a compacting collector, I think that
planning language changes to support it is putting the cart before the
horse.
> P.S. And, talking of assumptions, I think that it would be much better
> if the most important of them were fixed in the language
> specification. Then they would be not assumptions anymore but clear
> rules independent on the future implementation decisions.
I agree that that should be done where it is useful and necessary, but
the specific example you cited was neither. In Go it is not necessary
for code to understand precisely how arrays or slices are laid out, as
long as the reflect API is implemented correctly. For quite a long time
gccgo implemented strings differently from 6g/8g, and all the Go
libraries still worked fine (admittedly I did wind up changing gccgo to
use the 6g/8g representation as it made string slicing more efficient).
Even today there are relatively subtle differences between how 6g/8g and
gccgo implement interfaces and methods; these differences are hidden
inside the reflect API.
In general we should not confuse the language with the implementation,
and we should only constrain the implementation where it is necessary
and useful. It's OK if unsafe code only works with a single
implementation.
Ian
Not yet.
> C# guarantees that once an unsafe pointer is pinned with the "fixed"
> statement, all calculations based on this pointer are valid within the
> statement body regardless the data types of intermediate results. I
> don't see how a similar guarantee can be provided by just reporting Go
> unsafe pointers to the garbage collector.
Maybe we'll have to allow addition on unsafe.Pointers.
I don't know. We don't have to figure that out today.
Russ
> On 28 Jun., 00:43, Ian Lance Taylor <i...@google.com> wrote:
>>
>> It is perhaps worth noting that the current GC used by 6g/8g does not
>> take place at arbitrary moments.
>>
>
> But the current GC is not a problem. Perhaps any mark-and-sweep
> collector is not a problem - for instance, I have some limited
> experience with using Boehm's package as a garbage collector for Go.
My point is that 6g/8g can convert to a compacting GC while retaining
the feature that GC does not take place at arbitrary moments, which
makes the issue of fixing an unsafe.Pointer for the duration of a
statement of less interest.
> By the way, this may happen earlier than expected. What if someone
> will port Go to .Net?
Then at the present time I would expect them to make each unsafe.Pointer
fixed at the .Net level without changing anything at the Go language
level. And I would expect them to adjust the reflect API as required to
make it work on .Net.
> I would agree if the unsafe mode were used only in the restricted set
> of standard Go packages carefully managed by the core Go development
> team. But, as I said, there are good reasons to expect that in a
> systems programming language like Go the unsafe mode would be used
> rather frequently by various developers.
You're essentially arguing for a mode in between safe and unsafe. I
simply don't agree that we should change the language speculatively
because a compacting garbage collector might be implemented in the
future.
Ian
>> My point is that 6g/8g can convert to a compacting GC while retaining
>> the feature that GC does not take place at arbitrary moments, which
>> makes the issue of fixing an unsafe.Pointer for the duration of a
>> statement of less interest.
>
> I still fail to understand how exactly the garbage collector is
> supposed to coordinate its activities with concurrently running
> goroutines manipulating unsafe pointers.
The current GC does not coordinate its activities with concurrently
running goroutines in any special way. It simply asks all of them to
stop, and they stop when they choose to heed the request. I'm not
saying this is ideal, but it is what happens at present. A GC which
works while other goroutines continue to run is desirable but would have
to be implemented completely differently.
>> Then at the present time I would expect them to make each unsafe.Pointer
>> fixed at the .Net level without changing anything at the Go language
>> level. And I would expect them to adjust the reflect API as required to
>> make it work on .Net.
>>
>
> Making each unsafe.Pointer fixed at the .NET level would not work in
> general case because in Go unsafe pointers can be stored in some
> global data structures for the arbitrary periods of time. But in .NET
> pointers should be fixed for a rather short duration.
When an unsafe.Pointer is stored in a global data structure, the garbage
collector will be aware of it, just as it is aware of any pointer stored
in a data structure. The difficulties are with unsafe.Pointer values
being used while GC is running, or with unsafe.Pointer values which have
been converted to uintptr values and are thus invisible to the garbage
collector.
> Adjusting the present reflect API for .NET is itself not a trivial
> task because pointers of Go cannot be easily or efficiently mapped
> to .NET managed pointers. (At least, I don't see a reasonable solution
> for such a mapping without making some unsafe assumptions regarding
> physical layout of .NET objects.)
The reflect API certainly requires knowledge of physical layout of
objects. That is part of what makes Go a systems programming language.
I have no idea whether it is possible to implement that reasonable in
.NET. It may be that Go is not a suitable language for .NET, I don't
know enough to comment.
>> I simply don't agree that we should change the language speculatively
>> because a compacting garbage collector might be implemented in the
>> future.
>>
>
> If changes of this sort are required to make Go compatible with
> compacting garbage collectors, then in its present form the language
> is unable to work with collectors of this type. This is exactly what I
> am arguing for.
I think I understand the argument, I just don't think the point has been
proven. I am simply putting the ideas the other way around. First we
try to implement a compacting garbage collector; then, if that fails,
but would work if the language were adjusted, we consider adjusting the
language. Approaching the problem in that order is why I say that I
don't agree that we should change the language speculatively. We should
change it if we know it is required, not because we think it might be.
Ian
>>
>> The current GC does not coordinate its activities with concurrently
>> running goroutines in any special way. It simply asks all of them to
>> stop, and they stop when they choose to heed the request. I'm not
>> saying this is ideal, but it is what happens at present. A GC which
>> works while other goroutines continue to run is desirable but would have
>> to be implemented completely differently.
>>
>
> Apparently, I still miss the point. What if the garbage collector will
> stop the world while some goroutine is in the middle of something like
> the following code sequence [...]
As I said, the GC goroutine makes a request, and other goroutines stop
when they choose to heed the request.
The compiler can arrange to not permit a goroutine to stop while in a
loop involving an unsafe.Pointer.
>> When an unsafe.Pointer is stored in a global data structure, the garbage
>> collector will be aware of it, just as it is aware of any pointer stored
>> in a data structure. The difficulties are with unsafe.Pointer values
>> being used while GC is running, or with unsafe.Pointer values which have
>> been converted to uintptr values and are thus invisible to the garbage
>> collector.
>>
>
> Yes, and this is why fixing unsafe pointers for the duration of
> address calculations is critical. In C# this is done explicitly. You
> propose implicit fixing of each Go unsafe pointer. It is not clear,
> however, when and how to "unfix" them, provided that the lifetime of
> these pointers may be arbitrarily long. Reporting unsafe pointers to
> the garbage collector will neither eliminate the need of fixing them
> for calculations, nor help unfixing them once calculations are done.
As far as I can see, it is only necessary to fix unsafe.Pointer values
while they are being operated on, which is to say, during a function.
It is not necessary to fix them when they are stored in a data
structure. The lifetime of a function is not arbitrarily long.
>> I think I understand the argument, I just don't think the point has been
>> proven. I am simply putting the ideas the other way around. First we
>> try to implement a compacting garbage collector; then, if that fails,
>> but would work if the language were adjusted, we consider adjusting the
>> language. Approaching the problem in that order is why I say that I
>> don't agree that we should change the language speculatively. We should
>> change it if we know it is required, not because we think it might be.
>>
>
> Just above I posted an example of the real Go library code that
> suggests that the existing language design will cause critical
> problems with compacting garbage collectors. Does not this prove the
> point?
No, per my response. And even if it did, I would still be in favor of
putting the ideas the other way around. It may be that nobody ever
implements a compacting garbage collector for Go. If that should turn
out to be the case, then there would never be a reason to modify the
language to support it.
Ian
On 8 Jul., 23:58, bflm <befeleme...@gmail.com> wrote:
> I think a moving GC can handle unsafe pointers without any problem. The
> pinning in .net is AFAIK important only for pointers from the "outside
> world" (e.g. a buffer address passed to a WIN32 API function like file read)
> to not become invalid when it would crash the process.
>
I think you are mistaken. See for example:
"In an unsafe context, the embedded-statement (§15) production permits
an additional construct, the fixed statement, which is used to “fix” a
moveable variable such that its address remains constant for the
duration of the statement."
"For each address computed by a fixed-pointer-initializer the fixed
statement ensures that the variable referenced by the address is not
subject to relocation or disposal by the garbage collector for the
duration of the fixed statement. [Example: If the address computed by
a fixed-pointer-initializer references a field of an object or an
element of an array instance, the fixed statement guarantees that the
containing object instance is not relocated or disposed of during the
lifetime of the statement. end example]"
What if that loop also tries to receive a value from a channel, and
the sending goroutine has already stopped to wait for the GC?
Note that the scheduler generally can't know which goroutine is the
next sender on that channel. It could even be the one that wants to
run the GC...
> As far as I can see, it is only necessary to fix unsafe.Pointer values
> while they are being operated on, which is to say, during a function.
> It is not necessary to fix them when they are stored in a data
> structure. The lifetime of a function is not arbitrarily long.
For all practical purposes, the lifetime of a function *is*
arbitrarily long if the function in question happens to be called
'main·main()'.
>> The compiler can arrange to not permit a goroutine to stop while in a
>> loop involving an unsafe.Pointer.
>>
>
> Yes, but then you need a very intelligent compiler in order to
> reliably detect all "involvements" of unsafe pointers that may lead to
> invalid addresses. I don't know whether such a compiler can be created
> and anyway explicit "fixed" blocks placed by a programmer seem more
> practical.
I assert that no special intelligence is required here. It's similar
to, but simpler than, the restrict qualifier in C99. It's possible to
fail conservatively just as is true for the restrict qualifier.
> And anyway, no mechanism of this kind is available in the present Go
> implementation.
Of course not, because it is not necessary, because there is no
compacting garbage collector.
>> As far as I can see, it is only necessary to fix unsafe.Pointer values
>> while they are being operated on, which is to say, during a function.
>> It is not necessary to fix them when they are stored in a data
>> structure. The lifetime of a function is not arbitrarily long.
>>
>
> In principle, the lifetime of a function can be almost as long as
> lifetime of a whole program. And lifetime of an unsafe pointer may be
> not limited by the lifetime of a function in which this pointer's
> value is created. And, as I mentioned, it appears rather uneasy to
> track automatically critical periods in the lifetime of unsafe
> pointers.
Fair enough, when calling a function in a loop involving unsafe.Pointer
it may be necessary to store the unsafe.Pointer in an area known to the
garbage collector and reload it after the function call returns.
>> No, per my response. And even if it did, I would still be in favor of
>> putting the ideas the other way around. It may be that nobody ever
>> implements a compacting garbage collector for Go. If that should turn
>> out to be the case, then there would never be a reason to modify the
>> language to support it.
>>
>
> Sure, the garbage collector of Go still has a long way to go.
>
> But let's recall how this discussion was started. Go has been praised
> as having the superior programming model. I argued that such a praise
> may be a bit premature provided that, for instance, Go in its present
> state is hardly able to support compacting garbage collectors.
> Furthermore, comparison of unsafe features in Go and C# suggests that
> the latter language is superior in this respect. Whether the
> implementation of a compacting garbage collector in Go will actually
> take place, does not matter when programming models are compared. It
> just appears that at present Go is not fully compatible with the
> (supposedly) most advanced and efficient garbage collection
> technologies, while other languages like C# are.
I keep repeating myself, you keep repeating yourself. One of us fails
to understand what the other is saying.
Ian
Fair enough, when calling a function from code using unsafe.Pointer
values it may be necessary to store the unsafe.Pointer in an area known
to the garbage collector and reload it after the function call returns.
Ian
> Where is the conflict between the N-1 and N-2 posts?
Conflicting is your statement "The pinning in .net is AFAIK important
only for pointers from the "outside world".
> I fail to see it as a conflicting statement. Unsafe pointers not interacting
> with native code are IMO not important - they are not in principle a problem
> for a GC. A moving GC can handle them (probably with some extra bookeeping).
In your original statement ("The pinning in .net is AFAIK important
only for pointers from the "outside world") you discuss
specifically .NET and not some abstract garbage collected platform.
And in .NET fixing unsafe pointers _is_ important out of the calling
native code context, contrary to what you originally stated.
> For a specific implementation of such moving GC they could be a problem
> though - trade-off of efficiency/space etc. I know about an experimental
> implementation where every "pointer" is a two word structure because of
> simplifying GC things. Hypothetically only, one can also e.g. make every
> pointer doubly indirecting for an extra simple moving GC at the cost of
> execution performance (and memory fragmentation due to the intermediate
> indirection).
>
Of course if a value can be declared as a pointer then this pointer
can be in principle tracked by the garbage collector (although perhaps
with a significant performance penalty; its is also becomes unclear
what is then the difference between safe and unsafe pointers.)
However, this is not a case when for the purpose of address
calculations pointers are temporarily represented as integers, all
arithmetic is performed on those integers, which are converted back to
pointers in the end. And this exactly how Go at present does implement
address calculations.
C# provides address arithmetic for unsafe
pointers as a language feature, while Go doesn't. In Go unsafe.Pointer
has almost no functionality of its own, being just a passive link
between true managed typesafe pointers and integers (uintptr) actually
used for all address calculations.
> So I think Ian is right - usage of unsafe pointers in e.g. reflect can
> *possibly* be a future problem for some specific future GC, but
> not necessarily for all of GCs, thus changing the language for the maybe
> never-to-be-written-GC is not a good idea.
Garbage collection has been advertised among a few salient features of
Go and the present deisgn of Go is not compatible with most advanced
garbage collection technologies.
Well. perhaps this is really not a
serious issue ...