J'ai ce code qui est censé ne pas être alloué du tout, mais pour une raison quelconque, c'est le cas. Comme le dit le benchmark, 2 allocations ont lieu par opération.
Quelles lignes de la fonction sont allouées ? Pourquoi?
Caractéristiques :
func (vi *VarInt /* int32 */) Read(input io.Reader) error { var ( b byte buf = unsafe.Slice(&b, 1) shift int value uint32 ) for { _, err := io.ReadFull(input, buf) if err != nil { return err } value |= (uint32(b) & 0b01111111) << shift if (b & 0b10000000) == 0 { *vi = VarInt(value) return nil } shift += 7 if shift >= 32 { return ErrVarIntTooLong } } } func (vi *VarInt /* int32 */) Write(output io.Writer) error { var ( varint [5]byte uvalue = uint32(*vi) x int ) for ; ; x++ { vb := uint8(uvalue) if (vb & 0b10000000) == 0 { varint[x] = vb break } varint[x] = (vb & 0b01111111) | 0b10000000 uvalue >>= 7 } _, err := output.Write(varint[:x+1]) if err != nil { return err } return nil }
Référence :
func BenchmarkVarInt(b *testing.B) { var buf bytes.Buffer buf.Grow(5) b.ResetTimer() for i := 0; i < b.N; i++ { vi := (VarInt)(i) vi.Write(&buf) vi.Read(&buf) buf.Reset() } }
Je voulais buf
切片以某种方式逃逸,但我不知道如何逃逸,因为据我了解,在这种情况下切片是在堆栈上分配的结构,它将指向变量 b
作为其数据。我尝试将表达式 unsafe.Slice(&b, 1)
更改为 (*[1]byte)(unsafe.Pointer(&b))[:]
mais ça n’a rien changé.
Lorsqu'une valeur est encadrée dans une interface, elle est toujours considérée comme pouvant être évacuée - même si la valeur n'est jamais utilisée en dehors de la pile d'appels, Go arrêtera d'analyser à ce stade et pensera que quelqu'un aurait pu la récupérer de l'adresse, la valeur doit être placée sur le tas.
Depuis Read
采用 io.Reader
和 Write
采用 io.Writer
,因此 buf
(这是传递给这两个函数的 bytes.Buffer
) doit être échappé.
Même si vous faites en sorte que ces fonctions prennent des types concrets bytes.Buffer
(您可能不想要),但这还不够,因为 Read
调用 io.ReadFull
,它再次采用 io.Reader
. Vous devez travailler plus dur que cela pour obtenir cette dispense.
En passant, pour Read
中的其他问题,有一个更简单的解决方案,不需要任何 unsafe.Slice
恶作剧:只需将 var b byte
替换为 var b [1]byte
(这正是 内存中相同),将b[:]
传递给ReadFull
,并在其他使用b
的地方使用b[0]
.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!