uintptr vs unsafe.Pointer

4,125 views
Skip to first unread message
Message has been deleted

ziutek

unread,
Jan 11, 2011, 4:08:36 AM1/11/11
to golang-nuts
Is there a significant difference between using uintptr and
unsafe.Pointer as unexported field of struct.

I use uintptr for parameters binding in MyMySQL: http://github.com/ziutek/mymysql

All unsafe code is in unsafe.go file. When I need to get the value of
binded parameter, I must convert uintptr to unsafe.Pointer before
dereference the value. I prefer uintptr because I can avoid import
unsafe package as long as possible.

I have written simple performance test for this problem, and it didn't
show significant differences:

package main

import (
"time"
"fmt"
"unsafe"
)

func main() {
count := int(1e7)
ii := 0
kk := 0
ii_ptr := unsafe.Pointer(&ii)
kk_ptr := unsafe.Pointer(&kk)
ii_uptr := uintptr(ii_ptr)
kk_uptr := uintptr(kk_ptr)

ns1 := time.Nanoseconds()
for nn := 0; nn < count; nn++ {
ptr := ii_ptr
*(*int)(ptr) = nn
ptr = kk_ptr
*(*int)(ptr) = nn
ptr = ii_ptr
*(*int)(ptr) = kk
ptr = kk_ptr
*(*int)(ptr) = ii
}
ns2 := time.Nanoseconds()

fmt.Printf("%d, %d, %f iter/s\n",
ii, kk, float(count)*1e9 / float(ns2-ns1))

ii = 0
kk = 0

ns1 = time.Nanoseconds()
for nn := 0; nn < count; nn++ {
uptr := ii_uptr
*(*int)(unsafe.Pointer(uptr)) = nn
uptr = kk_uptr
*(*int)(unsafe.Pointer(uptr)) = nn
uptr = ii_uptr
*(*int)(unsafe.Pointer(uptr)) = kk
uptr = kk_uptr
*(*int)(unsafe.Pointer(uptr)) = ii
}
ns2 = time.Nanoseconds()

fmt.Printf("%d, %d, %f iter/s\n",
ii, kk, float(count)*1e9 / float(ns2-ns1))
}

Gustavo Niemeyer

unread,
Jan 11, 2011, 7:00:01 AM1/11/11
to ziutek, golang-nuts
> Is there a significant difference between using uintptr and
> unsafe.Pointer as unexported field of struct.
(...)

> I have written simple performance test for this problem, and it didn't
> show significant differences:

There's no runtime penalty in using uintptr vs. unsafe.Pointer. It's
effectively just a pointer.

--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/blog
http://niemeyer.net/twitter

ziutek

unread,
Jan 11, 2011, 9:23:51 AM1/11/11
to golang-nuts
Are there any garbage collection related differences between
unsafe.Pointer and uintptr?

How GC will work with this code:

package main

import (
"fmt"
"unsafe"
)

func returnPointer() unsafe.Pointer {
v := 1
return unsafe.Pointer(&v)
}

func returnUintptr() uintptr {
v := 2
return uintptr(unsafe.Pointer(&v))
}

func main() {
p1 := returnPointer()
p2 := returnUintptr()
p3 := int(p2)
p2 = uintptr(p1)
p1 = nil
p2 += 2
p3 += 2
p2 -= 2
p3 -= 2
fmt.Println(*(*int)(unsafe.Pointer(p2)))
fmt.Println(*(*int)(unsafe.Pointer(uintptr(p3))))
}

Ian Lance Taylor

unread,
Jan 11, 2011, 9:55:21 AM1/11/11
to ziutek, golang-nuts
ziutek <ziu...@Lnet.pl> writes:

> Are there any garbage collection related differences between
> unsafe.Pointer and uintptr?

Yes. If your struct has no pointers at all, only uintptr fields, then
if you do something like make([]MyStruct, 10) the garbage collector
won't look at any pointers in that slice. If there are any pointers in
the struct, then the current garbage collector will look at the whole
memory area--it doesn't know which fields are pointers and which aren't.
It's possible that this will change in the future. If the value really
is a pointer I would recommend using unsafe.Pointer, or, if you prefer,
*byte.

You will always have to convert to a pointer type before dereferencing
the value; nothing else makes sense. And Go does not permit converting
uintptr to a pointer type directly, because that would be unsafe.
Converting to unsafe.Pointer first is required to explicitly bypass Go's
type safety rules.

Ian

ziutek

unread,
Jan 11, 2011, 3:55:33 PM1/11/11
to golang-nuts
There is my struct definition:

type paramValue struct {
typ uint16
addr uintptr
is_ptr bool
raw bool
length int
}

paramValue instance is allocated this way:

func bindValue(val reflect.Value) (out *paramValue) {
out = &paramValue{addr: val.Addr()}
//...
return
}

I wonder, if addr is the sole reference to the variable, will GC know
about this and don't free memory used by this variable? What's more,
will GC free memory if I assign to addr the address of another
variable or if GC garbage the instance of paramValue?

And what will happen if the type of addr would be the unsafe.Pointer?

Ian Lance Taylor

unread,
Jan 11, 2011, 4:30:10 PM1/11/11
to ziutek, golang-nuts
ziutek <ziu...@Lnet.pl> writes:

In the current implementation, I believe the GC will see the value of
addr and will not collect anything which it points to. If you change
addr, then the GC will collect the memory which it previously pointed
to.

However, while I think that is the case today, this is not fixed in
stone. I think it is likely that a future implementation of the GC will
not see the value of addr, and will collect whatever it points to,
leaving you with a dangling uintptr. Using the type unsafe.Pointer will
avoid this possible future problem. The GC will certainly never collect
anything that a field of type unsafe.Pointer points to.

Ian

ziutek

unread,
Jan 12, 2011, 3:42:23 AM1/12/11
to golang-nuts
If I understand correctly, it means that GC treats uintptr as pointer,
but in the future uintptr could be treated as ordinary int.

So I need to fix my struct, that there will be no problems in the
future.

Ian Lance Taylor

unread,
Jan 12, 2011, 10:18:15 AM1/12/11
to ziutek, golang-nuts
ziutek <ziu...@Lnet.pl> writes:

> If I understand correctly, it means that GC treats uintptr as pointer,
> but in the future uintptr could be treated as ordinary int.

I would say, rather, that the current GC doesn't know which fields in a
struct are pointers and which are not, so in effect everything is
treated as a pointer. In the future, the GC might know which fields are
pointers and which are not, and, if and when that changes happens,
uintptr will not be a pointer.

Ian

ziutek

unread,
Jan 12, 2011, 12:12:37 PM1/12/11
to golang-nuts
Now everything is clear. Thanks!

Gustavo Niemeyer

unread,
Jan 12, 2011, 12:18:41 PM1/12/11
to ziutek, golang-nuts
> Now everything is clear. Thanks!

If you're curious about the topic, search for "conservative garbage collection".

Reply all
Reply to author
Forward
0 new messages