Насколько быстро вызывать len () для среза? - PullRequest
2 голосов
/ 24 сентября 2019

Мне интересно, как быстро получить доступ к len() среза.Если мне нужно несколько раз использовать длину среза, стоит ли сохранять ее в переменной int?Или вызов len() будет оптимизирован так, как если бы к переменной int обращались?(В таком случае нет необходимости хранить длину переменной пользователем.) Спасибо.

Ответы [ 2 ]

2 голосов
/ 25 сентября 2019

Все встроенные функции на самом деле не функции.Это может быть куча других функций или просто одна инструкция asm (как в этом случае).

Вот структура слайса:

type SliceHeader struct {
    Data uintptr // sizeof(uintptr) = 8 byte
    Len  int
    Cap  int
}

Чтобы получить len среза, мы должны получить смещение отуказатель среза.Go-идиоматический вариант выглядит следующим образом:

*(*int)(unsafe.Pointer(uintptr(pointer_to_slice) + 8))

Как видите, выходной код goasm для len (b) равен одной инструкции: https://godbolt.org/z/z0PtMe

var b1 = []byte{1, 2, 3}
var b2 = []byte{4, 5, 6}

func main() {
   l1 := len(b1)

   if len(b2) == l1 {
       println(l1)
   } else {
       println(len(b2))
   }
}

l1 := len(b1)

=

movq "".b1+8(SB), AX // ax == l1

, но для len(b2) == l1 компилятор создает дополнительную переменную:

movq "".b2+8(SB), CX // cx == len(b2) in "if" statement

Итак, мыМожно сделать вывод, что создание новой переменной длины не влияет на производительность.

2 голосов
/ 25 сентября 2019

Вот мое понимание:

Вы можете рассматривать slice как struct, членом которого является length.

Единственное, что делает функция len(), эточитать этот элемент type slice struct, поэтому не нужно беспокоиться о его производительности - это так же быстро, как и чтение length int, которое вы создаете сами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...