[go-nuts] Re: programmatic way to find if application go binary is built with -cover flag ?

2024-05-14 Thread Akash Kumar

I unable to find a flag from corresponds to -cover in the result returned 
from debug.buildInfo
On Monday, May 13, 2024 at 10:51:33 PM UTC+5:30 Tamás Gulácsi wrote:

> runtime/debug.ReadBuildInfo is a good source of truth:
> $ strings bin/godeb|grep '^build\s'
>
> build   -buildmode=exe
> build   -compiler=gc
> build   
> DefaultGODEBUG=httplaxcontentlength=1,httpmuxgo121=1,panicnil=1,tls10server=1,tlsrsakex=1,tlsunsafeekm=1
> build   CGO_ENABLED=1
> build   CGO_CFLAGS=
> build   CGO_CPPFLAGS=
> build   CGO_CXXFLAGS=
> build   CGO_LDFLAGS=
> build   GOARCH=amd64
> build   GOOS=linux
> build   GOAMD64=v1
> build   -buildmode=exe
> build   -compiler=gc
> build   
> DefaultGODEBUG=httplaxcontentlength=1,httpmuxgo121=1,panicnil=1,tls10server=1,tlsrsakex=1,tlsunsafeekm=1
> build   CGO_ENABLED=1
> build   CGO_CFLAGS=
> build   CGO_CPPFLAGS=
> build   CGO_CXXFLAGS=
> build   CGO_LDFLAGS=
> build   GOARCH=amd64
> build   GOOS=linux
> build   GOAMD64=v1
>
> Akash Kumar a következőt írta (2024. május 13., hétfő, 18:42:30 UTC+2):
>
>> I am writing an external go program that will take the path to another go 
>> binary as argument, and checks if the binary was built with cover flag.
>>
>> `debug.ReadBuildInfo()` is meant for getting build info embedded in the 
>> running binary as 
>> > ReadBuildInfo returns the build information embedded in the running 
>> binary 
>>
>> On Monday, May 13, 2024 at 6:37:46 PM UTC+5:30 Zxilly Chou wrote:
>>
>>> try debug.ReadBuildInfo(), then iterate the pair in the buildinfo.
>>> Settings
>>>
>>> 在2024年5月13日星期一 UTC+8 20:56:51 写道:
>>>
 Is there a way in go to find whether a go binary is built with -cover 
 flag ?
>>>
>>>

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/9fda396a-b79e-4b9e-9bc0-13a9cef2c921n%40googlegroups.com.


Re: [go-nuts] Bitmask is slower than modulo calculation

2024-05-14 Thread 'Keith Randall' via golang-nuts
Your test is benchmarking int->any conversions more than it is testing the 
underlying modulo/mask difference.
When you pass an integer to Enqueue, it is converted to any, which 
(usually) involves an allocation. That will swamp the cost of any single 
arithmetic operation.

There are a few ways to fix it. Probably the simplest is to make your ring 
buffers generic on the element type.
You could also fix the benchmark, by precomputing the any-typed elements 
you're going to enqueue before starting the timer.

When you get a surprising benchmark result, always run the benchmark with 
profiling on (-cpuprofile) and look at the resulting profile. This is a 
case where it would be obvious what the problem is.
On Sunday, May 12, 2024 at 10:18:38 PM UTC-7 robert engels wrote:

