2017-09-06 63 views
10

Większość implementacji std::string (w tym GCC) stosuje optymalizację małych ciągów. Na przykład. dyskutuje o tym answer.Nie ma optymalizacji małych ciągów za pomocą gcc?

Dzisiaj postanowiłem sprawdzić, w którym punkcie napis w skompilowanym przeze mnie kodzie zostanie przeniesiony do sterty. Ku mojemu zaskoczeniu mój kod testowy zdaje się wskazywać, że w ogóle nie ma optymalizacji małych napisów!

Kod:

#include <iostream> 
#include <string> 

using std::cout; 
using std::endl; 

int main(int argc, char* argv[]) { 
    std::string s; 

    cout << "capacity: " << s.capacity() << endl; 

    cout << (void*)s.c_str() << " | " << s << endl; 
    for (int i=0; i<33; ++i) { 
    s += 'a'; 
    cout << (void*)s.c_str() << " | " << s << endl; 
    } 

} 

Wyjście g++ test.cc && ./a.out jest

capacity: 0 
0x7fe405f6afb8 | 
0x7b0c38 | a 
0x7b0c68 | aa 
0x7b0c38 | aaa 
0x7b0c38 | aaaa 
0x7b0c68 | aaaaa 
0x7b0c68 | aaaaaa 
0x7b0c68 | aaaaaaa 
0x7b0c68 | aaaaaaaa 
0x7b0c98 | aaaaaaaaa 
0x7b0c98 | aaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaaaaaa 
0x7b0c98 | aaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0cd8 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 
0x7b0d28 | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 

Zgaduję, że większe pierwszy wskaźnik, tj 0x7fe405f6afb8 jest wskaźnik stosu, a pozostałe z nich wskazują na stercie . Uruchomienie tego wiele razy daje identyczne wyniki, w tym sensie, że pierwszy adres jest zawsze duży, a pozostałe są mniejsze; dokładne wartości zazwyczaj różnią się. Mniejsze adresy zawsze są zgodne ze standardową mocą 2 schematu alokacji, np. 0x7b0c38 figuruje raz, potem 0x7b0c68 figuruje raz, potem 0x7b0c38 dwa razy, a następnie 0x7b0c68 4 razy, potem 0x7b0c98 8 razy itd

Po przeczytaniu odpowiedzi Howarda, przy użyciu maszyny do 64bit, spodziewałem się zobaczyć ten sam adres drukowane dla pierwszych 22 znaków, a tylko wtedy, aby zobaczyć, jak się zmienia.

Czy brakuje mi czegoś?

także, co ciekawe, jeśli skompilować z -O (na każdym poziomie), mam stałą małą wartość wskaźnika 0x6021f8 w pierwszym przypadku, zamiast dużej wartości, a to 0x6021f8 nie zmienia się niezależnie od tego, ile razy Uruchomę program.

Wyjście g++ -v:

Using built-in specs. 
COLLECT_GCC=g++ 
COLLECT_LTO_WRAPPER=/foo/bar/gcc-6.2.0/gcc/libexec/gcc/x86_64-redhat-linux/6.2.0/lto-wrapper 
Target: x86_64-redhat-linux 
Configured with: ../gcc-6.2.0/configure --prefix=/foo/bar/gcc-6.2.0/gcc --build=x86_64-redhat-linux --disable-multilib --enable-languages=c,c++,fortran --with-default-libstdcxx-abi=gcc4-compatible --enable-bootstrap --enable-threads=posix --with-long-double-128 --enable-long-long --enable-lto --enable-__cxa_atexit --enable-gnu-unique-object --with-system-zlib --enable-gold 
Thread model: posix 
gcc version 6.2.0 (GCC) 
+1

'--with-default-libstdcxx-abi = kompatybilny z gcc4" –

+0

@ T.C. Naprawdę? 'gcc4' nie miał małej optymalizacji łańcucha? – SU3

+0

Pomyślałem, że przypomniałem sobie, że małą optymalizację napisów należy umieścić (z powrotem) w języku – xaxxon

Odpowiedz

13

Jeden z flagami jest:

--with-default-libstdcxx-abi=gcc4-compatible 

i gcc4 robi nie support mały ciąg optimzation.


GCC5 zaczął go wspierać. isocpp stany:

Nowa implementacja std :: string jest domyślnie włączona, za pomocą małego optymalizacji ciągów zamiast kopiowanie przy zapisie liczenia odniesienia.

która obsługuje moje roszczenie.

Ponadto Exploring std::string wspomina:

Jak widzimy, starszy libstdC++ narzędzia kopiowanie przy zapisie, a więc to sprawia sens ich nie wykorzystują małą optymalizacji obiektów.

, a następnie zmienia kontekst, gdy GCC5 wchodzi do gry.