2019-06-27 11:41:58 -04:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"runtime"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
"unsafe"
|
|
|
|
|
|
|
|
"git.wow.st/gmp/nswrap/examples/strings/ns"
|
|
|
|
)
|
|
|
|
|
|
|
|
func incr() func(bool) (int, float64) {
|
|
|
|
i := 0
|
|
|
|
b := 0.0
|
|
|
|
var mx sync.Mutex
|
|
|
|
return func(bad bool) (int, float64) {
|
|
|
|
mx.Lock()
|
|
|
|
if bad {
|
|
|
|
b++
|
|
|
|
defer mx.Unlock()
|
|
|
|
} else {
|
|
|
|
defer func() { i++; mx.Unlock() }()
|
|
|
|
}
|
|
|
|
if b == 0 {
|
|
|
|
return i, 0.0
|
|
|
|
} else {
|
2020-06-24 13:03:53 -04:00
|
|
|
return i, (b / float64(i)) * 100
|
2019-06-27 11:41:58 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type tracker struct {
|
|
|
|
add, drop func(*ns.Id)
|
2020-06-24 13:03:53 -04:00
|
|
|
check func()
|
|
|
|
i func(bool) (int, float64)
|
2019-06-27 11:41:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
type record struct {
|
2020-06-24 13:03:53 -04:00
|
|
|
ptr unsafe.Pointer
|
2019-06-27 11:41:58 -04:00
|
|
|
goPtr *ns.Id
|
2020-06-24 13:03:53 -04:00
|
|
|
when time.Time
|
2019-06-27 11:41:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func newTracker() (func(*ns.Id), func(*ns.Id), func()) {
|
|
|
|
addch := make(chan *ns.Id)
|
|
|
|
dropch := make(chan *ns.Id)
|
|
|
|
data := []record{}
|
|
|
|
var mux sync.Mutex
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case x := <-addch:
|
|
|
|
mux.Lock()
|
2020-06-24 13:03:53 -04:00
|
|
|
data = append(data, record{
|
|
|
|
x.Ptr(),
|
|
|
|
x,
|
|
|
|
time.Now(),
|
|
|
|
})
|
2019-06-27 11:41:58 -04:00
|
|
|
mux.Unlock()
|
|
|
|
case x := <-dropch:
|
|
|
|
mux.Lock()
|
2020-06-24 13:03:53 -04:00
|
|
|
data = append(data, record{
|
|
|
|
nil,
|
|
|
|
x,
|
|
|
|
time.Now(),
|
|
|
|
})
|
2019-06-27 11:41:58 -04:00
|
|
|
mux.Unlock()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
add := func(x *ns.Id) {
|
2020-06-24 13:03:53 -04:00
|
|
|
addch <- x
|
2019-06-27 11:41:58 -04:00
|
|
|
}
|
|
|
|
drop := func(x *ns.Id) {
|
2020-06-24 13:03:53 -04:00
|
|
|
dropch <- x
|
2019-06-27 11:41:58 -04:00
|
|
|
}
|
|
|
|
check := func() {
|
|
|
|
live := map[unsafe.Pointer]*ns.Id{}
|
|
|
|
bad := false
|
|
|
|
mux.Lock()
|
2020-06-24 13:03:53 -04:00
|
|
|
for _, r := range data {
|
2019-06-27 11:41:58 -04:00
|
|
|
if r.ptr != nil {
|
|
|
|
if live[r.ptr] != nil {
|
|
|
|
fmt.Printf("COLLISION: %p & %p -> %p\n", r.goPtr, live[r.ptr], r.ptr)
|
|
|
|
bad = true
|
|
|
|
}
|
|
|
|
live[r.ptr] = r.goPtr
|
|
|
|
} else {
|
2020-06-24 13:03:53 -04:00
|
|
|
delete(live, r.ptr)
|
2019-06-27 11:41:58 -04:00
|
|
|
}
|
|
|
|
}
|
2020-06-24 13:03:53 -04:00
|
|
|
fmt.Printf("Checked %d records -- ", len(data))
|
2019-06-27 11:41:58 -04:00
|
|
|
if bad {
|
|
|
|
fmt.Printf("failed\n")
|
|
|
|
} else {
|
|
|
|
fmt.Printf("ok\n")
|
|
|
|
}
|
|
|
|
mux.Unlock()
|
|
|
|
}
|
2020-06-24 13:03:53 -04:00
|
|
|
return add, drop, check
|
2019-06-27 11:41:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func mkstrings(t tracker) {
|
|
|
|
for {
|
|
|
|
//fmt.Printf("main thread: %t\n",ns.NSThreadIsMainThread())
|
2020-06-24 13:03:53 -04:00
|
|
|
x, b := t.i(false)
|
|
|
|
str := fmt.Sprintf("string %d", x)
|
2019-06-27 11:41:58 -04:00
|
|
|
s := ns.NSStringWithGoString(str)
|
|
|
|
//t.add(&s.Id)
|
|
|
|
for j := 0; j < 10; j++ {
|
|
|
|
sout := s.String()
|
|
|
|
if str != sout {
|
2020-06-24 13:03:53 -04:00
|
|
|
_, b = t.i(true)
|
2019-06-27 11:41:58 -04:00
|
|
|
fmt.Printf("%3.2f%% -- %d: '%s' '%s'\n", b, x, str, sout)
|
|
|
|
}
|
2020-06-24 13:03:53 -04:00
|
|
|
time.Sleep(time.Second / 1000)
|
2019-06-27 11:41:58 -04:00
|
|
|
}
|
2020-06-24 13:03:53 -04:00
|
|
|
if x%1000 == 0 {
|
2019-06-27 11:41:58 -04:00
|
|
|
fmt.Printf("%3.2f%% -- %s\n", b, time.Now().Format("03:04:05.000"))
|
|
|
|
}
|
|
|
|
//t.drop(&s.Id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
runtime.GOMAXPROCS(4)
|
|
|
|
fmt.Printf("Starting\n")
|
|
|
|
//ns.NSThreadNew().Start()
|
|
|
|
fmt.Printf("multithreaded: %t\n", ns.NSThreadIsMultiThreaded())
|
|
|
|
//pool := ns.NSAutoreleasePoolAlloc()
|
|
|
|
add, drop, check := newTracker()
|
|
|
|
i := tracker{add, drop, check, incr()}
|
|
|
|
go mkstrings(i)
|
|
|
|
go mkstrings(i)
|
|
|
|
go mkstrings(i)
|
|
|
|
go mkstrings(i)
|
|
|
|
go mkstrings(i)
|
|
|
|
go mkstrings(i)
|
|
|
|
go mkstrings(i)
|
|
|
|
go mkstrings(i)
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
runtime.GC()
|
2020-06-24 13:03:53 -04:00
|
|
|
time.Sleep(time.Second / 100)
|
2019-06-27 11:41:58 -04:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
time.Sleep(time.Second * 600)
|
|
|
|
i.check()
|
|
|
|
|
|
|
|
//pool.Drain()
|
|
|
|
os.Exit(0)
|
|
|
|
}
|