Pull to refresh

Comments 5

Если говорить по НЕ типизированный json (когда структура заранее неизвестна и разбор идет в interface{} ) могу порекомендовать вот этот модуль
Ну и ещё одно замечание. Если, скажем, декодирование ввода-вывода — это 10% ваших затрат процессорных ресурсов, то оптимизация на 10% даёт… 1%. С ценой в новую зависимость в вашем проекте.
Да, но там 10% — это самый маленький возможный прирост. Если Вы взглянете на бенчмарки, то увидите и 5x и 10x ускорение. В среднем примерно 2x — но всё, конечно же, зависит от конкретного случая. Да и зависимость одна меняется на другую (не спорю — потенциально, менее стабильную).

Код


func (m *Some) Reset()      { *m = Some{} } // очень грубо

не приводит к повторному выделению памяти. В этом легко убедиться:


package main

type Some struct {
     A int
     B string
}

// go:noinline
func (s *Some) Reset() {
    *s = Some{}
}

func main() {
    s := &Some{}
    s.Reset()
}

далее


go tool compile -S t.go
...
"".(*Some).Reset t=1 size=29 args=0x8 locals=0x0
        0x0000 00000 (t.go:9)   TEXT    "".(*Some).Reset(SB), $0-8
        0x0000 00000 (t.go:9)   NOP
        0x0000 00000 (t.go:9)   NOP
        0x0000 00000 (t.go:9)   FUNCDATA        $0, gclocals·87d20ce1b58390b294df80b886db78bf(SB)
        0x0000 00000 (t.go:9)   FUNCDATA        $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x0000 00000 (t.go:10)  MOVQ    "".s+8(FP), AX
        0x0005 00005 (t.go:10)  MOVQ    $0, (AX)
        0x000c 00012 (t.go:10)  MOVQ    $0, 8(AX)
        0x0014 00020 (t.go:10)  MOVQ    $0, 16(AX)
        0x001c 00028 (t.go:11)  RET

(то есть, структура s просто обнуляется, либо таким образом, либо вызовом duff device)

Очень интересно. Не думал, что всё так грамотно.

Но как быть если

package main

type Some struct {
    A []byte // LargeSlice
    B []byte // VeryLargeSlice
}

// go:noinline
func (s *Some) Reset() {
    *s = Some{}
}

func main() {
    s := &Some{
        A: make([]byte, 0, 100),
        B: make([]byte, 0, 1000),
    }
    s.Reset()
}


"".(*Some).Reset t=1 size=34 args=0x8 locals=0x0
        0x0000 00000 (some.go:9)        TEXT    "".(*Some).Reset(SB), $0-8
        0x0000 00000 (some.go:9)        NOP
        0x0000 00000 (some.go:9)        NOP
        0x0000 00000 (some.go:9)        FUNCDATA        $0, gclocals·87d20ce1b58390b294df80b886db78bf(SB)
        0x0000 00000 (some.go:9)        FUNCDATA        $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x0000 00000 (some.go:10)       MOVQ    "".s+8(FP), DI
        0x0005 00005 (some.go:10)       TESTB   AL, (DI)
        0x0007 00007 (some.go:10)       XORPS   X0, X0
        0x000a 00010 (some.go:10)       ADDQ    $-16, DI
        0x000e 00014 (some.go:10)       DUFFZERO        $288
        0x0021 00033 (some.go:11)       RET


Попробуй пойми. DUFFZERO обнуляет память. Я так понимаю, что оба слайса сгорают в печке GC, что по логике приведённого кода правильно. Вопрос в том, как подменить (в идеале) Reset на свой, или (не так уж и идеально) если делать s.A = s.A[:0], то куда денется слайс после Reset? Сгорит. Думаю, что сгорит.

Впрочем затрагиваемые вопросы очень специфичны и в среднем случае не имеют значения.
Sign up to leave a comment.

Articles