0

I am trying to implement a per go routine statistics. I want to come up with an array such as statistics[number_of_thread][statistics_type] and update the stat from each go routine. Eventually, I can either display all stats per go routine or can sum up the values of a single stat type from all go routines and display that. For this I need to identify each go routine. If this was pthread, then in C, I can achieve this by using pthread_key right at the beginning of the thread function:

pthread_key_t trace_key; >>>> This is global
uint32_t gbl_ctr; >>> This is global

pthread_setspecific(trace_key,(void *)__sync_fetch_and_add(&gbl_ctr, 1)) >>> Used in thread function.

Then, while updating the statistics, I can use pthread_getspecific() which would return the value specific to the thread which I can use to index the row of the above 'statistics' structure.

Is there something similar to pthread key in GO?

Thanks in advance.

NeilB
  • 347
  • 2
  • 16
  • 1
    By design goroutines are not addressable, and have no local storage. – JimB Apr 07 '21 at 21:24
  • Possible duplicate https://stackoverflow.com/questions/31932945/does-go-have-something-like-threadlocal-from-java – JimB Apr 07 '21 at 21:27
  • 1
    This is one of those Go things where the answer is "Don't do that." If you want data per goroutine then declare it as a function level variable in the goroutine function. Simple. – Zan Lynx Apr 07 '21 at 21:44
  • 1
    Oh and if you want to track stats shove the stat update off to a channel and have a stats collector goroutine reading them. – Zan Lynx Apr 07 '21 at 21:45
  • 1
    And also if you want unique goroutine identifiers I like having a goroutine ID server which just creates IDs (increment a local counter) and writes them to a channel. Read the channel, get a unique ID. Very simple and all locking is done by the channel which is pretty well optimized in Go. – Zan Lynx Apr 07 '21 at 21:56
  • @ZanLynx What did you mean by function level variable? I see that a local variable declared inside parent function is accessible within anonymous functions called from the parent but if it is not anonymous call then compilation error (as expected). I am very new to GO. Is there any way to define a local variable inside a unction which will be accessible to all sub functions (without passing it as argument)? – NeilB Apr 08 '21 at 07:25
  • @ZanLynx I like the channel idea. I also found a similar discussion in https://stackoverflow.com/questions/16783273/best-way-to-implement-global-counters-for-highly-concurrent-applications. Is it accepted fact that channel method provides better performance that atomically incrementing a counter? – NeilB Apr 08 '21 at 07:28
  • 1
    @NeilB, of course atomic operations are going to be faster for counters than channels. Channels simply do more and have more overhead involved. – JimB Apr 08 '21 at 12:24
  • 1
    @JimB There's a small amount more overhead on a channel. But atomic operations have the downside that too many programmers think they're cheap. They are not cheap. And if someone screws up and allocates multiple atomic values on the same cache line and then uses them from different threads, performance goes to trash. Channels are a lot smarter than that. – Zan Lynx Apr 08 '21 at 16:07
  • @JimB Hey here is a quote from https://golang.org/pkg/sync/atomic/ "These functions require great care to be used correctly. Except for special, low-level applications, synchronization is better done with channels or the facilities of the sync package. Share memory by communicating; don't communicate by sharing memory." – Zan Lynx Apr 08 '21 at 16:13
  • @ZanLynx, yes I am very aware of the documentation, and channels are cheap in general, but using them implies coordinating goroutines which is not cheap relative to atomic operations (and while there are worst-case examples like you mention, there are other ways to thrash the cpu cache, and there is the converse that many atomic operations are essentially free). Of course one needs to know what they are doing when using them, but I have also seen so many programmers make unmaintainable messes of goroutines and channels when simple mutex or atomic would suffice. – JimB Apr 08 '21 at 16:22
  • @JimB Well, my experience is completely different. I've seen too many programmers trying to recreate their C++ app in Go by using mutexes, atomics and everything except channels. Channels are the primary thing for synchronization in Go and should be used if at all possible. Shared data structures are a threat and menace. – Zan Lynx Apr 09 '21 at 15:13
  • @ZanLynx: take `expvar` for example: [`Int.Add`](https://go.googlesource.com/go/+/go1.16.2/src/expvar/expvar.go#60). I agree they need to be used in moderation, but there's no need to setup channels and collector goroutines for something this simple. – JimB Apr 09 '21 at 15:26

0 Answers0