2014-09-05 14 views
6

Mam ten tekst, który chciałbym wprowadzić do plasterka bajtów:Tworzenie kawałek bajt ze znanym ciągiem tekstowym, w Golang

s := "There are these two young fish swimming along and they happen to meet an older fish swimming the other way" 

Jeśli piszę

b := []byte("There are these two young fish swimming along and they happen to meet an older fish swimming the other way") 

Jak rozumiem , w czasie wykonywania tego wola:

  1. utworzyć ciąg z wartościami w pamięci
  2. stworzyć kawałek bajtowy
  3. skopiować zawartość ciąg do plasterka bajtów (realokacji w razie potrzeby)

mogę przekonwertować każdy z ciągów znaków na ich odpowiedniki ASCII i stworzyć kawałek bajtowy bezpośrednio:

b := []byte{84, 104, ... } 

Chociaż jest to mało czytelne.

Rozumiem, że przykład tutaj jest trochę trywialny i większość komputerów może to zrobić w błysku, ale jestem ciekaw tego. Czy kompilator interpretuje []byte("blah") i przekształca go w wydajny kawałek bajta w czasie kompilacji? Czy najlepsze rozwiązanie zmieniłoby się, gdyby ciąg zawierał znaki spoza ASCII?

+1

Czy te konwersje są częścią twojej najbardziej wewnętrznej pętli obliczeniowej? Czy to wąskie gardło pojawia się w profilowaniu? Czy GC jest wolna, ponieważ generuje się zbyt dużo takich konwersji? Jeśli nie: po co zawracać sobie głowę? – Volker

+0

"Czy najlepsze rozwiązanie zmieniłoby się, gdyby ciąg zawierał znaki spoza ASCII?" No. Go source to utf8; rzeczy takie jak 'for _, chr: = range str {...}' uchwyt pętli utf8; Twój program prawdopodobnie nie będzie musiał robić żadnych specjalnych przepisów, aby obsłużyć utf-8. – twotwotwo

+1

Nie myśl, że to "ponowne przydzielenie w razie potrzeby", ponieważ już wie, ile bajtów jest w ciągu znaków, więc może pobrać wystarczającą ilość pamięci z góry. Wypisanie bajtów wydaje się bardzo złym pomysłem (sprawia, że ​​kod źródłowy jest nieprzyjemny) i nie jestem pewien, czy jest on wykonywany nawet nieskończenie wydajniej; ponieważ plastry bajtów są zmienne, bajty mogą nadal wymagać skopiowania z stałej ziemi do pamięci sterty. Ponadto, jak mówi Volker, wszelkie nanosekundy spędzone na kopiowaniu podczas uruchamiania nie są wielkim problemem. – twotwotwo

Odpowiedz

3

Go osadza ciąg w programie wykonywalnym jako literał łańcuchowy. Konwertuje literał łańcuchowy na bajtowy w czasie wykonywania przy użyciu funkcji runtime.stringtoslicebyte.

2

Jeśli zainicjalizujesz zmienną []byte ze stałego łańcucha, wygląda na to, że kompilator jest wystarczająco inteligentny, aby nie tworzyć pośredniego łańcucha: zamiast tego tablica tylna dla segmentu bajtowego jest inicjowana bezpośrednio z danych statycznych, zamiast konstruować najpierw zmienna łańcuchowa.

Istnieje kopia danych, ale należy się tego spodziewać podczas konstruowania typu zmiennego.

+0

Odniesienie do tego, gdzie to zobaczyłeś (na podstawie "wygląda jak") byłoby pomocne tutaj. – seh

+1

Było to od sprawdzenia asemblera wygenerowanego przez kompilator. –