2013-08-01 11 views
8

Mamy dużą bazę kodów, która z powodzeniem używała boost :: signals od lat. Niedawno przestawiliśmy się na zwiększenie v1.54 i zdecydowaliśmy, że ponieważ sygnały boost :: były przestarzałe, przełączaliśmy się na boost :: signals2.Skompiluj razy z boostem :: signals2 very slow

Problemem, który widzimy, jest to, że czasy kompilacji są przerażające. Na przykład mały plik .cpp zajmie teraz ponad 20 sekund, w którym był używany 4.

Podobnie, jedna z naszych bibliotek (duża), która trwała około 10 minut do wygenerowania teraz, zajmuje nawet godzinę. Przeszukałem wszędzie dokumentację, jak to poprawić poprzez prekompilowane nagłówki, makra itp., Ale jeszcze nie znalazłem niczego, co znacznie poprawiłoby sytuację.

Przeglądanie cl.exe w procmon pokazuje ogromną ilość IO w bibliotekach boost :: signals2 i mpl.

Nie potrzebujemy zabezpieczenia gwintu, które zapewniają sygnały2, w tym momencie jesteśmy blisko wyciągania wtyczki "aktualizacji" i powrotu do sygnałów. Czy ktokolwiek ma jakieś sugestie lub doświadczenie z tym, zanim się poddamy?

Używamy VS2012 z dużą ilością pamięci RAM/dysku/etc.

+1

Czy używasz prekompilowanych nagłówków? –

+8

Signals2 używa szablonów variadic, są one emulowane w VS2012 po znacznych kosztach. Naprawiono w VS2013. Pomiędzy Boostem dostosowującym się do tego i lądowaniem VS2013 na pulpicie, daj mu garść miesięcy. –

+0

@HansPassant Dzięki za informację, nie brałem tego pod uwagę. Biorąc pod uwagę, że nie możemy czekać, aż VS2013 jest najlepszym sposobem działania, aby powrócić do biblioteki sygnałów według ciebie? Tak jak obecnie, kod nie nadaje się do użytku ze względu na wolne czasy kompilacji. – pennyowe

Odpowiedz

6

W projekcie, nad którym pracowałem, wszystkie sygnały sygnałów doładowania zostały spłaszczone w taki sposób, że deklaracje forward są wystarczające. To znacznie skraca czas kompilacji, ponieważ definicje signal2 są analizowane tylko wtedy, gdy są rzeczywiście potrzebne. Zamiast dostarczania publicznego elementu boost::signals2::signal, klasa ma prywatny element std :: unique_pointer i zapewnia publiczną funkcję connectToX, która zwraca obiekt std :: unique_pointer.

class Subject { 
public: 
    boost::signals2::signal<void (int)> valueChanged; 
    void setValue(int x) { 
     valueChanged(x); 
    } 
}; 

class A { 
public: 
    A(Subject& subject): conn(subject.sig.connect([&](int x) {this->onChange(x);}) {} 
    ~A() {conn.disconnect();} 
private: 
    void onChange(x) {} 

    boost::signals2::connection conn; 
}; 

staje się wtedy tylko do przodu z nagłówka deklaracji i nie zawiera nagłówków signals2 doładowania:

// Header file 
class Subject { 
public: 
    std::unique_ptr<boost::signals2::connection> connect(std::function<void (int)> observer); 

private: 
    class Impl; 
    std::unique_ptr<Impl> mImpl; 
}; 

Klasy nie interesuje sygnałów teraz nie trzeba analizować nagłówki signals2. Warto zauważyć, że z mojego doświadczenia większość czasu nie jest parsowana w kompilatorze, ale w linkerze. każda jednostka kompilacji wykorzystująca sygnały doładowania zawiera wiele instancji funkcji, które generują informacje debugowania i muszą zostać wyeliminowane przez linker na końcu. A biorąc pod uwagę, że łącznik MS jest jednowątkowy i bardzo powolny, to właśnie tam spędza się czas na IO. Dysk SSD zapewnił tutaj dobre przyspieszenie.

+0

Dzięki za te opinie. To bardzo dobry pomysł (choć niefortunne jest, że taki taniec jest konieczny). Nie rozważaliśmy użycia pimpl w naszym przypadku głównie dlatego, że użycie było tak powszechne, że zmiana byłaby znaczna. Inna zmarszczka polega na tym, że klienci sygnałów korzystali czasem z paradygmatu scoped_connection. Obecnie aktualizujemy nasze pliki projektów do VS2013, więc będę zainteresowany, czy powyższe komentarze @Hans Passant są prawdziwe. – pennyowe

+0

Tak, pimpl sprawia, że ​​używanie sygnałów jest bardziej skomplikowane, szczególnie dlatego, że trzeba zwracać unique_ptrs z połączeniami. Jestem dość zainteresowany wynikami VS2013, chociaż nie pracuję obecnie na platformie Windows. Nie oczekuję zbyt dużej poprawy, ponieważ linker nie został znacznie ulepszony i właśnie tam został wydany nasz czas kompilacji (wraz z pisaniem plików pdb z dużą ilością instancji boost). Możesz użyć cl/Bt + lub link/time +, aby uzyskać pomiary czasu budowy. – Jens