> Hi. This is still not correct. Use the “for.. in b.N” as discussed in the 
> blog in order to understand the per op difference - which will be more 
> accurate for a microbenchmark timing,
>
> But, if you really want to make a case that bit mask is slower than mod, 
> then a simpler test would be better - you can do these ops on in loop using 
> b.N to time the difference.
>
>
>
> On May 12, 2024, at 8:28 PM, Yuta MIYAKE  wrote:
>
> Thank you. 
>
> This is benchstat result. new test code follows:
>
> ❯ go test -test.bench BenchmarkTestSingleModulo -count=10 -cpu=1 > 
> modulo.txt
> ❯ go test -test.bench BenchmarkTestSingleBitMask -count=10 -cpu=1 > 
> bitmask.txt
> ❯ benchstat modulo.txt bitmask.txt
> goos: darwin
> goarch: arm64
> pkg: ringbuffer
>   │ modulo.txt │bitmask.txt│
>   │   sec/op   │   sec/opvs base   │
> TestSingleModulo6.648 ± 1%
> TestSingleBitMask6.694 ± 5%
> geomean 6.6486.694   ? ¹ ²
>
>
> new test code:
>
> const BufferSize = 2 * 1024 * 1024
>
> func benchmarkSingle(rb RingBuffer) {
>
>
> total := 50
> for i := 0; i < total; i++ {
> for j := 0; j < 1000; j++ {
> rb.Enqueue(j)
> }
> for j := 0; j < 1000; j++ {
> rb.Dequeue()
> }
> }
> }
>
>
> func BenchmarkTestSingleModulo(b *testing.B) {
> rb := NewRingBuffer0(BufferSize)
> b.ResetTimer()
> benchmarkSingle(rb)
> }
>
> func BenchmarkTestSingleBitMask(b *testing.B) {
> rb := NewRingBuffer1(BufferSize)
> b.ResetTimer()
> benchmarkSingle(rb)
> }
>
> On Monday, May 13, 2024 at 8:20:05 AM UTC+9 robert engels wrote:
>
>> Use the Go benchmarking facilities, see 
>> https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go
>>
>> On May 11, 2024, at 9:57 PM, leon  wrote:
>>
>> I'm trying to prove an optimization technique for ring buffer is 
>> effective. One of the technique is using bitmask instead of modulo to 
>> calculate a wrap around. However, in my environment, modulo is slightly 
>> faster in a test where 1 billion items are enqueued /dequeued by a single 
>> goroutine. What do you think could be the cause? 
>>
>> Full code:
>> https://go.dev/play/p/H933oqrhPI-
>>
>> Environment:
>> * go version go1.21.4 darwin/arm64
>> * Apple M1 Pro
>>
>> RingBuffer with modulo:
>> ```
>> type RingBuffer0 struct {
>> writeIdx uint64
>> readIdx  uint64
>> buffers  []any
>> size uint64
>> }
>>
>> func NewRingBuffer0(size uint64) *RingBuffer0 {
>> rb := &RingBuffer0{}
>> rb.init(size)
>> return rb
>> }
>>
>> func (rb *RingBuffer0) init(size uint64) {
>> rb.buffers = make([]any, size)
>> rb.size = size
>> }
>>
>> func (rb *RingBuffer0) Enqueue(item any) error {
>> if rb.writeIdx-rb.readIdx == rb.size {
>> return ErrBufferFull
>> }
>> rb.buffers[rb.writeIdx%rb.size] = item
>> rb.writeIdx++
>> return nil
>> }
>>
>> func (rb *RingBuffer0) Dequeue() (any, error) {
>> if rb.writeIdx == rb.readIdx {
>> return nil, ErrBufferEmpty
>> }
>> item := rb.buffers[rb.readIdx%rb.size]
>> rb.readIdx++
>> return item, nil
>> }
>> ```
>>
>> RingBuffer with bitmask:
>> change each module calculation to the code below
>> * rb.buffers[rb.writeIdx&(rb.size-1)] = item
>> * item := rb.buffers[rb.readIdx&(rb.size-1)]
>>
>> Test:
>> func TestSingle(rb RingBuffer) {
>> start := time.Now()
>> total := 50
>> for i := 0; i < total; i++ {
>> for j := 0; j < 1000; j++ {
>> rb.Enqueue(j)
>> }
>> for j := 0; j < 1000; j++ {
>> rb.Dequeue()
>> }
>> }
>> end := time.Now()
>> count := total * 2000
>> duration := end.Sub(start).Milliseconds()
>> fmt.Printf("%d ops in %d ms\n", count, duration)
>> }
>>
>>
>> -- 
>> 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.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/golang-nuts/b9c4d2e0-4ab4-4d27-9359-abd8c090ae33n%40googlegroups.com
>>  
>> 
>> .
>>
>>
>>
> -- 
> You received this message because you are subscribed to the Google Groups 

Re: [go-nuts] Re: raw bit types without arithmetic

2024-05-14 Thread jimmy frasche
Arrays are arrays regardless of what they're arrays of. So it would be
strange for arrays of certain things to have properties that other
arrays don't have and bitwise ops don't make sense for arrays of, say,
strings.

Also some processors support these sizes natively but wouldn't support
a [4096]byte natively. On processors that don't support all or some of
these sizes it would need to fake it by doing m operations† but that's
bounded and if, for example, the target processor supports 256 bit but
not 512 bit values it can use two 256 ORs instead of four 64 bit ORs.
Maybe that could be made to work in general and if so that would be
great but it's not the only benefit of these types.

