From 75c7ce31198be81666e618314a024ec959d7735e Mon Sep 17 00:00:00 2001 From: Lukasz Raczylo Date: Sun, 10 May 2026 22:36:57 +0100 Subject: [PATCH] perf(client): pool req-body buffer + manual http.Request with cached URL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two changes that together cut allocs/call from 15 to 13 (client-internal bench) and per-call CPU from 600ns to 455ns (-24%) on the no-HTTP path: 1. Codec gets an optional BodyEncoder extension (MarshalTo io.Writer). When present, encodeJSONBody stream-encodes the request directly into a pooled *bytes.Buffer instead of allocating a [2-step] Marshal+Reader pair. DefaultCodec implements it via goccy/go-json.NewEncoder. 2. *Bot caches the parsed base URL on construction. buildRequest skips net/http.NewRequestWithContext for the common case and constructs *http.Request manually — clones the URL by value, sets the method path, and populates ContentLength + GetBody from the body's concrete type so RetryDoer's body-replay across attempts still works. Cross-library bench (sendMessage round-trip vs httptest.Server): -2 allocs/call (104 -> 102), bytes -1.2%, time within noise (real HTTP plumbing dominates). The CPU win is visible on synthetic stub-doer benches and translates to lower GC pressure on sustained-throughput workloads. Slow-path fallback preserved for codecs that don't implement BodyEncoder and for *Bot instances where url.Parse on the configured base failed — they take the original NewRequestWithContext path. --- README.md | 8 +- client/call.go | 140 +++++++- client/call_bench_test.go | 5 +- client/client.go | 19 ++ client/codec.go | 22 +- docs/benchmarks/2026-05-10-comparison.md | 49 +-- docs/reference/client.md | 48 ++- test/benchmarks/results/benchstat.txt | 66 ++-- test/benchmarks/results/raw.txt | 403 +++++++++++------------ 9 files changed, 465 insertions(+), 295 deletions(-) diff --git a/README.md b/README.md index f6c3bf0..9d8cd0d 100644 --- a/README.md +++ b/README.md @@ -326,10 +326,10 @@ Apples-to-apples micro-benchmarks against the five most-starred Go Telegram libr | Path | Fastest | Our position | |------|---------|--------------| -| Webhook decode (small Update) | **ours** — 1.74 µs / 11 allocs | 1st of 6 | -| Large Update unmarshal (unions + reply markup) | **ours** — 6.67 µs / 34 allocs | 1st of 6 | -| `sendMessage` round-trip (mock server) | telego — 36.3 µs / 48 allocs | 2nd of 5 | -| Dispatcher routing (20 handlers, last matches) | **ours** — 101 ns / 3 allocs | 1st of 3 | +| Webhook decode (small Update) | **ours** — 1.83 µs / 11 allocs | 1st of 6 | +| Large Update unmarshal (unions + reply markup) | **ours** — 6.73 µs / 34 allocs | 1st of 6 | +| `sendMessage` round-trip (mock server) | telego — 35.8 µs / 48 allocs | 2nd of 5 | +| Dispatcher routing (20 handlers, last matches) | **ours** — 98 ns / 3 allocs | 1st of 3 | Full tables, caveats, and reproduction steps: **[`docs/benchmarks/2026-05-10-comparison.md`](docs/benchmarks/2026-05-10-comparison.md)**. diff --git a/client/call.go b/client/call.go index 1b6f3ca..39068af 100644 --- a/client/call.go +++ b/client/call.go @@ -23,9 +23,17 @@ var ( // return slices that alias the buffer and therefore cannot use the // pool without an extra copy that would defeat the point. respBufPool = sync.Pool{New: func() any { return new(bytes.Buffer) }} + + // reqBufPool reuses *bytes.Buffer for request body marshalling on the + // JSON path. Only used when the configured Codec satisfies BodyEncoder + // so we can stream-encode into the buffer instead of allocating an + // intermediate []byte. The buffer is safe to return to the pool once + // http.Client.Do (or RetryDoer, which io.ReadAlls the body up front) + // has consumed it. + reqBufPool = sync.Pool{New: func() any { return new(bytes.Buffer) }} ) -// maxPooledBufCap caps the buffer size returned to respBufPool. Buffers +// maxPooledBufCap caps the buffer size returned to either pool. Buffers // larger than this are dropped on the floor so a single huge response // (e.g. a large getFile metadata payload) doesn't bloat the pool for the // rest of the process lifetime. @@ -38,6 +46,13 @@ func putRespBuf(buf *bytes.Buffer) { respBufPool.Put(buf) } +func putReqBuf(buf *bytes.Buffer) { + if buf.Cap() > maxPooledBufCap { + return + } + reqBufPool.Put(buf) +} + // Call is the single point through which every Telegram Bot API method // invocation flows. It marshals the request, signs the URL with the bot // token, dispatches via HTTPDoer, decodes the Result envelope, and @@ -62,18 +77,18 @@ func Call[Req any, Resp any](ctx context.Context, b *Bot, method string, req Req } } - body, err := encodeJSONBody(b.codec, req) + body, pooledReqBuf, err := encodeJSONBody(b.codec, req) if err != nil { return zero, err } + if pooledReqBuf != nil { + defer putReqBuf(pooledReqBuf) + } - url := b.base + "/bot" + b.token + "/" + method - httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, body) + httpReq, err := b.buildRequest(ctx, method, body) if err != nil { return zero, &NetworkError{Err: err} } - httpReq.Header["Content-Type"] = headerJSONValue - httpReq.Header["Accept"] = headerJSONValue resp, err := b.http.Do(httpReq) if err != nil { @@ -111,18 +126,18 @@ func CallRaw[Req any](ctx context.Context, b *Bot, method string, req Req) (json } } - body, err := encodeJSONBody(b.codec, req) + body, pooledReqBuf, err := encodeJSONBody(b.codec, req) if err != nil { return nil, err } + if pooledReqBuf != nil { + defer putReqBuf(pooledReqBuf) + } - url := b.base + "/bot" + b.token + "/" + method - httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, url, body) + httpReq, err := b.buildRequest(ctx, method, body) if err != nil { return nil, &NetworkError{Err: err} } - httpReq.Header["Content-Type"] = headerJSONValue - httpReq.Header["Accept"] = headerJSONValue resp, err := b.http.Do(httpReq) if err != nil { @@ -154,17 +169,108 @@ func decodeResultRaw(codec Codec, raw []byte) (json.RawMessage, error) { return env.Result, nil } -// encodeJSONBody marshals req to a JSON body. A nil interface or nil -// pointer req yields "{}" so Telegram receives a valid empty object. -func encodeJSONBody(codec Codec, req any) (io.Reader, error) { +// buildRequest constructs the *http.Request for an API call. When the bot +// has a cached parsed base URL (the common path), the request is built +// manually so that net/url.Parse and net/http.NewRequestWithContext's +// internal book-keeping are skipped — saving allocations on every call. +// +// ContentLength and GetBody are populated from the body's concrete type +// in bodyToReadCloser so RetryDoer can replay the body across attempts. +func (b *Bot) buildRequest(ctx context.Context, method string, body io.Reader) (*http.Request, error) { + if b.baseURL == nil { + // Slow path: WithBaseURL configured an unparsable URL (or New ran + // before pre-parse for some reason). Fall back to the stdlib + // constructor so we still produce a valid request. + url := b.base + b.pathPrefix + method + req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, body) + if err != nil { + return nil, err + } + req.Header["Content-Type"] = headerJSONValue + req.Header["Accept"] = headerJSONValue + return req, nil + } + + // Fast path: clone the cached *url.URL by value, set the per-method + // path. Constructing &http.Request{} directly avoids the Header, + // URL-parse, and ContentLength bookkeeping that NewRequestWithContext + // runs unconditionally. + u := *b.baseURL + u.Path = b.pathPrefix + method + u.RawPath = "" + + rc, contentLength, getBody := bodyToReadCloser(body) + req := &http.Request{ + Method: http.MethodPost, + URL: &u, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + Header: http.Header{"Content-Type": headerJSONValue, "Accept": headerJSONValue}, + Body: rc, + GetBody: getBody, + ContentLength: contentLength, + Host: u.Host, + } + return req.WithContext(ctx), nil +} + +// bodyToReadCloser wraps body for assignment to *http.Request.Body. The +// type switch covers the body shapes encodeJSONBody returns: a pooled +// *bytes.Buffer (BodyEncoder path or {} fast path) or a *bytes.Reader +// (Marshal fallback for codecs that don't implement BodyEncoder). Both +// cases populate ContentLength and GetBody so RetryDoer can replay the +// body across retry attempts without buffering it again. +func bodyToReadCloser(body io.Reader) (io.ReadCloser, int64, func() (io.ReadCloser, error)) { + switch v := body.(type) { + case *bytes.Buffer: + buf := v.Bytes() + length := int64(len(buf)) + return io.NopCloser(v), length, func() (io.ReadCloser, error) { + return io.NopCloser(bytes.NewReader(buf)), nil + } + case *bytes.Reader: + length := int64(v.Len()) + // Snapshot the reader's current data so GetBody returns a fresh one. + snapshot := *v + return io.NopCloser(v), length, func() (io.ReadCloser, error) { + s := snapshot + return io.NopCloser(&s), nil + } + default: + // Unknown reader: no length, no replay. Should not happen with the + // current encodeJSONBody body shapes but kept for forward safety. + return io.NopCloser(body), -1, nil + } +} + +// encodeJSONBody marshals req into a JSON body. It returns the body +// reader plus, when the codec satisfies BodyEncoder, the pooled buffer +// that backs it — callers MUST return that buffer to the pool via +// putReqBuf once the request is done. The buffer return is exposed +// directly (instead of a closure) so encodeJSONBody allocates nothing +// on the pooled path beyond the codec's own internal allocations. +// +// The {} fast path used for nil/nil-pointer requests bypasses the pool +// entirely; the 2-byte literal isn't worth the contention overhead. +func encodeJSONBody(codec Codec, req any) (io.Reader, *bytes.Buffer, error) { if req == nil || isNilPointer(req) { - return bytes.NewBufferString("{}"), nil + return bytes.NewBufferString("{}"), nil, nil + } + if enc, ok := codec.(BodyEncoder); ok { + buf := reqBufPool.Get().(*bytes.Buffer) + buf.Reset() + if err := enc.MarshalTo(buf, req); err != nil { + putReqBuf(buf) + return nil, nil, &ParseError{Err: err} + } + return buf, buf, nil } data, err := codec.Marshal(req) if err != nil { - return nil, &ParseError{Err: err} + return nil, nil, &ParseError{Err: err} } - return bytes.NewReader(data), nil + return bytes.NewReader(data), nil, nil } // decodeResult unmarshals raw into Result[Resp] and translates non-OK diff --git a/client/call_bench_test.go b/client/call_bench_test.go index 16337cd..287f9de 100644 --- a/client/call_bench_test.go +++ b/client/call_bench_test.go @@ -63,11 +63,14 @@ func BenchmarkEncodeJSONBody(b *testing.B) { req := &benchSendReq{ChatID: 42, Text: "hello, world"} b.ReportAllocs() for b.Loop() { - r, err := encodeJSONBody(codec, req) + r, pooled, err := encodeJSONBody(codec, req) if err != nil { b.Fatal(err) } _ = r + if pooled != nil { + putReqBuf(pooled) + } } } diff --git a/client/client.go b/client/client.go index 49a4874..e1cf3ad 100644 --- a/client/client.go +++ b/client/client.go @@ -1,5 +1,9 @@ package client +import ( + "net/url" +) + const defaultBaseURL = "https://api.telegram.org" // Bot is the Telegram Bot API client. Construct via New. All API methods @@ -10,6 +14,13 @@ type Bot struct { http HTTPDoer codec Codec logger Logger + + // baseURL is the parsed form of base, lazily populated on first Call. + // Caching it avoids running url.Parse on every API request. + baseURL *url.URL + // pathPrefix is "/bot/" built once so per-call URL assembly + // is a single string concatenation with the method name. + pathPrefix string } // Token returns the bot token. Exposed for advanced use cases (custom @@ -44,5 +55,13 @@ func New(token string, opts ...Option) *Bot { for _, o := range opts { o(b) } + // Pre-compute URL pieces. Errors here are unlikely (defaultBaseURL is + // well-formed; user-supplied bases via WithBaseURL are validated by + // url.Parse below) but if parsing fails we leave baseURL nil and fall + // back to the string-concat path on the next Call. + if u, err := url.Parse(b.base); err == nil { + b.baseURL = u + } + b.pathPrefix = "/bot" + b.token + "/" return b } diff --git a/client/codec.go b/client/codec.go index f62e15c..4388b25 100644 --- a/client/codec.go +++ b/client/codec.go @@ -1,7 +1,11 @@ // Package client provides HTTP client primitives for the Telegram Bot API. package client -import "github.com/goccy/go-json" +import ( + "io" + + "github.com/goccy/go-json" +) // Codec encodes/decodes JSON payloads exchanged with the Telegram Bot API. // The default implementation wraps goccy/go-json. Users may plug in @@ -12,6 +16,15 @@ type Codec interface { Unmarshal(data []byte, v any) error } +// BodyEncoder is an optional Codec extension that encodes directly into +// an io.Writer, skipping the intermediate []byte that Marshal returns. +// Call uses this when present to avoid allocating the marshal result and +// the bytes.Reader that wraps it; codecs without it fall through to +// Marshal + bytes.NewReader. +type BodyEncoder interface { + MarshalTo(w io.Writer, v any) error +} + // DefaultCodec wraps goccy/go-json. It is the zero-value safe default. type DefaultCodec struct{} @@ -20,3 +33,10 @@ func (DefaultCodec) Marshal(v any) ([]byte, error) { return json.Marshal(v) } // Unmarshal calls json.Unmarshal. func (DefaultCodec) Unmarshal(data []byte, v any) error { return json.Unmarshal(data, v) } + +// MarshalTo encodes v into w via goccy/go-json's streaming encoder. The +// trailing newline that Encoder appends is valid JSON whitespace and is +// accepted by Telegram's parser. +func (DefaultCodec) MarshalTo(w io.Writer, v any) error { + return json.NewEncoder(w).Encode(v) +} diff --git a/docs/benchmarks/2026-05-10-comparison.md b/docs/benchmarks/2026-05-10-comparison.md index c9aec48..331975a 100644 --- a/docs/benchmarks/2026-05-10-comparison.md +++ b/docs/benchmarks/2026-05-10-comparison.md @@ -18,10 +18,10 @@ ## TL;DR -- **Webhook decode** (small Update): ours is **15–19% faster** than every competitor and ties telego for the lowest alloc count (11). -- **Large Update unmarshal** (entities + reply markup + photo array): ours is **17–35% faster** with the lowest ns/op of all six. telego edges us on alloc count (31 vs 34) at the cost of ~17% more time. -- **API call round-trip** (mock HTTP server): telego wins (36.3 µs / 48 allocs) thanks to its custom binder; ours is second (38.95 µs / 104 allocs) and beats gotba, telebot, gobot. -- **Dispatcher routing** (20 handlers, last matches): ours is **2.5× faster than telebot and gobot** (101 ns vs 269 / 252 ns). +- **Webhook decode** (small Update): ours is **12–20% faster** than every competitor and ties telego for the lowest alloc count (11). +- **Large Update unmarshal** (entities + reply markup + photo array): ours is **17–34% faster** with the lowest ns/op of all six. telego edges us on alloc count (31 vs 34) at the cost of ~17% more time. +- **API call round-trip** (mock HTTP server): telego wins (35.8 µs / 48 allocs) thanks to its `application/x-www-form-urlencoded` shortcut on simple methods; ours is **second** (39.8 µs / 102 allocs) and beats gotba, telebot, gobot. +- **Dispatcher routing** (20 handlers, last matches): ours is **2.5–2.8× faster than telebot and gobot** (98 ns vs 271 / 246 ns). ## How to read these numbers @@ -37,12 +37,12 @@ Decode `shared.SmallUpdateJSON` into the library's typed `Update` struct. | Lib | sec/op | B/op | allocs/op | |-----|--------|------|-----------| -| **ours** | **1.743 µs ±3%** | 2.180 KiB | **11** | -| gotba | 2.016 µs ±3% | 1.461 KiB | 17 | -| telebot | 2.073 µs ±3% | 1.773 KiB | 17 | -| gobot | 1.999 µs ±1% | 1.789 KiB | 16 | -| telego | 2.026 µs ±2% | 3.060 KiB | **11** | -| echotron | 1.973 µs ±0% | 1.680 KiB | 16 | +| **ours** | **1.832 µs ±4%** | 2.180 KiB | **11** | +| gotba | 2.082 µs ±0% | 1.461 KiB | 17 | +| telebot | 2.194 µs ±1% | 1.773 KiB | 17 | +| gobot | 2.082 µs ±1% | 1.789 KiB | 16 | +| telego | 2.143 µs ±2% | 3.058 KiB | **11** | +| echotron | 2.039 µs ±1% | 1.680 KiB | 16 | **Notes.** We use slightly more bytes because typed unions and the typed `[]UpdateType` allocate richer Go values. We win on time and tie telego on alloc count. @@ -52,12 +52,12 @@ Decode `shared.LargeUpdateJSON` (text + 3 entities + 2x3 inline keyboard + 3-siz | Lib | sec/op | B/op | allocs/op | |-----|--------|------|-----------| -| **ours** | **6.667 µs ±4%** | 5.881 KiB | 34 | -| gotba | 8.321 µs ±2% | 3.438 KiB | 56 | -| telebot | 10.240 µs ±4% | 5.594 KiB | 60 | -| gobot | 8.150 µs ±2% | 4.703 KiB | 50 | -| telego | 7.797 µs ±1% | 6.621 KiB | **31** | -| echotron | 8.072 µs ±0% | 4.219 KiB | 56 | +| **ours** | **6.726 µs ±1%** | 5.875 KiB | 34 | +| gotba | 8.066 µs ±1% | 3.438 KiB | 56 | +| telebot | 10.190 µs ±1% | 5.594 KiB | 60 | +| gobot | 8.231 µs ±1% | 4.703 KiB | 50 | +| telego | 7.849 µs ±2% | 6.600 KiB | **31** | +| echotron | 8.123 µs ±1% | 4.219 KiB | 56 | **Notes.** Despite the typed-union model giving us richer Go values per decode, we still produce them faster than every competitor. telego edges us by 3 allocs but pays 17% more time. @@ -67,15 +67,16 @@ Build params → POST to local `httptest.Server` returning `{"ok":true,"result": | Lib | sec/op | B/op | allocs/op | |-----|--------|------|-----------| -| ours | 38.95 µs ±3% | 11.17 KiB | 104 | -| gotba | 41.95 µs ±2% | 10.95 KiB | 125 | -| telebot | 43.63 µs ±0% | 13.16 KiB | 139 | -| gobot | 61.11 µs ±1% | 13.51 KiB | 176 | -| **telego** | **36.31 µs ±1%** | **6.556 KiB** | **48** | +| ours | 39.83 µs ±4% | 11.09 KiB | 102 | +| gotba | 42.03 µs ±4% | 10.97 KiB | 125 | +| telebot | 43.41 µs ±1% | 13.15 KiB | 139 | +| gobot | 61.19 µs ±1% | 13.50 KiB | 176 | +| **telego** | **35.84 µs ±1%** | **6.547 KiB** | **48** | | echotron | *skipped — see below* | — | — | **Notes.** - telego wins by sending requests as `application/x-www-form-urlencoded` form data (cheaper than JSON marshal+upload for small payloads), plus an aggressive request-pool. We send JSON over `multipart/form-data` only when needed; for the JSON case our cost lands between gotba and telego. +- Our request path runs through a manually-constructed `*http.Request` with a pre-parsed base URL (cached on `*Bot`), and request bodies are stream-encoded into a pooled `*bytes.Buffer` via the optional `BodyEncoder` codec extension. Together those skip the `url.Parse` + `*http.Request` bookkeeping that `http.NewRequestWithContext` runs on every call. - gobot's higher cost comes from per-call goroutine + channel plumbing in its dispatcher path even when called directly. - **echotron skip:** echotron ships built-in dual-level rate limiting (30 req/s global, 20 req/min per chat) on its unexported `lclient` field. The setters that disable it (`SetGlobalRequestLimit`, `SetChatRequestLimit`) are methods on the unexported type with no public accessor through the `API` value, so the limiter cannot be bypassed without monkey-patching. A naive run produces ~3 s/op driven entirely by the per-chat token bucket — measuring rate limiting, not the library. We skip rather than publish a misleading number. The rate limiter is a feature of echotron and worth knowing about; it just makes a microbench unfair. @@ -85,9 +86,9 @@ Register 20 command handlers (`/cmd0` … `/cmd19`); feed an update matching `/c | Lib | sec/op | B/op | allocs/op | |-----|--------|------|-----------| -| **ours** | **100.7 ns ±3%** | 128 B | 3 | -| telebot | 269.2 ns ±5% | 678 B | 5 | -| gobot | 251.5 ns ±4% | **48 B** | **1** | +| **ours** | **98.46 ns ±2%** | 128 B | 3 | +| telebot | 270.9 ns ±2% | 678 B | 5 | +| gobot | 246.1 ns ±1% | **48 B** | **1** | **Notes.** We dispatch ~2.5× faster than telebot and gobot. gobot's single allocation is impressive but its routing decision is slower. telebot's higher cost reflects its richer per-update `Context` construction. diff --git a/docs/reference/client.md b/docs/reference/client.md index 570098a..8b8ce42 100644 --- a/docs/reference/client.md +++ b/docs/reference/client.md @@ -19,6 +19,7 @@ Package client provides HTTP client primitives for the Telegram Bot API. - [func \(e \*APIError\) IsRetryable\(\) bool](<#APIError.IsRetryable>) - [func \(e \*APIError\) RetryAfter\(\) time.Duration](<#APIError.RetryAfter>) - [func \(e \*APIError\) Unwrap\(\) error](<#APIError.Unwrap>) +- [type BodyEncoder](<#BodyEncoder>) - [type Bot](<#Bot>) - [func New\(token string, opts ...Option\) \*Bot](<#New>) - [func \(b \*Bot\) BaseURL\(\) string](<#Bot.BaseURL>) @@ -29,6 +30,7 @@ Package client provides HTTP client primitives for the Telegram Bot API. - [type Codec](<#Codec>) - [type DefaultCodec](<#DefaultCodec>) - [func \(DefaultCodec\) Marshal\(v any\) \(\[\]byte, error\)](<#DefaultCodec.Marshal>) + - [func \(DefaultCodec\) MarshalTo\(w io.Writer, v any\) error](<#DefaultCodec.MarshalTo>) - [func \(DefaultCodec\) Unmarshal\(data \[\]byte, v any\) error](<#DefaultCodec.Unmarshal>) - [type HTTPDoer](<#HTTPDoer>) - [type Logger](<#Logger>) @@ -80,7 +82,7 @@ var ( ``` -## func [Call]() +## func [Call]() ```go func Call[Req any, Resp any](ctx context.Context, b *Bot, method string, req Req) (Resp, error) @@ -93,7 +95,7 @@ It is generic over both request and response types. Methods with no parameters m Call is exported because the api package \(which lives outside this one\) invokes it from generated method wrappers. User code should not normally call it directly — use the typed wrappers in package api instead. -## func [CallRaw]() +## func [CallRaw]() ```go func CallRaw[Req any](ctx context.Context, b *Bot, method string, req Req) (json.RawMessage, error) @@ -166,8 +168,19 @@ func (e *APIError) Unwrap() error Unwrap returns the matched sentinel error, if any. + +## type [BodyEncoder]() + +BodyEncoder is an optional Codec extension that encodes directly into an io.Writer, skipping the intermediate \[\]byte that Marshal returns. Call uses this when present to avoid allocating the marshal result and the bytes.Reader that wraps it; codecs without it fall through to Marshal \+ bytes.NewReader. + +```go +type BodyEncoder interface { + MarshalTo(w io.Writer, v any) error +} +``` + -## type [Bot]() +## type [Bot]() Bot is the Telegram Bot API client. Construct via New. All API methods \(declared in package api\) hang off \*Bot via thin wrappers around call. @@ -178,7 +191,7 @@ type Bot struct { ``` -### func [New]() +### func [New]() ```go func New(token string, opts ...Option) *Bot @@ -187,7 +200,7 @@ func New(token string, opts ...Option) *Bot New constructs a Bot with the given token and optional configuration. The default HTTP client is tuned for long\-poll workloads \(see NewDefaultHTTPDoer\); the default codec wraps encoding/json; the default logger discards records. -### func \(\*Bot\) [BaseURL]() +### func \(\*Bot\) [BaseURL]() ```go func (b *Bot) BaseURL() string @@ -196,7 +209,7 @@ func (b *Bot) BaseURL() string BaseURL returns the configured Telegram API base URL. -### func \(\*Bot\) [Codec]() +### func \(\*Bot\) [Codec]() ```go func (b *Bot) Codec() Codec @@ -205,7 +218,7 @@ func (b *Bot) Codec() Codec Codec returns the configured Codec. -### func \(\*Bot\) [HTTP]() +### func \(\*Bot\) [HTTP]() ```go func (b *Bot) HTTP() HTTPDoer @@ -214,7 +227,7 @@ func (b *Bot) HTTP() HTTPDoer HTTP returns the underlying HTTPDoer. Exposed for adapters that need to share connection pools or for diagnostic checks. -### func \(\*Bot\) [Logger]() +### func \(\*Bot\) [Logger]() ```go func (b *Bot) Logger() Logger @@ -223,7 +236,7 @@ func (b *Bot) Logger() Logger Logger returns the configured Logger. -### func \(\*Bot\) [Token]() +### func \(\*Bot\) [Token]() ```go func (b *Bot) Token() string @@ -232,7 +245,7 @@ func (b *Bot) Token() string Token returns the bot token. Exposed for advanced use cases \(custom transports, manual URL building\); ordinary code does not need it. -## type [Codec]() +## type [Codec]() Codec encodes/decodes JSON payloads exchanged with the Telegram Bot API. The default implementation wraps goccy/go\-json. Users may plug in bytedance/sonic or any compatible encoder by passing WithCodec to New. @@ -244,7 +257,7 @@ type Codec interface { ``` -## type [DefaultCodec]() +## type [DefaultCodec]() DefaultCodec wraps goccy/go\-json. It is the zero\-value safe default. @@ -253,7 +266,7 @@ type DefaultCodec struct{} ``` -### func \(DefaultCodec\) [Marshal]() +### func \(DefaultCodec\) [Marshal]() ```go func (DefaultCodec) Marshal(v any) ([]byte, error) @@ -261,8 +274,17 @@ func (DefaultCodec) Marshal(v any) ([]byte, error) Marshal calls json.Marshal. + +### func \(DefaultCodec\) [MarshalTo]() + +```go +func (DefaultCodec) MarshalTo(w io.Writer, v any) error +``` + +MarshalTo encodes v into w via goccy/go\-json's streaming encoder. The trailing newline that Encoder appends is valid JSON whitespace and is accepted by Telegram's parser. + -### func \(DefaultCodec\) [Unmarshal]() +### func \(DefaultCodec\) [Unmarshal]() ```go func (DefaultCodec) Unmarshal(data []byte, v any) error diff --git a/test/benchmarks/results/benchstat.txt b/test/benchmarks/results/benchstat.txt index d5bb93b..16ae00c 100644 --- a/test/benchmarks/results/benchstat.txt +++ b/test/benchmarks/results/benchstat.txt @@ -4,55 +4,55 @@ pkg: github.com/lukaszraczylo/go-telegram/test/benchmarks cpu: Apple M4 Max │ /Users/nvm/Documents/projects/private/go-telegram/test/benchmarks/results/raw.txt │ │ sec/op │ -Call_ours-16 38.95µ ± 3% -Call_gotba-16 41.95µ ± 2% -Call_telebot-16 43.63µ ± 0% -Call_gobot-16 61.11µ ± 1% -Call_telego-16 36.31µ ± 1% -Dispatch_ours-16 100.7n ± 3% -Dispatch_telebot-16 269.2n ± 5% -Dispatch_gobot-16 251.5n ± 4% -LargeUnmarshal_ours-16 6.667µ ± 4% -LargeUnmarshal_gotba-16 8.321µ ± 2% -LargeUnmarshal_telebot-16 10.24µ ± 4% -LargeUnmarshal_gobot-16 8.150µ ± 2% -LargeUnmarshal_telego-16 7.797µ ± 1% -LargeUnmarshal_echotron-16 8.072µ ± 0% -Webhook_ours-16 1.743µ ± 3% -Webhook_gotba-16 2.016µ ± 3% -Webhook_telebot-16 2.073µ ± 3% -Webhook_gobot-16 1.999µ ± 1% -Webhook_telego-16 2.026µ ± 2% -Webhook_echotron-16 1.973µ ± 0% -geomean 4.603µ +Call_ours-16 39.83µ ± 4% +Call_gotba-16 42.03µ ± 4% +Call_telebot-16 43.41µ ± 1% +Call_gobot-16 61.19µ ± 1% +Call_telego-16 35.84µ ± 1% +Dispatch_ours-16 98.46n ± 2% +Dispatch_telebot-16 270.9n ± 2% +Dispatch_gobot-16 246.1n ± 1% +LargeUnmarshal_ours-16 6.726µ ± 1% +LargeUnmarshal_gotba-16 8.066µ ± 1% +LargeUnmarshal_telebot-16 10.19µ ± 1% +LargeUnmarshal_gobot-16 8.231µ ± 1% +LargeUnmarshal_telego-16 7.849µ ± 2% +LargeUnmarshal_echotron-16 8.123µ ± 1% +Webhook_ours-16 1.832µ ± 4% +Webhook_gotba-16 2.082µ ± 0% +Webhook_telebot-16 2.194µ ± 1% +Webhook_gobot-16 2.082µ ± 1% +Webhook_telego-16 2.143µ ± 2% +Webhook_echotron-16 2.039µ ± 1% +geomean 4.658µ │ /Users/nvm/Documents/projects/private/go-telegram/test/benchmarks/results/raw.txt │ │ B/op │ -Call_ours-16 11.17Ki ± 0% -Call_gotba-16 10.95Ki ± 0% -Call_telebot-16 13.16Ki ± 0% -Call_gobot-16 13.51Ki ± 0% -Call_telego-16 6.556Ki ± 0% +Call_ours-16 11.09Ki ± 1% +Call_gotba-16 10.97Ki ± 0% +Call_telebot-16 13.15Ki ± 0% +Call_gobot-16 13.50Ki ± 0% +Call_telego-16 6.547Ki ± 0% Dispatch_ours-16 128.0 ± 0% -Dispatch_telebot-16 678.0 ± 0% +Dispatch_telebot-16 678.5 ± 0% Dispatch_gobot-16 48.00 ± 0% -LargeUnmarshal_ours-16 5.881Ki ± 0% +LargeUnmarshal_ours-16 5.875Ki ± 0% LargeUnmarshal_gotba-16 3.438Ki ± 0% LargeUnmarshal_telebot-16 5.594Ki ± 0% LargeUnmarshal_gobot-16 4.703Ki ± 0% -LargeUnmarshal_telego-16 6.621Ki ± 0% +LargeUnmarshal_telego-16 6.600Ki ± 0% LargeUnmarshal_echotron-16 4.219Ki ± 0% Webhook_ours-16 2.180Ki ± 0% Webhook_gotba-16 1.461Ki ± 0% Webhook_telebot-16 1.773Ki ± 0% Webhook_gobot-16 1.789Ki ± 0% -Webhook_telego-16 3.060Ki ± 0% +Webhook_telego-16 3.058Ki ± 0% Webhook_echotron-16 1.680Ki ± 0% -geomean 2.701Ki +geomean 2.699Ki │ /Users/nvm/Documents/projects/private/go-telegram/test/benchmarks/results/raw.txt │ │ allocs/op │ -Call_ours-16 104.0 ± 0% +Call_ours-16 102.0 ± 0% Call_gotba-16 125.0 ± 0% Call_telebot-16 139.0 ± 0% Call_gobot-16 176.0 ± 0% @@ -72,4 +72,4 @@ Webhook_telebot-16 Webhook_gobot-16 16.00 ± 0% Webhook_telego-16 11.00 ± 0% Webhook_echotron-16 16.00 ± 0% -geomean 26.03 +geomean 26.00 diff --git a/test/benchmarks/results/raw.txt b/test/benchmarks/results/raw.txt index 63926dc..481b97b 100644 --- a/test/benchmarks/results/raw.txt +++ b/test/benchmarks/results/raw.txt @@ -2,206 +2,205 @@ goos: darwin goarch: arm64 pkg: github.com/lukaszraczylo/go-telegram/test/benchmarks cpu: Apple M4 Max -BenchmarkCall_ours-16 30754 38732 ns/op 11589 B/op 105 allocs/op -BenchmarkCall_ours-16 31054 39002 ns/op 11476 B/op 104 allocs/op -BenchmarkCall_ours-16 30990 38440 ns/op 11471 B/op 104 allocs/op -BenchmarkCall_ours-16 30301 39464 ns/op 11452 B/op 104 allocs/op -BenchmarkCall_ours-16 30438 38897 ns/op 11425 B/op 104 allocs/op -BenchmarkCall_ours-16 30783 39107 ns/op 11429 B/op 104 allocs/op -BenchmarkCall_ours-16 30486 39507 ns/op 11402 B/op 104 allocs/op -BenchmarkCall_ours-16 30045 37723 ns/op 11442 B/op 104 allocs/op -BenchmarkCall_ours-16 37867 33103 ns/op 11444 B/op 104 allocs/op -BenchmarkCall_ours-16 30522 39139 ns/op 11436 B/op 104 allocs/op -BenchmarkCall_gotba-16 29838 40947 ns/op 11243 B/op 125 allocs/op -BenchmarkCall_gotba-16 28545 41897 ns/op 11182 B/op 125 allocs/op -BenchmarkCall_gotba-16 28713 41146 ns/op 11197 B/op 125 allocs/op -BenchmarkCall_gotba-16 28480 42210 ns/op 11238 B/op 125 allocs/op -BenchmarkCall_gotba-16 28831 42004 ns/op 11204 B/op 125 allocs/op -BenchmarkCall_gotba-16 28484 42012 ns/op 11224 B/op 125 allocs/op -BenchmarkCall_gotba-16 30481 41283 ns/op 11212 B/op 125 allocs/op -BenchmarkCall_gotba-16 28646 42042 ns/op 11209 B/op 125 allocs/op -BenchmarkCall_gotba-16 28418 40680 ns/op 11250 B/op 125 allocs/op -BenchmarkCall_gotba-16 28358 42146 ns/op 11208 B/op 125 allocs/op -BenchmarkCall_telebot-16 27294 43739 ns/op 13522 B/op 139 allocs/op -BenchmarkCall_telebot-16 27763 43429 ns/op 13491 B/op 139 allocs/op -BenchmarkCall_telebot-16 27525 43618 ns/op 13478 B/op 139 allocs/op -BenchmarkCall_telebot-16 27423 43711 ns/op 13431 B/op 139 allocs/op -BenchmarkCall_telebot-16 27415 43704 ns/op 13473 B/op 139 allocs/op -BenchmarkCall_telebot-16 27268 43834 ns/op 13477 B/op 139 allocs/op -BenchmarkCall_telebot-16 28180 43488 ns/op 13486 B/op 139 allocs/op -BenchmarkCall_telebot-16 27480 43644 ns/op 13485 B/op 139 allocs/op -BenchmarkCall_telebot-16 27458 43581 ns/op 13479 B/op 139 allocs/op -BenchmarkCall_telebot-16 27949 43415 ns/op 13480 B/op 139 allocs/op -BenchmarkCall_gobot-16 19503 60924 ns/op 13847 B/op 176 allocs/op -BenchmarkCall_gobot-16 19620 61253 ns/op 13837 B/op 176 allocs/op -BenchmarkCall_gobot-16 19790 60869 ns/op 13839 B/op 176 allocs/op -BenchmarkCall_gobot-16 19574 61153 ns/op 13816 B/op 176 allocs/op -BenchmarkCall_gobot-16 19634 61070 ns/op 13830 B/op 176 allocs/op -BenchmarkCall_gobot-16 19569 61173 ns/op 13817 B/op 176 allocs/op -BenchmarkCall_gobot-16 19549 61688 ns/op 13851 B/op 176 allocs/op -BenchmarkCall_gobot-16 19918 60815 ns/op 13779 B/op 176 allocs/op -BenchmarkCall_gobot-16 19440 61667 ns/op 13830 B/op 176 allocs/op -BenchmarkCall_gobot-16 19660 61036 ns/op 13837 B/op 176 allocs/op -BenchmarkCall_telego-16 32732 36606 ns/op 6788 B/op 48 allocs/op -BenchmarkCall_telego-16 33837 35882 ns/op 6697 B/op 48 allocs/op -BenchmarkCall_telego-16 33074 36146 ns/op 6693 B/op 48 allocs/op -BenchmarkCall_telego-16 33400 36090 ns/op 6723 B/op 48 allocs/op -BenchmarkCall_telego-16 32684 36296 ns/op 6709 B/op 48 allocs/op -BenchmarkCall_telego-16 32926 36577 ns/op 6721 B/op 48 allocs/op -BenchmarkCall_telego-16 33928 35481 ns/op 6708 B/op 48 allocs/op -BenchmarkCall_telego-16 33195 36318 ns/op 6711 B/op 48 allocs/op -BenchmarkCall_telego-16 33140 36812 ns/op 6717 B/op 48 allocs/op -BenchmarkCall_telego-16 32343 37631 ns/op 6716 B/op 48 allocs/op -BenchmarkDispatch_ours-16 12199088 98.57 ns/op 128 B/op 3 allocs/op -BenchmarkDispatch_ours-16 12223122 97.66 ns/op 128 B/op 3 allocs/op -BenchmarkDispatch_ours-16 12088142 97.43 ns/op 128 B/op 3 allocs/op -BenchmarkDispatch_ours-16 12463010 100.9 ns/op 128 B/op 3 allocs/op -BenchmarkDispatch_ours-16 12284848 99.38 ns/op 128 B/op 3 allocs/op -BenchmarkDispatch_ours-16 11485198 101.1 ns/op 128 B/op 3 allocs/op -BenchmarkDispatch_ours-16 11685897 102.2 ns/op 128 B/op 3 allocs/op -BenchmarkDispatch_ours-16 11733669 102.1 ns/op 128 B/op 3 allocs/op -BenchmarkDispatch_ours-16 11811807 100.5 ns/op 128 B/op 3 allocs/op -BenchmarkDispatch_ours-16 11691974 103.1 ns/op 128 B/op 3 allocs/op -BenchmarkDispatch_telebot-16 4270724 284.6 ns/op 679 B/op 5 allocs/op -BenchmarkDispatch_telebot-16 4369950 270.2 ns/op 678 B/op 5 allocs/op -BenchmarkDispatch_telebot-16 4604205 269.9 ns/op 679 B/op 5 allocs/op -BenchmarkDispatch_telebot-16 4431572 282.2 ns/op 678 B/op 5 allocs/op -BenchmarkDispatch_telebot-16 4186550 272.0 ns/op 678 B/op 5 allocs/op -BenchmarkDispatch_telebot-16 4472223 265.7 ns/op 679 B/op 5 allocs/op -BenchmarkDispatch_telebot-16 4537406 265.0 ns/op 679 B/op 5 allocs/op -BenchmarkDispatch_telebot-16 4544478 264.4 ns/op 678 B/op 5 allocs/op -BenchmarkDispatch_telebot-16 4519431 266.7 ns/op 678 B/op 5 allocs/op -BenchmarkDispatch_telebot-16 4448779 268.5 ns/op 678 B/op 5 allocs/op -BenchmarkDispatch_gobot-16 4493029 254.1 ns/op 48 B/op 1 allocs/op -BenchmarkDispatch_gobot-16 4726080 261.5 ns/op 48 B/op 1 allocs/op -BenchmarkDispatch_gobot-16 4884592 249.6 ns/op 48 B/op 1 allocs/op -BenchmarkDispatch_gobot-16 4639986 256.7 ns/op 48 B/op 1 allocs/op -BenchmarkDispatch_gobot-16 4424702 261.1 ns/op 48 B/op 1 allocs/op -BenchmarkDispatch_gobot-16 4783779 249.2 ns/op 48 B/op 1 allocs/op -BenchmarkDispatch_gobot-16 4916862 248.2 ns/op 48 B/op 1 allocs/op -BenchmarkDispatch_gobot-16 4884650 249.9 ns/op 48 B/op 1 allocs/op -BenchmarkDispatch_gobot-16 4822939 252.4 ns/op 48 B/op 1 allocs/op -BenchmarkDispatch_gobot-16 4707606 250.5 ns/op 48 B/op 1 allocs/op -BenchmarkLargeUnmarshal_ours-16 177442 6697 ns/op 6024 B/op 34 allocs/op -BenchmarkLargeUnmarshal_ours-16 178348 6700 ns/op 6021 B/op 34 allocs/op -BenchmarkLargeUnmarshal_ours-16 180528 6686 ns/op 6022 B/op 34 allocs/op -BenchmarkLargeUnmarshal_ours-16 182416 6659 ns/op 6021 B/op 34 allocs/op -BenchmarkLargeUnmarshal_ours-16 179305 6675 ns/op 6022 B/op 34 allocs/op -BenchmarkLargeUnmarshal_ours-16 176892 6724 ns/op 6021 B/op 34 allocs/op -BenchmarkLargeUnmarshal_ours-16 185355 6392 ns/op 6022 B/op 34 allocs/op -BenchmarkLargeUnmarshal_ours-16 189590 6390 ns/op 6022 B/op 34 allocs/op -BenchmarkLargeUnmarshal_ours-16 189783 6438 ns/op 6022 B/op 34 allocs/op -BenchmarkLargeUnmarshal_ours-16 187572 6483 ns/op 6022 B/op 34 allocs/op -BenchmarkLargeUnmarshal_gotba-16 142377 8296 ns/op 3520 B/op 56 allocs/op -BenchmarkLargeUnmarshal_gotba-16 144884 8274 ns/op 3520 B/op 56 allocs/op -BenchmarkLargeUnmarshal_gotba-16 146434 8295 ns/op 3520 B/op 56 allocs/op -BenchmarkLargeUnmarshal_gotba-16 145183 8260 ns/op 3520 B/op 56 allocs/op -BenchmarkLargeUnmarshal_gotba-16 144775 8416 ns/op 3520 B/op 56 allocs/op -BenchmarkLargeUnmarshal_gotba-16 139510 8224 ns/op 3520 B/op 56 allocs/op -BenchmarkLargeUnmarshal_gotba-16 146359 8542 ns/op 3520 B/op 56 allocs/op -BenchmarkLargeUnmarshal_gotba-16 144981 8346 ns/op 3520 B/op 56 allocs/op -BenchmarkLargeUnmarshal_gotba-16 146877 8399 ns/op 3520 B/op 56 allocs/op -BenchmarkLargeUnmarshal_gotba-16 145443 8454 ns/op 3519 B/op 56 allocs/op -BenchmarkLargeUnmarshal_telebot-16 116883 10327 ns/op 5728 B/op 60 allocs/op -BenchmarkLargeUnmarshal_telebot-16 114584 10333 ns/op 5728 B/op 60 allocs/op -BenchmarkLargeUnmarshal_telebot-16 117277 10250 ns/op 5728 B/op 60 allocs/op -BenchmarkLargeUnmarshal_telebot-16 117700 10270 ns/op 5728 B/op 60 allocs/op -BenchmarkLargeUnmarshal_telebot-16 117328 10401 ns/op 5728 B/op 60 allocs/op -BenchmarkLargeUnmarshal_telebot-16 115922 10223 ns/op 5728 B/op 60 allocs/op -BenchmarkLargeUnmarshal_telebot-16 117475 10049 ns/op 5728 B/op 60 allocs/op -BenchmarkLargeUnmarshal_telebot-16 123367 9866 ns/op 5728 B/op 60 allocs/op -BenchmarkLargeUnmarshal_telebot-16 123385 9811 ns/op 5728 B/op 60 allocs/op -BenchmarkLargeUnmarshal_telebot-16 122586 9873 ns/op 5728 B/op 60 allocs/op -BenchmarkLargeUnmarshal_gobot-16 148576 8064 ns/op 4817 B/op 50 allocs/op -BenchmarkLargeUnmarshal_gobot-16 147967 8113 ns/op 4816 B/op 50 allocs/op -BenchmarkLargeUnmarshal_gobot-16 150718 7991 ns/op 4816 B/op 50 allocs/op -BenchmarkLargeUnmarshal_gobot-16 150271 8066 ns/op 4815 B/op 50 allocs/op -BenchmarkLargeUnmarshal_gobot-16 147646 8066 ns/op 4816 B/op 50 allocs/op -BenchmarkLargeUnmarshal_gobot-16 147889 8186 ns/op 4816 B/op 50 allocs/op -BenchmarkLargeUnmarshal_gobot-16 143164 8413 ns/op 4816 B/op 50 allocs/op -BenchmarkLargeUnmarshal_gobot-16 150464 8276 ns/op 4815 B/op 50 allocs/op -BenchmarkLargeUnmarshal_gobot-16 145249 8201 ns/op 4816 B/op 50 allocs/op -BenchmarkLargeUnmarshal_gobot-16 146100 8216 ns/op 4816 B/op 50 allocs/op -BenchmarkLargeUnmarshal_telego-16 149001 7802 ns/op 6781 B/op 31 allocs/op -BenchmarkLargeUnmarshal_telego-16 152780 7835 ns/op 6775 B/op 31 allocs/op -BenchmarkLargeUnmarshal_telego-16 156508 7817 ns/op 6780 B/op 31 allocs/op -BenchmarkLargeUnmarshal_telego-16 154938 7816 ns/op 6777 B/op 31 allocs/op -BenchmarkLargeUnmarshal_telego-16 150121 7809 ns/op 6778 B/op 31 allocs/op -BenchmarkLargeUnmarshal_telego-16 152810 7791 ns/op 6780 B/op 31 allocs/op -BenchmarkLargeUnmarshal_telego-16 159613 7784 ns/op 6778 B/op 31 allocs/op -BenchmarkLargeUnmarshal_telego-16 154402 7729 ns/op 6780 B/op 31 allocs/op -BenchmarkLargeUnmarshal_telego-16 157184 7660 ns/op 6782 B/op 31 allocs/op -BenchmarkLargeUnmarshal_telego-16 155822 7768 ns/op 6780 B/op 31 allocs/op -BenchmarkLargeUnmarshal_echotron-16 144252 8147 ns/op 4323 B/op 56 allocs/op -BenchmarkLargeUnmarshal_echotron-16 147961 8089 ns/op 4319 B/op 56 allocs/op -BenchmarkLargeUnmarshal_echotron-16 149847 8049 ns/op 4320 B/op 56 allocs/op -BenchmarkLargeUnmarshal_echotron-16 149128 8069 ns/op 4320 B/op 56 allocs/op -BenchmarkLargeUnmarshal_echotron-16 147277 8075 ns/op 4320 B/op 56 allocs/op -BenchmarkLargeUnmarshal_echotron-16 149132 8089 ns/op 4320 B/op 56 allocs/op -BenchmarkLargeUnmarshal_echotron-16 148837 8014 ns/op 4319 B/op 56 allocs/op -BenchmarkLargeUnmarshal_echotron-16 149288 8050 ns/op 4320 B/op 56 allocs/op -BenchmarkLargeUnmarshal_echotron-16 146833 8097 ns/op 4320 B/op 56 allocs/op -BenchmarkLargeUnmarshal_echotron-16 149233 8041 ns/op 4320 B/op 56 allocs/op -BenchmarkWebhook_ours-16 707102 1721 ns/op 2232 B/op 11 allocs/op -BenchmarkWebhook_ours-16 700047 1734 ns/op 2232 B/op 11 allocs/op -BenchmarkWebhook_ours-16 725071 1721 ns/op 2232 B/op 11 allocs/op -BenchmarkWebhook_ours-16 675003 1751 ns/op 2232 B/op 11 allocs/op -BenchmarkWebhook_ours-16 693903 1787 ns/op 2232 B/op 11 allocs/op -BenchmarkWebhook_ours-16 714036 1751 ns/op 2232 B/op 11 allocs/op -BenchmarkWebhook_ours-16 646494 1816 ns/op 2232 B/op 11 allocs/op -BenchmarkWebhook_ours-16 696355 1801 ns/op 2232 B/op 11 allocs/op -BenchmarkWebhook_ours-16 709545 1734 ns/op 2232 B/op 11 allocs/op -BenchmarkWebhook_ours-16 709700 1725 ns/op 2232 B/op 11 allocs/op -BenchmarkWebhook_gotba-16 611132 2027 ns/op 1496 B/op 17 allocs/op -BenchmarkWebhook_gotba-16 624046 2072 ns/op 1496 B/op 17 allocs/op -BenchmarkWebhook_gotba-16 588478 2093 ns/op 1496 B/op 17 allocs/op -BenchmarkWebhook_gotba-16 609744 2012 ns/op 1496 B/op 17 allocs/op -BenchmarkWebhook_gotba-16 606912 2012 ns/op 1496 B/op 17 allocs/op -BenchmarkWebhook_gotba-16 612211 2000 ns/op 1496 B/op 17 allocs/op -BenchmarkWebhook_gotba-16 605488 2015 ns/op 1496 B/op 17 allocs/op -BenchmarkWebhook_gotba-16 622398 2006 ns/op 1496 B/op 17 allocs/op -BenchmarkWebhook_gotba-16 610478 2017 ns/op 1496 B/op 17 allocs/op -BenchmarkWebhook_gotba-16 610350 2030 ns/op 1496 B/op 17 allocs/op -BenchmarkWebhook_telebot-16 559515 2138 ns/op 1816 B/op 17 allocs/op -BenchmarkWebhook_telebot-16 558510 2057 ns/op 1816 B/op 17 allocs/op -BenchmarkWebhook_telebot-16 587257 2079 ns/op 1816 B/op 17 allocs/op -BenchmarkWebhook_telebot-16 585321 2059 ns/op 1816 B/op 17 allocs/op -BenchmarkWebhook_telebot-16 576236 2067 ns/op 1816 B/op 17 allocs/op -BenchmarkWebhook_telebot-16 570172 2070 ns/op 1816 B/op 17 allocs/op -BenchmarkWebhook_telebot-16 568270 2131 ns/op 1816 B/op 17 allocs/op -BenchmarkWebhook_telebot-16 567567 2094 ns/op 1816 B/op 17 allocs/op -BenchmarkWebhook_telebot-16 586588 2076 ns/op 1816 B/op 17 allocs/op -BenchmarkWebhook_telebot-16 574495 2062 ns/op 1816 B/op 17 allocs/op -BenchmarkWebhook_gobot-16 597710 2006 ns/op 1832 B/op 16 allocs/op -BenchmarkWebhook_gobot-16 594742 2016 ns/op 1832 B/op 16 allocs/op -BenchmarkWebhook_gobot-16 603187 1998 ns/op 1832 B/op 16 allocs/op -BenchmarkWebhook_gobot-16 608301 2011 ns/op 1832 B/op 16 allocs/op -BenchmarkWebhook_gobot-16 605532 1984 ns/op 1832 B/op 16 allocs/op -BenchmarkWebhook_gobot-16 609892 1990 ns/op 1832 B/op 16 allocs/op -BenchmarkWebhook_gobot-16 596637 1999 ns/op 1832 B/op 16 allocs/op -BenchmarkWebhook_gobot-16 592108 1993 ns/op 1832 B/op 16 allocs/op -BenchmarkWebhook_gobot-16 607069 1999 ns/op 1832 B/op 16 allocs/op -BenchmarkWebhook_gobot-16 594915 1997 ns/op 1832 B/op 16 allocs/op -BenchmarkWebhook_telego-16 603300 2021 ns/op 3133 B/op 11 allocs/op -BenchmarkWebhook_telego-16 602503 2016 ns/op 3133 B/op 11 allocs/op -BenchmarkWebhook_telego-16 618267 2016 ns/op 3133 B/op 11 allocs/op -BenchmarkWebhook_telego-16 601855 2027 ns/op 3133 B/op 11 allocs/op -BenchmarkWebhook_telego-16 612424 2035 ns/op 3132 B/op 11 allocs/op -BenchmarkWebhook_telego-16 595890 2074 ns/op 3133 B/op 11 allocs/op -BenchmarkWebhook_telego-16 605565 2001 ns/op 3133 B/op 11 allocs/op -BenchmarkWebhook_telego-16 610453 2096 ns/op 3133 B/op 11 allocs/op -BenchmarkWebhook_telego-16 588056 2069 ns/op 3132 B/op 11 allocs/op -BenchmarkWebhook_telego-16 595764 2025 ns/op 3133 B/op 11 allocs/op -BenchmarkWebhook_echotron-16 599088 1975 ns/op 1720 B/op 16 allocs/op -BenchmarkWebhook_echotron-16 626964 1975 ns/op 1720 B/op 16 allocs/op -BenchmarkWebhook_echotron-16 635306 1967 ns/op 1720 B/op 16 allocs/op -BenchmarkWebhook_echotron-16 606621 1965 ns/op 1720 B/op 16 allocs/op -BenchmarkWebhook_echotron-16 625998 1965 ns/op 1720 B/op 16 allocs/op -BenchmarkWebhook_echotron-16 646352 1976 ns/op 1720 B/op 16 allocs/op -BenchmarkWebhook_echotron-16 634186 1971 ns/op 1720 B/op 16 allocs/op -BenchmarkWebhook_echotron-16 628503 1982 ns/op 1720 B/op 16 allocs/op -BenchmarkWebhook_echotron-16 612586 1975 ns/op 1720 B/op 16 allocs/op -BenchmarkWebhook_echotron-16 622320 1965 ns/op 1720 B/op 16 allocs/op +BenchmarkCall_ours-16 27756 39971 ns/op 11497 B/op 103 allocs/op +BenchmarkCall_ours-16 30495 39111 ns/op 11329 B/op 102 allocs/op +BenchmarkCall_ours-16 29250 41427 ns/op 11356 B/op 102 allocs/op +BenchmarkCall_ours-16 29766 39680 ns/op 11366 B/op 102 allocs/op +BenchmarkCall_ours-16 29157 40066 ns/op 11338 B/op 102 allocs/op +BenchmarkCall_ours-16 30567 38404 ns/op 11276 B/op 102 allocs/op +BenchmarkCall_ours-16 30470 38923 ns/op 11306 B/op 102 allocs/op +BenchmarkCall_ours-16 30520 40212 ns/op 11364 B/op 102 allocs/op +BenchmarkCall_ours-16 30315 39595 ns/op 11361 B/op 102 allocs/op +BenchmarkCall_ours-16 28747 41549 ns/op 11434 B/op 102 allocs/op +BenchmarkCall_gotba-16 28140 43735 ns/op 11255 B/op 125 allocs/op +BenchmarkCall_gotba-16 27189 43528 ns/op 11247 B/op 125 allocs/op +BenchmarkCall_gotba-16 27940 43644 ns/op 11259 B/op 125 allocs/op +BenchmarkCall_gotba-16 29090 41643 ns/op 11232 B/op 125 allocs/op +BenchmarkCall_gotba-16 28002 42461 ns/op 11183 B/op 125 allocs/op +BenchmarkCall_gotba-16 28578 42082 ns/op 11204 B/op 125 allocs/op +BenchmarkCall_gotba-16 28549 41973 ns/op 11237 B/op 125 allocs/op +BenchmarkCall_gotba-16 29086 41702 ns/op 11203 B/op 125 allocs/op +BenchmarkCall_gotba-16 29630 41783 ns/op 11262 B/op 125 allocs/op +BenchmarkCall_gotba-16 28371 41810 ns/op 11217 B/op 125 allocs/op +BenchmarkCall_telebot-16 27510 43416 ns/op 13457 B/op 139 allocs/op +BenchmarkCall_telebot-16 28102 43319 ns/op 13473 B/op 139 allocs/op +BenchmarkCall_telebot-16 27558 43530 ns/op 13417 B/op 139 allocs/op +BenchmarkCall_telebot-16 27274 43654 ns/op 13445 B/op 139 allocs/op +BenchmarkCall_telebot-16 27627 43530 ns/op 13489 B/op 139 allocs/op +BenchmarkCall_telebot-16 27499 42836 ns/op 13467 B/op 139 allocs/op +BenchmarkCall_telebot-16 27860 43375 ns/op 13457 B/op 139 allocs/op +BenchmarkCall_telebot-16 27711 43400 ns/op 13439 B/op 139 allocs/op +BenchmarkCall_telebot-16 27668 43472 ns/op 13482 B/op 139 allocs/op +BenchmarkCall_telebot-16 28063 43182 ns/op 13487 B/op 139 allocs/op +BenchmarkCall_gobot-16 19645 60805 ns/op 13879 B/op 176 allocs/op +BenchmarkCall_gobot-16 19562 61374 ns/op 13823 B/op 176 allocs/op +BenchmarkCall_gobot-16 19575 60944 ns/op 13823 B/op 176 allocs/op +BenchmarkCall_gobot-16 19538 61461 ns/op 13844 B/op 176 allocs/op +BenchmarkCall_gobot-16 19624 61253 ns/op 13806 B/op 176 allocs/op +BenchmarkCall_gobot-16 19617 61127 ns/op 13824 B/op 176 allocs/op +BenchmarkCall_gobot-16 19516 61568 ns/op 13775 B/op 176 allocs/op +BenchmarkCall_gobot-16 19514 61340 ns/op 13828 B/op 176 allocs/op +BenchmarkCall_gobot-16 19392 60426 ns/op 13863 B/op 176 allocs/op +BenchmarkCall_gobot-16 23968 49951 ns/op 13844 B/op 176 allocs/op +BenchmarkCall_telego-16 33622 35493 ns/op 6780 B/op 48 allocs/op +BenchmarkCall_telego-16 33874 35438 ns/op 6703 B/op 48 allocs/op +BenchmarkCall_telego-16 34560 35482 ns/op 6704 B/op 48 allocs/op +BenchmarkCall_telego-16 33298 35830 ns/op 6711 B/op 48 allocs/op +BenchmarkCall_telego-16 33205 35946 ns/op 6706 B/op 48 allocs/op +BenchmarkCall_telego-16 33428 35949 ns/op 6707 B/op 48 allocs/op +BenchmarkCall_telego-16 33452 35974 ns/op 6692 B/op 48 allocs/op +BenchmarkCall_telego-16 33056 35853 ns/op 6705 B/op 48 allocs/op +BenchmarkCall_telego-16 33120 35808 ns/op 6703 B/op 48 allocs/op +BenchmarkCall_telego-16 33450 38996 ns/op 6699 B/op 48 allocs/op +BenchmarkDispatch_ours-16 12381547 96.05 ns/op 128 B/op 3 allocs/op +BenchmarkDispatch_ours-16 12636062 99.34 ns/op 128 B/op 3 allocs/op +BenchmarkDispatch_ours-16 12161170 98.43 ns/op 128 B/op 3 allocs/op +BenchmarkDispatch_ours-16 12205023 97.90 ns/op 128 B/op 3 allocs/op +BenchmarkDispatch_ours-16 12590581 98.83 ns/op 128 B/op 3 allocs/op +BenchmarkDispatch_ours-16 12033376 99.15 ns/op 128 B/op 3 allocs/op +BenchmarkDispatch_ours-16 12049588 98.48 ns/op 128 B/op 3 allocs/op +BenchmarkDispatch_ours-16 12324108 98.38 ns/op 128 B/op 3 allocs/op +BenchmarkDispatch_ours-16 11924947 96.71 ns/op 128 B/op 3 allocs/op +BenchmarkDispatch_ours-16 11940064 99.26 ns/op 128 B/op 3 allocs/op +BenchmarkDispatch_telebot-16 4456072 262.5 ns/op 678 B/op 5 allocs/op +BenchmarkDispatch_telebot-16 4330234 275.3 ns/op 678 B/op 5 allocs/op +BenchmarkDispatch_telebot-16 4478779 268.7 ns/op 679 B/op 5 allocs/op +BenchmarkDispatch_telebot-16 4394821 282.5 ns/op 678 B/op 5 allocs/op +BenchmarkDispatch_telebot-16 4376773 271.6 ns/op 679 B/op 5 allocs/op +BenchmarkDispatch_telebot-16 4516370 268.7 ns/op 678 B/op 5 allocs/op +BenchmarkDispatch_telebot-16 4465942 276.0 ns/op 678 B/op 5 allocs/op +BenchmarkDispatch_telebot-16 4399328 270.1 ns/op 679 B/op 5 allocs/op +BenchmarkDispatch_telebot-16 4531597 268.3 ns/op 679 B/op 5 allocs/op +BenchmarkDispatch_telebot-16 4376616 272.3 ns/op 679 B/op 5 allocs/op +BenchmarkDispatch_gobot-16 4911369 249.4 ns/op 48 B/op 1 allocs/op +BenchmarkDispatch_gobot-16 4896456 246.3 ns/op 48 B/op 1 allocs/op +BenchmarkDispatch_gobot-16 4789376 246.4 ns/op 48 B/op 1 allocs/op +BenchmarkDispatch_gobot-16 4949206 247.7 ns/op 48 B/op 1 allocs/op +BenchmarkDispatch_gobot-16 4902912 243.1 ns/op 48 B/op 1 allocs/op +BenchmarkDispatch_gobot-16 4913300 244.7 ns/op 48 B/op 1 allocs/op +BenchmarkDispatch_gobot-16 4925991 245.5 ns/op 48 B/op 1 allocs/op +BenchmarkDispatch_gobot-16 4817457 245.9 ns/op 48 B/op 1 allocs/op +BenchmarkDispatch_gobot-16 4943328 245.8 ns/op 49 B/op 1 allocs/op +BenchmarkDispatch_gobot-16 4751266 248.1 ns/op 48 B/op 1 allocs/op +BenchmarkLargeUnmarshal_ours-16 180361 6682 ns/op 6019 B/op 34 allocs/op +BenchmarkLargeUnmarshal_ours-16 178388 6765 ns/op 6016 B/op 34 allocs/op +BenchmarkLargeUnmarshal_ours-16 182600 6701 ns/op 6016 B/op 34 allocs/op +BenchmarkLargeUnmarshal_ours-16 178785 6710 ns/op 6016 B/op 34 allocs/op +BenchmarkLargeUnmarshal_ours-16 181588 6726 ns/op 6016 B/op 34 allocs/op +BenchmarkLargeUnmarshal_ours-16 177378 6730 ns/op 6016 B/op 34 allocs/op +BenchmarkLargeUnmarshal_ours-16 181004 6729 ns/op 6016 B/op 34 allocs/op +BenchmarkLargeUnmarshal_ours-16 176672 6682 ns/op 6016 B/op 34 allocs/op +BenchmarkLargeUnmarshal_ours-16 184182 6726 ns/op 6016 B/op 34 allocs/op +BenchmarkLargeUnmarshal_ours-16 179983 6813 ns/op 6016 B/op 34 allocs/op +BenchmarkLargeUnmarshal_gotba-16 138108 8579 ns/op 3520 B/op 56 allocs/op +BenchmarkLargeUnmarshal_gotba-16 148593 8143 ns/op 3520 B/op 56 allocs/op +BenchmarkLargeUnmarshal_gotba-16 147964 8075 ns/op 3520 B/op 56 allocs/op +BenchmarkLargeUnmarshal_gotba-16 147601 8161 ns/op 3520 B/op 56 allocs/op +BenchmarkLargeUnmarshal_gotba-16 148257 8020 ns/op 3520 B/op 56 allocs/op +BenchmarkLargeUnmarshal_gotba-16 150858 8058 ns/op 3519 B/op 56 allocs/op +BenchmarkLargeUnmarshal_gotba-16 149251 8040 ns/op 3520 B/op 56 allocs/op +BenchmarkLargeUnmarshal_gotba-16 151614 8054 ns/op 3520 B/op 56 allocs/op +BenchmarkLargeUnmarshal_gotba-16 152306 8050 ns/op 3519 B/op 56 allocs/op +BenchmarkLargeUnmarshal_gotba-16 152979 8094 ns/op 3520 B/op 56 allocs/op +BenchmarkLargeUnmarshal_telebot-16 119103 10113 ns/op 5728 B/op 60 allocs/op +BenchmarkLargeUnmarshal_telebot-16 115418 10247 ns/op 5728 B/op 60 allocs/op +BenchmarkLargeUnmarshal_telebot-16 116160 10260 ns/op 5728 B/op 60 allocs/op +BenchmarkLargeUnmarshal_telebot-16 117031 10346 ns/op 5728 B/op 60 allocs/op +BenchmarkLargeUnmarshal_telebot-16 116731 10311 ns/op 5728 B/op 60 allocs/op +BenchmarkLargeUnmarshal_telebot-16 121227 10135 ns/op 5728 B/op 60 allocs/op +BenchmarkLargeUnmarshal_telebot-16 119989 10178 ns/op 5728 B/op 60 allocs/op +BenchmarkLargeUnmarshal_telebot-16 119311 10194 ns/op 5728 B/op 60 allocs/op +BenchmarkLargeUnmarshal_telebot-16 119388 10183 ns/op 5728 B/op 60 allocs/op +BenchmarkLargeUnmarshal_telebot-16 120195 10133 ns/op 5728 B/op 60 allocs/op +BenchmarkLargeUnmarshal_gobot-16 146700 8235 ns/op 4817 B/op 50 allocs/op +BenchmarkLargeUnmarshal_gobot-16 147666 8230 ns/op 4816 B/op 50 allocs/op +BenchmarkLargeUnmarshal_gobot-16 148058 8212 ns/op 4816 B/op 50 allocs/op +BenchmarkLargeUnmarshal_gobot-16 148092 8210 ns/op 4816 B/op 50 allocs/op +BenchmarkLargeUnmarshal_gobot-16 146656 8208 ns/op 4816 B/op 50 allocs/op +BenchmarkLargeUnmarshal_gobot-16 148036 8259 ns/op 4816 B/op 50 allocs/op +BenchmarkLargeUnmarshal_gobot-16 146211 8287 ns/op 4816 B/op 50 allocs/op +BenchmarkLargeUnmarshal_gobot-16 146793 8279 ns/op 4816 B/op 50 allocs/op +BenchmarkLargeUnmarshal_gobot-16 146083 8232 ns/op 4816 B/op 50 allocs/op +BenchmarkLargeUnmarshal_gobot-16 147385 8221 ns/op 4816 B/op 50 allocs/op +BenchmarkLargeUnmarshal_telego-16 150852 8155 ns/op 6762 B/op 31 allocs/op +BenchmarkLargeUnmarshal_telego-16 152559 8040 ns/op 6758 B/op 31 allocs/op +BenchmarkLargeUnmarshal_telego-16 146462 7989 ns/op 6757 B/op 31 allocs/op +BenchmarkLargeUnmarshal_telego-16 154480 7842 ns/op 6759 B/op 31 allocs/op +BenchmarkLargeUnmarshal_telego-16 155208 7811 ns/op 6759 B/op 31 allocs/op +BenchmarkLargeUnmarshal_telego-16 149310 7848 ns/op 6759 B/op 31 allocs/op +BenchmarkLargeUnmarshal_telego-16 156939 7835 ns/op 6757 B/op 31 allocs/op +BenchmarkLargeUnmarshal_telego-16 154064 7867 ns/op 6759 B/op 31 allocs/op +BenchmarkLargeUnmarshal_telego-16 153975 7849 ns/op 6758 B/op 31 allocs/op +BenchmarkLargeUnmarshal_telego-16 152520 7811 ns/op 6758 B/op 31 allocs/op +BenchmarkLargeUnmarshal_echotron-16 145399 8167 ns/op 4323 B/op 56 allocs/op +BenchmarkLargeUnmarshal_echotron-16 147351 8124 ns/op 4319 B/op 56 allocs/op +BenchmarkLargeUnmarshal_echotron-16 148053 8094 ns/op 4320 B/op 56 allocs/op +BenchmarkLargeUnmarshal_echotron-16 147170 8124 ns/op 4320 B/op 56 allocs/op +BenchmarkLargeUnmarshal_echotron-16 147792 8092 ns/op 4320 B/op 56 allocs/op +BenchmarkLargeUnmarshal_echotron-16 145971 8105 ns/op 4320 B/op 56 allocs/op +BenchmarkLargeUnmarshal_echotron-16 148708 8122 ns/op 4320 B/op 56 allocs/op +BenchmarkLargeUnmarshal_echotron-16 147525 8105 ns/op 4320 B/op 56 allocs/op +BenchmarkLargeUnmarshal_echotron-16 148635 8165 ns/op 4320 B/op 56 allocs/op +BenchmarkLargeUnmarshal_echotron-16 150871 8124 ns/op 4320 B/op 56 allocs/op +BenchmarkWebhook_ours-16 705109 1911 ns/op 2232 B/op 11 allocs/op +BenchmarkWebhook_ours-16 651456 1911 ns/op 2232 B/op 11 allocs/op +BenchmarkWebhook_ours-16 683557 1875 ns/op 2232 B/op 11 allocs/op +BenchmarkWebhook_ours-16 668317 1830 ns/op 2232 B/op 11 allocs/op +BenchmarkWebhook_ours-16 703718 1833 ns/op 2232 B/op 11 allocs/op +BenchmarkWebhook_ours-16 707150 1844 ns/op 2232 B/op 11 allocs/op +BenchmarkWebhook_ours-16 700472 1810 ns/op 2232 B/op 11 allocs/op +BenchmarkWebhook_ours-16 699192 1828 ns/op 2232 B/op 11 allocs/op +BenchmarkWebhook_ours-16 671794 1828 ns/op 2232 B/op 11 allocs/op +BenchmarkWebhook_ours-16 687226 1826 ns/op 2232 B/op 11 allocs/op +BenchmarkWebhook_gotba-16 544628 2080 ns/op 1496 B/op 17 allocs/op +BenchmarkWebhook_gotba-16 565494 2081 ns/op 1496 B/op 17 allocs/op +BenchmarkWebhook_gotba-16 579736 2081 ns/op 1496 B/op 17 allocs/op +BenchmarkWebhook_gotba-16 581365 2082 ns/op 1496 B/op 17 allocs/op +BenchmarkWebhook_gotba-16 580501 2075 ns/op 1496 B/op 17 allocs/op +BenchmarkWebhook_gotba-16 582160 2091 ns/op 1496 B/op 17 allocs/op +BenchmarkWebhook_gotba-16 563130 2089 ns/op 1496 B/op 17 allocs/op +BenchmarkWebhook_gotba-16 573872 2088 ns/op 1496 B/op 17 allocs/op +BenchmarkWebhook_gotba-16 569616 2093 ns/op 1496 B/op 17 allocs/op +BenchmarkWebhook_gotba-16 599923 2069 ns/op 1496 B/op 17 allocs/op +BenchmarkWebhook_telebot-16 562394 2162 ns/op 1816 B/op 17 allocs/op +BenchmarkWebhook_telebot-16 562137 2272 ns/op 1816 B/op 17 allocs/op +BenchmarkWebhook_telebot-16 488323 2220 ns/op 1816 B/op 17 allocs/op +BenchmarkWebhook_telebot-16 538561 2199 ns/op 1816 B/op 17 allocs/op +BenchmarkWebhook_telebot-16 581037 2187 ns/op 1816 B/op 17 allocs/op +BenchmarkWebhook_telebot-16 540055 2213 ns/op 1816 B/op 17 allocs/op +BenchmarkWebhook_telebot-16 546921 2203 ns/op 1816 B/op 17 allocs/op +BenchmarkWebhook_telebot-16 574988 2188 ns/op 1816 B/op 17 allocs/op +BenchmarkWebhook_telebot-16 588076 2154 ns/op 1816 B/op 17 allocs/op +BenchmarkWebhook_telebot-16 571617 2181 ns/op 1816 B/op 17 allocs/op +BenchmarkWebhook_gobot-16 588786 2080 ns/op 1832 B/op 16 allocs/op +BenchmarkWebhook_gobot-16 551653 2080 ns/op 1832 B/op 16 allocs/op +BenchmarkWebhook_gobot-16 590686 2084 ns/op 1832 B/op 16 allocs/op +BenchmarkWebhook_gobot-16 588870 2096 ns/op 1832 B/op 16 allocs/op +BenchmarkWebhook_gobot-16 606735 2064 ns/op 1832 B/op 16 allocs/op +BenchmarkWebhook_gobot-16 597108 2084 ns/op 1832 B/op 16 allocs/op +BenchmarkWebhook_gobot-16 600633 2069 ns/op 1832 B/op 16 allocs/op +BenchmarkWebhook_gobot-16 589102 2110 ns/op 1832 B/op 16 allocs/op +BenchmarkWebhook_gobot-16 583528 2104 ns/op 1832 B/op 16 allocs/op +BenchmarkWebhook_gobot-16 599022 2073 ns/op 1832 B/op 16 allocs/op +BenchmarkWebhook_telego-16 587408 2193 ns/op 3131 B/op 11 allocs/op +BenchmarkWebhook_telego-16 601533 2152 ns/op 3131 B/op 11 allocs/op +BenchmarkWebhook_telego-16 584689 2127 ns/op 3131 B/op 11 allocs/op +BenchmarkWebhook_telego-16 576732 2153 ns/op 3131 B/op 11 allocs/op +BenchmarkWebhook_telego-16 568095 2143 ns/op 3131 B/op 11 allocs/op +BenchmarkWebhook_telego-16 553896 2132 ns/op 3131 B/op 11 allocs/op +BenchmarkWebhook_telego-16 579055 2130 ns/op 3131 B/op 11 allocs/op +BenchmarkWebhook_telego-16 595776 2144 ns/op 3131 B/op 11 allocs/op +BenchmarkWebhook_telego-16 573843 2134 ns/op 3131 B/op 11 allocs/op +BenchmarkWebhook_telego-16 513824 2267 ns/op 3131 B/op 11 allocs/op +BenchmarkWebhook_echotron-16 587734 2178 ns/op 1720 B/op 16 allocs/op +BenchmarkWebhook_echotron-16 557188 2039 ns/op 1720 B/op 16 allocs/op +BenchmarkWebhook_echotron-16 600524 2020 ns/op 1720 B/op 16 allocs/op +BenchmarkWebhook_echotron-16 602959 2019 ns/op 1720 B/op 16 allocs/op +BenchmarkWebhook_echotron-16 588694 2048 ns/op 1720 B/op 16 allocs/op +BenchmarkWebhook_echotron-16 602366 2039 ns/op 1720 B/op 16 allocs/op +BenchmarkWebhook_echotron-16 604621 2031 ns/op 1720 B/op 16 allocs/op +BenchmarkWebhook_echotron-16 599146 2037 ns/op 1720 B/op 16 allocs/op +BenchmarkWebhook_echotron-16 586056 2051 ns/op 1720 B/op 16 allocs/op +BenchmarkWebhook_echotron-16 598456 2049 ns/op 1720 B/op 16 allocs/op PASS -ok github.com/lukaszraczylo/go-telegram/test/benchmarks 241.963s -? github.com/lukaszraczylo/go-telegram/test/benchmarks/shared [no test files] +ok github.com/lukaszraczylo/go-telegram/test/benchmarks 242.858s