Почему go часто хранит данные строк по смещенным адресам - PullRequest
1 голос
/ 07 марта 2020

Я много читал о том, как важно выравнивание значений в памяти, потому что доступ к невыровненным адресам может либо замедлить работу, либо просто не работать вообще, в зависимости от архитектуры ЦП (одна ссылка https://syslog.ravelin.com/go-and-memory-layout-6ef30c730d51). Но потом я заметил, что при создании простой строки в Go она часто хранит строковое значение по неверно выровненному адресу.

Это можно увидеть, выполнив следующий код:

package main

import (
    "fmt"
    "unsafe"
    "reflect"
)

func main() {
    testString:= "testString"

    fmt.Println(fmt.Sprintf("Data is at address %d", ((*reflect.StringHeader)(unsafe.Pointer(&testString))).Data))
}

При запуске на https://play.golang.org/p/d1eX0nP3AgV я получаю:

Data is at address 1140305

1140305 явно не делится на 4 или 8.

Может кто-нибудь объясните, почему Go хранит это значение по смещенному адресу, пожалуйста? Не лучше ли использовать выровненный? Это просто, чтобы не тратить пространство, полагаясь на то, что современные процессоры могут справиться с этим. Или это потому, что уровень виртуальной памяти абстрагирует адрес физической памяти и фактически физический адрес правильно выровнен?

1 Ответ

2 голосов
/ 07 марта 2020

Вы правы, 32-битное значение (например, целое число) должно быть выровнено по 4-байтовой границе, иначе для доступа к нему может потребоваться два обращения к памяти вместо одного. Точно так же 64-битное значение должно быть выровнено по 8-байтовой границе, хотя в 32-битной системе (ie 32 строки данных в память) 4-байтовая граница является адекватной, так как в любом случае требуется два обращения к памяти.

Однако данные строки в Go фактически являются массивом байтов и, следовательно, не имеют требований к выравниванию . То же самое вы найдете, если напечатать адрес строки в C (который очень важен для выравнивания по соображениям эффективности).

Выравнивание довольно просто, как только вы его понимаете, но требует много объяснений , Я написал об этом (для C) на http://devmethodologies.blogspot.com/2013/04/alignment-and-pragma-pack.html.

...