† except for shifts, those would have to deal with carries. That may
be a problem, but I think even then it should be fast enough to not be
an issue the way faking div or something very expensive like that
would be.

On Mon, May 13, 2024 at 8:41 PM Kevin Chowski  wrote:
>
> Sorry, sent too early.
>
> Obviously that doesn't support the bitwise type conversion you mentioned; I 
> don't really have an opinion on that one, I don't really convert from float 
> to bits very often.
>
> It seems like the compiler optimizations you mention could happen with or 
> without these extra types, if such optimizations just worked on byte arrays 
> in general.
>
> On Monday, May 13, 2024 at 9:38:36 PM UTC-6 Kevin Chowski wrote:
>>
>> How about just allowing bitwise operations on byte arrays (of the same 
>> length)?
>>
>> On Monday, May 13, 2024 at 2:51:19 PM UTC-6 jimmy frasche wrote:
>>>
>>> I'm not 100% sure if this is a good idea but it's been knocking around
>>> in my head all week so I thought I'd share in case it has any merit:
>>>
>>> Introduce bitsN types for N=8, 16, 32, 64, 128, 256, and 512.
>>>
>>> These are similar to uintN but they are unordered and have no
>>> arithmetic operations defined.
>>>
>>> They only have literals, comparison, and bitwise operations.
>>> (fmt.Print and friends should render them in hex by default.)
>>>
>>> Conversions between the numeric types and the bitN are allowed, which,
>>> for example, let's us rewrite math.Float64bits as simply
>>>
>>> func Float64bits(f float64) uint64 {
>>> return uint64(bits64(f))
>>> }
>>>
>>> Since there are no arithmetic operations, the 128+ sizes should be
>>> fairly efficient to fake on architectures without special
>>> instructions/registers.
>>>
>>> Potential uses:
>>>
>>> UUIDs could be stored as a bits128 instead of a [2]uint64 or [16]byte.
>>>
>>> SIMD vectors could be created and stored easily, even if they need
>>> assembly to operate on them efficiently.
>>>
>>> Same for int128/uint128 values or even for more exotic numeric types
>>> like the various float16 definitions or "floating slash" rationals.
>>>
>>> It would also be handy to have larger bitsets that are easy to work with.
>
> --
> 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+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/1f0329c1-8b82-4683-999e-62b9a046c0a8n%40googlegroups.com.

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CANG3jXLdcRs9AMS_xE15EEgqKmYFRgexgGBfpSxVA-%3D60A69sQ%40mail.gmail.com.


[go-nuts] using runtime cgo.Handle passing struct types

2024-05-14 Thread Pavan
Hi, 
I need to pass value of struct type, which has C strings and functions to C 
function as void* argument.  C layer would provide this struct type data 
back to go function. Below is the sample program. It panics if the handle 
used is returned from getH function. It works fine if the handle is global. 
Can the handle be dynamically returned from getH and make it work. Please 
correct if i missed something..



package main

/*
struct dt {
  void *context;
};
typedef struct dt dt;

extern void MyGoPrint(void *context);
static inline void myprint(struct dt *a1) {
MyGoPrint(a1->context);
}
*/
import "C"
import (
"context"
"runtime/cgo"
"unsafe"
)

//export MyGoPrint
func MyGoPrint(context unsafe.Pointer) {
h := *(*cgo.Handle)(context)
val := h.Value().(accessTokenCB)
println(val.id)
h.Delete()
}

type At struct {
Tok string
}

type accessTokenCB struct {
ctx context.Context
callbackfunc(context.Context, *At) error
id  uint64
ctoken  *C.char
cprivateKey *C.char
}

func getH() cgo.Handle {
cb := func(ctx context.Context, tok *At) error {
tok.Tok = "123"
return nil
}
val := accessTokenCB{callback: cb, ctx: context.Background(), id: 32, 
ctoken: nil, cprivateKey: nil}
h := cgo.NewHandle(val)
return h

}

var h cgo.Handle

func main() {
var h cgo.Handle // commenting this line runs the program successfully else 
it panics. (cgo argument has Go pointer to unpinned Go pointer)
h = getH()
var poolCt C.dt
poolCt.context = unsafe.Pointer(&h)
C.myprint(&poolCt)
// Output: 32
}

-- 
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+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/1b34c3ba-cf4b-4663-b509-5ef84e9600c1n%40googlegroups.com.