|
|
Created:
11 years, 8 months ago by funny.falcon Modified:
11 years, 2 months ago CC:
golang-codereviews Visibility:
Public. |
Descriptiontime: lower level interface to Timer: embedding, compact interface callback with fast callback
In developed library, there is a need to setup timer per every outgoing request.
Allocating timer separately costs too much. Allocation func() for request's method also costs.
So that, embedding Timer into request struct and setting callback by pointer to
struct (which implements Expirator) give countable improvement.
BenchmarkPointerStop 5000000 297 ns/op
BenchmarkPointerStop-2 10000000 266 ns/op
BenchmarkPointerStop-3 10000000 289 ns/op
BenchmarkPointerStop-4 5000000 317 ns/op
BenchmarkEmbedStop 10000000 176 ns/op
BenchmarkEmbedStop-2 10000000 223 ns/op
BenchmarkEmbedStop-3 10000000 266 ns/op
BenchmarkEmbedStop-4 10000000 293 ns/op
Patch Set 1 #Patch Set 2 : diff -r 9810b5abd0ab https://code.google.com/p/go #Patch Set 3 : diff -r 9810b5abd0ab https://code.google.com/p/go #Patch Set 4 : diff -r 9810b5abd0ab https://code.google.com/p/go #Patch Set 5 : diff -r 9810b5abd0ab https://code.google.com/p/go #
Total comments: 1
Patch Set 6 : diff -r 9810b5abd0ab https://code.google.com/p/go #
MessagesTotal messages: 28
Hello golang-dev@googlegroups.com (cc: golang-dev@googlegroups.com), I'd like you to review this change to https://code.google.com/p/go
Sign in to reply to this message.
Hello golang-dev@googlegroups.com (cc: golang-dev@googlegroups.com), Please take another look.
Sign in to reply to this message.
R=dvyukov This CL isn't acceptable as-is (too much new weird API, and docs need lot of work), but perhaps you and Dmitry Vyukov can discuss what you need and what an alternative solution might be. On Fri, Aug 23, 2013 at 3:18 PM, <funny.falcon@gmail.com> wrote: > Hello golang-dev@googlegroups.com (cc: golang-dev@googlegroups.com), > > Please take another look. > > > https://codereview.appspot.**com/12876047/<https://codereview.appspot.com/128... > > -- > > ---You received this message because you are subscribed to the Google > Groups "golang-dev" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to golang-dev+unsubscribe@**googlegroups.com<golang-dev%2Bunsubscribe@googlegrou... > . > For more options, visit https://groups.google.com/**groups/opt_out<https://groups.google.com/groups/o... > . >
Sign in to reply to this message.
https://codereview.appspot.com/12876047/diff/10001/src/pkg/time/sleep.go File src/pkg/time/sleep.go (right): https://codereview.appspot.com/12876047/diff/10001/src/pkg/time/sleep.go#newc... src/pkg/time/sleep.go:137: // SetupExpire initialize already allocated timer to call e.Expire() after elapsed duration. An API that says "don't use me I am very dangerous and you may only use me in very specific cases when you are very careful" seems out-of-place in a very user-public package like time. Currently only runtime and syscall packages take the liberty of being dangerous.
Sign in to reply to this message.
On 2013/08/23 20:28:59, remyoudompheng wrote: > https://codereview.appspot.com/12876047/diff/10001/src/pkg/time/sleep.go > File src/pkg/time/sleep.go (right): > > https://codereview.appspot.com/12876047/diff/10001/src/pkg/time/sleep.go#newc... > src/pkg/time/sleep.go:137: // SetupExpire initialize already allocated timer to > call e.Expire() after elapsed duration. > An API that says "don't use me I am very dangerous and you may only use me in > very specific cases when you are very careful" seems out-of-place in a very > user-public package like time. > > Currently only runtime and syscall packages take the liberty of being dangerous. But why? If user is informed about dangers, why not give him ability to be fast? Our team is about to switch platform. I propose go. Alternative is C+libev+LuaJIT. I'm writting relatively lowlevel library for fast asynchronous network protocol. One of primary condition: every single request should have expiration timer. Within benchmark, there is over 500 000 rps. Without timers I could easely beat alternative solution, but it already have timers provided by libev, and thowe timers are cheap, cause they are embed. With proposed change I could contest with alternative. But Timer ought to be allocated (and func() trampoline), then I much slower simply cause of allocation and GC. OK, may be running Expire() within internal goroutine is nof critical for my case, cause timer likely to be stopped before expiration in 99.9%. But why not allow low level library's authors a possibility to be extremely fast?
Sign in to reply to this message.
Yuri, We do want things to be very fast, but we also want clean, simple APIs. It's a balance. If you can think of a simple API that can also be made fast and with less garbage, then that is interesting. http://golang.org/pkg/time/#Timer.Reset was added in Go 1.1 (largely for performance reasons). It's possible that new additions can be added, but only if they're useful and understandable too. On Fri, Aug 23, 2013 at 4:33 PM, <funny.falcon@gmail.com> wrote: > On 2013/08/23 20:28:59, remyoudompheng wrote: > > https://codereview.appspot.**com/12876047/diff/10001/src/** > pkg/time/sleep.go<https://codereview.appspot.com/12876047/diff/10001/src/pkg/time/sleep.go> > >> File src/pkg/time/sleep.go (right): >> > > > https://codereview.appspot.**com/12876047/diff/10001/src/** > pkg/time/sleep.go#newcode137<https://codereview.appspot.com/12876047/diff/10001/src/pkg/time/sleep.go#newcode137> > >> src/pkg/time/sleep.go:137: // SetupExpire initialize already allocated >> > timer to > >> call e.Expire() after elapsed duration. >> An API that says "don't use me I am very dangerous and you may only >> > use me in > >> very specific cases when you are very careful" seems out-of-place in a >> > very > >> user-public package like time. >> > > Currently only runtime and syscall packages take the liberty of being >> > dangerous. > > But why? If user is informed about dangers, why not give him ability to > be fast? > > Our team is about to switch platform. I propose go. Alternative is > C+libev+LuaJIT. > I'm writting relatively lowlevel library for fast asynchronous network > protocol. > One of primary condition: every single request should have expiration > timer. > Within benchmark, there is over 500 000 rps. > Without timers I could easely beat alternative solution, but it already > have timers provided by libev, and thowe timers are cheap, cause they > are embed. > With proposed change I could contest with alternative. But Timer ought > to be allocated (and func() trampoline), then I much slower simply cause > of allocation and GC. > > OK, may be running Expire() within internal goroutine is nof critical > for my case, cause timer likely to be stopped before expiration in > 99.9%. But why not allow low > level library's authors a possibility to be extremely fast? > > https://codereview.appspot.**com/12876047/<https://codereview.appspot.com/128... >
Sign in to reply to this message.
Brad, Dmitry I've separate EmbedTimer from Timer, so that new methods do not pollute Timer's api. Also I give up on running callback in timer's goroutine. While it could be useful, I'm still not sure it is critical for me. On 2013/08/23 21:40:46, bradfitz wrote: > Yuri, > > We do want things to be very fast, but we also want clean, simple APIs. > It's a balance. > > If you can think of a simple API that can also be made fast and with less > garbage, then that is interesting. > > http://golang.org/pkg/time/#Timer.Reset was added in Go 1.1 (largely for > performance reasons). It's possible that new additions can be added, but > only if they're useful and understandable too. >
Sign in to reply to this message.
On 2013/8/24 <funny.falcon@gmail.com> wrote: > Brad, Dmitry > > I've separate EmbedTimer from Timer, so that new methods do not pollute > Timer's api. > > Also I give up on running callback in timer's goroutine. While it could > be useful, I'm still not sure it is critical for me. I don't understand why this is useful when we can reuse Timers. Rémy.
Sign in to reply to this message.
Hi, I agree with others that such a low-level interface is not a good thing. As for memory allocation, I think you should pool timers along with request structs; so when you obtain the request struct you already have the timer. Regarding running user callbacks in timer goroutine, this is no-no. First, it's just too easy to screw up. Then, eventually it will run outside of goroutine context as part of the scheduler; so it can't potentially run arbitrary Go code. There are also some things that can be done in runtime to make timers faster, I've filed https://code.google.com/p/go/issues/detail?id=6239 for this. I don't know your architecture, but there is one potential solution that can give you necessary performance today. You can have a single low frequency ticker (say, once per 10 minutes), when it fires check all requests and cancel very old ones.
Sign in to reply to this message.
On 2013/08/23 21:33:30, funny.falcon wrote: > On 2013/08/23 20:28:59, remyoudompheng wrote: > > https://codereview.appspot.com/12876047/diff/10001/src/pkg/time/sleep.go > > File src/pkg/time/sleep.go (right): > > > > > https://codereview.appspot.com/12876047/diff/10001/src/pkg/time/sleep.go#newc... > > src/pkg/time/sleep.go:137: // SetupExpire initialize already allocated timer > to > > call e.Expire() after elapsed duration. > > An API that says "don't use me I am very dangerous and you may only use me in > > very specific cases when you are very careful" seems out-of-place in a very > > user-public package like time. > > > > Currently only runtime and syscall packages take the liberty of being > dangerous. > > But why? If user is informed about dangers, why not give him ability to be fast? > > Our team is about to switch platform. I propose go. Alternative is > C+libev+LuaJIT. > I'm writting relatively lowlevel library for fast asynchronous network protocol. > One of primary condition: every single request should have expiration timer. > Within benchmark, there is over 500 000 rps. > Without timers I could easely beat alternative solution, but it already have > timers provided by libev, and thowe timers are cheap, cause they are embed. > With proposed change I could contest with alternative. But Timer ought to be > allocated (and func() trampoline), then I much slower simply cause of allocation > and GC. > > OK, may be running Expire() within internal goroutine is nof critical for my > case, cause timer likely to be stopped before expiration in 99.9%. But why not > allow low > level library's authors a possibility to be extremely fast? I understand your situation. But it's not a reason to introduce APIs that must not be there otherwise. Especially just before release.
Sign in to reply to this message.
On 2013/08/24 07:10:44, remyoudompheng wrote: > On 2013/8/24 <mailto:funny.falcon@gmail.com> wrote: > > Brad, Dmitry > > > > I've separate EmbedTimer from Timer, so that new methods do not pollute > > Timer's api. > > > > Also I give up on running callback in timer's goroutine. While it could > > be useful, I'm still not sure it is critical for me. > > I don't understand why this is useful when we can reuse Timers. > > Rémy. I could not reuse timer, cause its callback is request's method. One solution is to fully replicate timer's heap in pure Go, but it is strange to have custom timers when runtime already have timers.
Sign in to reply to this message.
On 2013/08/24 10:45:57, dvyukov wrote: > Hi, > > I agree with others that such a low-level interface is not a good thing. > As for memory allocation, I think you should pool timers along with request > structs; so when you obtain the request struct you already have the timer. > Regarding running user callbacks in timer goroutine, this is no-no. First, it's > just too easy to screw up. Then, eventually it will run outside of goroutine > context as part of the scheduler; so it can't potentially run arbitrary Go code. > > There are also some things that can be done in runtime to make timers faster, > I've filed https://code.google.com/p/go/issues/detail?id=6239 for this. > > I don't know your architecture, but there is one potential solution that can > give you necessary performance today. You can have a single low frequency ticker > (say, once per 10 minutes), when it fires check all requests and cancel very old > ones. Request lasts for 100 milliseconds at max. And I'm not able to reuse request structure due to multithreading issues (ie GOMAXPROCS>1). I allocate request structure by 8 at once, but there is no way to allocate 8 timers.
Sign in to reply to this message.
On 2013/08/24 11:22:25, funny.falcon wrote: > On 2013/08/24 10:45:57, dvyukov wrote: > > Hi, > > > > I agree with others that such a low-level interface is not a good thing. > > As for memory allocation, I think you should pool timers along with request > > structs; so when you obtain the request struct you already have the timer. > > Regarding running user callbacks in timer goroutine, this is no-no. First, > it's > > just too easy to screw up. Then, eventually it will run outside of goroutine > > context as part of the scheduler; so it can't potentially run arbitrary Go > code. > > > > There are also some things that can be done in runtime to make timers faster, > > I've filed https://code.google.com/p/go/issues/detail?id=6239 for this. > > > > I don't know your architecture, but there is one potential solution that can > > give you necessary performance today. You can have a single low frequency > ticker > > (say, once per 10 minutes), when it fires check all requests and cancel very > old > > ones. > > Request lasts for 100 milliseconds at max. And I'm not able to reuse request > structure due to multithreading issues (ie GOMAXPROCS>1). I allocate request > structure by 8 at once, but there is no way to allocate 8 timers. I am sure you can reuse timer even if its callback is tied to request, if you reuse requests as well. In short, you need to be ready to cope with stale timeouts from old requests. Here is a simplified sketch: http://play.golang.org/p/HVilcEF0qt This code uses single-threaded pool. But since you say that you allocate requests in batches of 8, I assume that you can implement the pool as follows. Global mutex-protected pool of batches of requests, on top of it goroutine local cache that gets and returns batches to the global pool.
Sign in to reply to this message.
On 2013/08/24 12:04:07, dvyukov wrote: > On 2013/08/24 11:22:25, funny.falcon wrote: > > On 2013/08/24 10:45:57, dvyukov wrote: > > > Hi, > > > > > > I agree with others that such a low-level interface is not a good thing. > > > As for memory allocation, I think you should pool timers along with request > > > structs; so when you obtain the request struct you already have the timer. > > > Regarding running user callbacks in timer goroutine, this is no-no. First, > > it's > > > just too easy to screw up. Then, eventually it will run outside of goroutine > > > context as part of the scheduler; so it can't potentially run arbitrary Go > > code. > > > > > > There are also some things that can be done in runtime to make timers > faster, > > > I've filed https://code.google.com/p/go/issues/detail?id=6239 for this. > > > > > > I don't know your architecture, but there is one potential solution that can > > > give you necessary performance today. You can have a single low frequency > > ticker > > > (say, once per 10 minutes), when it fires check all requests and cancel very > > old > > > ones. > > > > Request lasts for 100 milliseconds at max. And I'm not able to reuse request > > structure due to multithreading issues (ie GOMAXPROCS>1). I allocate request > > structure by 8 at once, but there is no way to allocate 8 timers. > > > I am sure you can reuse timer even if its callback is tied to request, if you > reuse requests as well. In short, you need to be ready to cope with stale > timeouts from old requests. Here is a simplified sketch: > http://play.golang.org/p/HVilcEF0qt > > This code uses single-threaded pool. But since you say that you allocate > requests in batches of 8, I assume that you can implement the pool as follows. > Global mutex-protected pool of batches of requests, on top of it goroutine local > cache that gets and returns batches to the global pool. In multithreaded environment there is a single point in time, when we could return request into pool: when garbage collector sees no references to it. Are finalizators so cheap?
Sign in to reply to this message.
On Sat, Aug 24, 2013 at 7:33 PM, <funny.falcon@gmail.com> wrote: > On 2013/08/24 12:04:07, dvyukov wrote: >> >> On 2013/08/24 11:22:25, funny.falcon wrote: >> > On 2013/08/24 10:45:57, dvyukov wrote: >> > > Hi, >> > > >> > > I agree with others that such a low-level interface is not a good > > thing. >> >> > > As for memory allocation, I think you should pool timers along > > with request >> >> > > structs; so when you obtain the request struct you already have > > the timer. >> >> > > Regarding running user callbacks in timer goroutine, this is > > no-no. First, >> >> > it's >> > > just too easy to screw up. Then, eventually it will run outside of > > goroutine >> >> > > context as part of the scheduler; so it can't potentially run > > arbitrary Go >> >> > code. >> > > >> > > There are also some things that can be done in runtime to make > > timers >> >> faster, >> > > I've filed https://code.google.com/p/go/issues/detail?id=6239 for > > this. >> >> > > >> > > I don't know your architecture, but there is one potential > > solution that can >> >> > > give you necessary performance today. You can have a single low > > frequency >> >> > ticker >> > > (say, once per 10 minutes), when it fires check all requests and > > cancel very >> >> > old >> > > ones. >> > >> > Request lasts for 100 milliseconds at max. And I'm not able to reuse > > request >> >> > structure due to multithreading issues (ie GOMAXPROCS>1). I allocate > > request >> >> > structure by 8 at once, but there is no way to allocate 8 timers. > > > >> I am sure you can reuse timer even if its callback is tied to request, > > if you >> >> reuse requests as well. In short, you need to be ready to cope with > > stale >> >> timeouts from old requests. Here is a simplified sketch: >> http://play.golang.org/p/HVilcEF0qt > > >> This code uses single-threaded pool. But since you say that you > > allocate >> >> requests in batches of 8, I assume that you can implement the pool as > > follows. >> >> Global mutex-protected pool of batches of requests, on top of it > > goroutine local >> >> cache that gets and returns batches to the global pool. > > > In multithreaded environment there is a single point in time, when we > could return request into pool: when garbage collector sees no > references to it. Are finalizators so cheap? Well, I can imagine that it may be difficult to control request lifetime in a concurrent system. So, this patch only removes memory allocation of timers. What do you see in the profile? Is it actually memory allocation that consumes most of the time? How much faster is your program with this patch? Memory allocator and GC also must be made faster. I've started some work for Go1.2. But GC is in significant flux, so I had to delay it.
Sign in to reply to this message.
On 2013/08/24 15:55:17, dvyukov wrote: > On Sat, Aug 24, 2013 at 7:33 PM, <mailto:funny.falcon@gmail.com> wrote: > > On 2013/08/24 12:04:07, dvyukov wrote: > >> > >> On 2013/08/24 11:22:25, funny.falcon wrote: > >> > On 2013/08/24 10:45:57, dvyukov wrote: > >> > > Hi, > >> > > > >> > > I agree with others that such a low-level interface is not a good > > > > thing. > >> > >> > > As for memory allocation, I think you should pool timers along > > > > with request > >> > >> > > structs; so when you obtain the request struct you already have > > > > the timer. > >> > >> > > Regarding running user callbacks in timer goroutine, this is > > > > no-no. First, > >> > >> > it's > >> > > just too easy to screw up. Then, eventually it will run outside of > > > > goroutine > >> > >> > > context as part of the scheduler; so it can't potentially run > > > > arbitrary Go > >> > >> > code. > >> > > > >> > > There are also some things that can be done in runtime to make > > > > timers > >> > >> faster, > >> > > I've filed https://code.google.com/p/go/issues/detail?id=6239 for > > > > this. > >> > >> > > > >> > > I don't know your architecture, but there is one potential > > > > solution that can > >> > >> > > give you necessary performance today. You can have a single low > > > > frequency > >> > >> > ticker > >> > > (say, once per 10 minutes), when it fires check all requests and > > > > cancel very > >> > >> > old > >> > > ones. > >> > > >> > Request lasts for 100 milliseconds at max. And I'm not able to reuse > > > > request > >> > >> > structure due to multithreading issues (ie GOMAXPROCS>1). I allocate > > > > request > >> > >> > structure by 8 at once, but there is no way to allocate 8 timers. > > > > > > > >> I am sure you can reuse timer even if its callback is tied to request, > > > > if you > >> > >> reuse requests as well. In short, you need to be ready to cope with > > > > stale > >> > >> timeouts from old requests. Here is a simplified sketch: > >> http://play.golang.org/p/HVilcEF0qt > > > > > >> This code uses single-threaded pool. But since you say that you > > > > allocate > >> > >> requests in batches of 8, I assume that you can implement the pool as > > > > follows. > >> > >> Global mutex-protected pool of batches of requests, on top of it > > > > goroutine local > >> > >> cache that gets and returns batches to the global pool. > > > > > > In multithreaded environment there is a single point in time, when we > > could return request into pool: when garbage collector sees no > > references to it. Are finalizators so cheap? > > > Well, I can imagine that it may be difficult to control request > lifetime in a concurrent system. > > So, this patch only removes memory allocation of timers. What do you > see in the profile? Is it actually memory allocation that consumes > most of the time? How much faster is your program with this patch? > > Memory allocator and GC also must be made faster. I've started some > work for Go1.2. But GC is in significant flux, so I had to delay it. I give up, and settle with custom timers.
Sign in to reply to this message.
NOT LGTM Too much new API. Timers can already be reused.
Sign in to reply to this message.
On 2013/09/03 21:34:38, rsc wrote: > NOT LGTM > > Too much new API. Timers can already be reused. But callback could not be changed.
Sign in to reply to this message.
Sign in to reply to this message.
Russ, Now 100_000 of them per second? How much presure on GC it will cause? Inplace allocation (ie timer inside other struct) with interface callback needs no allocations. Your example allocates 3 closures and a timer itself. 2013/9/5 Russ Cox <rsc@golang.org> > http://play.golang.org/p/Jw3YEDMY6d > >
Sign in to reply to this message.
On Thu, Sep 5, 2013 at 5:46 PM, Юрий Соколов <funny.falcon@gmail.com> wrote: > Russ, > > Now 100_000 of them per second? How much presure on GC it will cause? > Inplace allocation (ie timer inside other struct) with interface callback > needs no allocations. Your example allocates 3 closures and a timer itself. > i was demonstrating that it is possible to reuse a timer. that would mean you don't need to create 100,000 of them per second. russ
Sign in to reply to this message.
Then, I need to create 100_000 of closures per sec? Ah, callback could call interface, stored in an array along with pointer to timer, and list of free timers could be managed. And bash is a Turing complete language. Thanks. 06.09.2013 3:08 пользователь "Russ Cox" <rsc@golang.org> написал: > On Thu, Sep 5, 2013 at 5:46 PM, Юрий Соколов <funny.falcon@gmail.com>wrote: > >> Russ, >> >> Now 100_000 of them per second? How much presure on GC it will cause? >> Inplace allocation (ie timer inside other struct) with interface callback >> needs no allocations. Your example allocates 3 closures and a timer itself. >> > > i was demonstrating that it is possible to reuse a timer. that would mean > you don't need to create 100,000 of them per second. > > russ >
Sign in to reply to this message.
On 2013/9/6 Юрий Соколов <funny.falcon@gmail.com> wrote: > Then, I need to create 100_000 of closures per sec? Ah, callback could call > interface, stored in an array along with pointer to timer, and list of free > timers could be managed. And bash is a Turing complete language. Thanks. I'm not sure why you want to optimize that at all. Rémy.
Sign in to reply to this message.
That's pretty much what I showed here: http://play.golang.org/p/HVilcEF0qt You have a pair of (timer, chan), timer always sends to the chan, chan is reused along with the timer. On Fri, Sep 6, 2013 at 10:47 AM, Юрий Соколов <funny.falcon@gmail.com> wrote: > Then, I need to create 100_000 of closures per sec? Ah, callback could call > interface, stored in an array along with pointer to timer, and list of free > timers could be managed. And bash is a Turing complete language. Thanks. > > 06.09.2013 3:08 пользователь "Russ Cox" <rsc@golang.org> написал: > >> On Thu, Sep 5, 2013 at 5:46 PM, Юрий Соколов <funny.falcon@gmail.com> >> wrote: >>> >>> Russ, >>> >>> Now 100_000 of them per second? How much presure on GC it will cause? >>> Inplace allocation (ie timer inside other struct) with interface callback >>> needs no allocations. Your example allocates 3 closures and a timer itself. >> >> >> i was demonstrating that it is possible to reuse a timer. that would mean >> you don't need to create 100,000 of them per second. >> >> russ
Sign in to reply to this message.
Note that Russ' code needs additional synchronization, as-is it contains a data race on f. On Fri, Sep 6, 2013 at 12:14 PM, Dmitry Vyukov <dvyukov@google.com> wrote: > That's pretty much what I showed here: > http://play.golang.org/p/HVilcEF0qt > > You have a pair of (timer, chan), timer always sends to the chan, chan > is reused along with the timer. > > > On Fri, Sep 6, 2013 at 10:47 AM, Юрий Соколов <funny.falcon@gmail.com> wrote: >> Then, I need to create 100_000 of closures per sec? Ah, callback could call >> interface, stored in an array along with pointer to timer, and list of free >> timers could be managed. And bash is a Turing complete language. Thanks. >> >> 06.09.2013 3:08 пользователь "Russ Cox" <rsc@golang.org> написал: >> >>> On Thu, Sep 5, 2013 at 5:46 PM, Юрий Соколов <funny.falcon@gmail.com> >>> wrote: >>>> >>>> Russ, >>>> >>>> Now 100_000 of them per second? How much presure on GC it will cause? >>>> Inplace allocation (ie timer inside other struct) with interface callback >>>> needs no allocations. Your example allocates 3 closures and a timer itself. >>> >>> >>> i was demonstrating that it is possible to reuse a timer. that would mean >>> you don't need to create 100,000 of them per second. >>> >>> russ
Sign in to reply to this message.
Dmitry, your code needs synchronization as well, cause this is not safe in case GOMAXPROCS > 1 func NewReq(timeout time.Duration) *Req { r := reqPool if r != nil { reqPool = r.next r.id = reqSet func DoneReq(r *Req) { r.next = reqPool reqPool = r } More over: this way user ought to call DoneReq and not touch request after calling it - this smells as C :( And this is all completely unnecessary, if timer could be embedded into request, and callback set as an interface. 2013/9/6 Dmitry Vyukov <dvyukov@google.com> > Note that Russ' code needs additional synchronization, as-is it > contains a data race on f. > > > On Fri, Sep 6, 2013 at 12:14 PM, Dmitry Vyukov <dvyukov@google.com> wrote: > > That's pretty much what I showed here: > > http://play.golang.org/p/HVilcEF0qt > > > > You have a pair of (timer, chan), timer always sends to the chan, chan > > is reused along with the timer. > > > > > > On Fri, Sep 6, 2013 at 10:47 AM, Юрий Соколов <funny.falcon@gmail.com> > wrote: > >> Then, I need to create 100_000 of closures per sec? Ah, callback could > call > >> interface, stored in an array along with pointer to timer, and list of > free > >> timers could be managed. And bash is a Turing complete language. Thanks. > >> > >> 06.09.2013 3:08 пользователь "Russ Cox" <rsc@golang.org> написал: > >> > >>> On Thu, Sep 5, 2013 at 5:46 PM, Юрий Соколов <funny.falcon@gmail.com> > >>> wrote: > >>>> > >>>> Russ, > >>>> > >>>> Now 100_000 of them per second? How much presure on GC it will cause? > >>>> Inplace allocation (ie timer inside other struct) with interface > callback > >>>> needs no allocations. Your example allocates 3 closures and a timer > itself. > >>> > >>> > >>> i was demonstrating that it is possible to reuse a timer. that would > mean > >>> you don't need to create 100,000 of them per second. > >>> > >>> russ >
Sign in to reply to this message.
Replacing golang-dev with golang-codereviews.
Sign in to reply to this message.
|