Może to zabrzmieć jako dziwne pytanie, ale w moim dziale mamy problemy z następującą sytuacją:
Pracujemy tutaj nad aplikacją serwerową, która staje się coraz większa, nawet w momencie, gdy rozważamy podzielenie jej na różne części (pliki DLL), dynamiczne ładowanie w razie potrzeby, a następnie rozładowywanie, aby móc obsłużyć problemy z wydajnością.
Ale: funkcje, których używamy, przekazują parametry wejściowe i wyjściowe jako obiekty STL, i jak wspomniano w odpowiedzi na przepełnienie stosu , jest to bardzo zły pomysł. (Post zawiera kilka ± rozwiązań i hacków, ale nie wszystko wygląda solidnie).
Oczywiście moglibyśmy zastąpić parametry wejściowe / wyjściowe standardowymi typami C ++ i tworzyć obiekty STL z tych, które znajdują się w funkcjach, ale może to powodować spadek wydajności.
Czy można stwierdzić, że jeśli rozważasz zbudowanie aplikacji, która może wzrosnąć tak bardzo, że jeden komputer nie będzie w stanie jej obsługiwać, nie możesz w ogóle używać STL jako technologii?
Więcej informacji na temat tego pytania:
Wydaje się, że istnieją pewne nieporozumienia dotyczące pytania: problem jest następujący:
Moja aplikacja wykorzystuje ogromną wydajność (procesor, pamięć) w celu dokończenia pracy i chciałbym podzielić tę pracę na różne części (ponieważ program jest już podzielony na wiele funkcji), tworzenie bibliotek DLL z mojej aplikacji i umieszczanie niektórych funkcji w tabeli eksportu tych bibliotek nie jest trudne. Spowodowałoby to następującą sytuację:
+-----------+-----------+----
| Machine1 | Machine2 | ...
| App_Inst1 | App_Inst2 | ...
| | |
| DLL1.1 | DLL2.1 | ...
| DLL1.2 | DLL2.2 | ...
| DLL1.x | DLL2.x | ...
+-----------+-----------+----
App_Inst1 to instancja aplikacji zainstalowanej na komputerze Machine1, natomiast App_Inst2 to instancja tej samej aplikacji zainstalowanej na komputerze Machine2.
DLL1.x jest biblioteką DLL zainstalowaną na komputerze Machine1, natomiast DLL2.x jest biblioteką DLL zainstalowaną na komputerze Machine2.
DLLx.1 obejmuje eksportowaną funkcję 1.
DLLx.2 obejmuje funkcję eksportu2.
Teraz na maszynie 1 chciałbym wykonać funkcję 1 i funkcję 2. Wiem, że spowoduje to przeciążenie Machine1, dlatego chciałbym wysłać wiadomość do App_Inst2, prosząc tę instancję aplikacji o wykonanie funkcji 2.
Parametry wejściowe / wyjściowe funkcji1 i funkcji2 są obiektami STL (C ++ Standard Type Library) i regularnie mogę oczekiwać, że klient dokona aktualizacji App_Inst1, App_Inst2, DLLx.y (ale nie wszystkie z nich, klient może zaktualizować Machine1, ale nie Machine2, lub tylko aktualizuj aplikacje, ale nie biblioteki DLL lub odwrotnie, ...). Oczywiście, jeśli interfejs (parametry wejściowe / wyjściowe) ulegnie zmianie, wówczas klient jest zmuszony dokonać kompletnych aktualizacji.
Jednak, jak wspomniano w odnośnym adresie URL StackOverflow, prosta ponowna kompilacja App_Inst1 lub jednej z bibliotek DLL może spowodować rozpad całego systemu, stąd mój oryginalny tytuł tego postu, odradzający użycie STL (Standardowy szablon C ++ Biblioteka) dla dużych aplikacji.
Mam nadzieję, że niniejszym wyjaśniłem niektóre pytania / wątpliwości.
Odpowiedzi:
Jest to klasyczny problem XY.
Twoim prawdziwym problemem są problemy z wydajnością. Jednak twoje pytanie wyjaśnia, że nie przeprowadziłeś profilowania ani innych ocen tego, skąd faktycznie pochodzą problemy z wydajnością. Zamiast tego masz nadzieję, że podzielenie kodu na biblioteki DLL magicznie rozwiąże problem (czego nie zrobi, dla przypomnienia), a teraz martwisz się o jeden aspekt tego nierozwiązania.
Zamiast tego musisz rozwiązać prawdziwy problem. Jeśli masz wiele plików wykonywalnych, sprawdź, który z nich powoduje spowolnienie. W tym momencie upewnij się, że program zajmuje cały czas przetwarzania, a nie źle skonfigurowany sterownik Ethernet lub coś w tym rodzaju. Następnie rozpocznij profilowanie różnych zadań w kodzie. Precyzyjny zegar jest tutaj Twoim przyjacielem. Klasycznym rozwiązaniem jest monitorowanie średniego i najgorszego czasu przetwarzania dla części kodu.
Gdy masz dane, możesz dowiedzieć się, jak poradzić sobie z problemem, a następnie ustalić, gdzie je zoptymalizować.
źródło
Jeśli musisz podzielić oprogramowanie na wiele fizycznych komputerów, musisz mieć jakąś formę serializacji podczas przesyłania danych między komputerami, ponieważ tylko w niektórych przypadkach możesz po prostu wysłać dokładnie ten sam plik binarny między komputerami. Większość metod serializacji nie ma problemów z obsługą typów STL, więc sprawa nie jest czymś, co by mnie martwiło.
Jeśli musisz podzielić aplikację na biblioteki współdzielone (DLL) (zanim zrobisz to ze względu na wydajność, naprawdę powinieneś upewnić się, że rzeczywiście rozwiąże to problemy z wydajnością) przekazywanie obiektów STL może być problemem, ale nie musi tak być. Jak już podałeś łącze, przekazywanie obiektów STL działa, jeśli używasz tego samego kompilatora i tych samych ustawień kompilatora. Jeśli użytkownicy dostarczą biblioteki DLL, możesz nie być w stanie łatwo na to liczyć. Jeśli podasz wszystkie biblioteki DLL i skompilujesz wszystko razem, być może będziesz w stanie na to liczyć, a używanie obiektów STL ponad granicami bibliotek DLL stanie się bardzo możliwe. Nadal musisz uważać na ustawienia kompilatora, aby nie uzyskać wielu różnych hałd, jeśli przejdziesz na własność obiektu, chociaż nie jest to problem specyficzny dla STL.
źródło
Pamięć RAM jest tania, dlatego nieaktywny kod jest tani. Ładowanie i rozładowywanie kodu (szczególnie rozładowywanie) jest delikatnym procesem i jest mało prawdopodobne, aby miało znaczący wpływ na wydajność twoich programów na nowoczesnym sprzęcie stacjonarnym / serwerowym.
Pamięć podręczna jest droższa, ale wpływa tylko na kod, który jest ostatnio aktywny, a nie na kod, który jest nieużywany w pamięci.
Ogólnie rzecz biorąc, programy przerastają komputery z powodu rozmiaru danych lub czasu procesora, a nie rozmiaru kodu. Jeśli rozmiar twojego kodu staje się tak duży, że powoduje poważne problemy, prawdopodobnie prawdopodobnie zastanawiasz się, dlaczego tak się dzieje.
Powinno być w porządku, o ile biblioteki DLL i pliki wykonywalne są zbudowane z tego samego kompilatora i dynamicznie połączone z tą samą biblioteką środowiska wykonawczego C ++. Wynika z tego, że jeśli aplikacja i powiązane z nią biblioteki DLL zostaną zbudowane i wdrożone jako pojedyncza jednostka, nie powinno to stanowić problemu.
Problemem może być budowanie bibliotek przez różne osoby lub ich osobna aktualizacja.
Nie całkiem.
Po rozpoczęciu rozprzestrzeniania aplikacji na wielu komputerach masz cały szereg rozważań dotyczących sposobu przekazywania danych między tymi komputerami. Szczegóły dotyczące tego, czy stosowane są typy STL, czy bardziej podstawowe typy, mogą zostać utracone w hałasie.
źródło
Nie, nie sądzę, aby taki wniosek był następujący. Nawet jeśli twój program jest dystrybuowany na wielu komputerach, nie ma powodu, aby użycie STL wewnętrznie zmusiło cię do użycia go w komunikacji między modułami / procesami.
W rzeczywistości uważam, że od samego początku należy oddzielić projektowanie zewnętrznych interfejsów od implementacji wewnętrznej, ponieważ te pierwsze będą bardziej solidne / trudne do zmiany w porównaniu do tego, co jest używane wewnętrznie
źródło
Nie rozumiesz sedna tego pytania.
Istnieją dwa typy bibliotek DLL. Twój własny i cudzego. „Problem STL” polega na tym, że ty i oni nie korzystacie z tego samego kompilatora. Oczywiście nie stanowi to problemu dla własnej biblioteki DLL.
źródło
Jeśli skompilujesz biblioteki DLL z tego samego drzewa źródłowego w tym samym czasie za pomocą tego samego kompilatora i opcji kompilacji, to będzie działać OK.
Jednak „podzielony na Windows” sposób dzielenia aplikacji na wiele części, z których niektóre nadają się do ponownego użycia, to komponenty COM . Mogą być małe (pojedyncze elementy sterujące lub kodeki) lub duże (IE jest dostępny jako element sterujący COM w pliku mshtml.dll).
W przypadku aplikacji serwerowej prawdopodobnie będzie to miało straszną wydajność; jest to naprawdę wykonalne tylko wtedy, gdy masz aplikację, która przechodzi przez wiele faz w długim okresie czasu, dzięki czemu wiesz, kiedy coś już nie będzie potrzebne. Przypomina mi gry DOS z mechanizmem nakładki.
Poza tym, jeśli twój system pamięci wirtualnej działa poprawnie, poradzi sobie z tym, stronicując nieużywane strony kodowe.
Kup większy komputer.
Nie zapominaj, że przy odpowiedniej optymalizacji laptop może przewyższyć klaster hadoop.
Jeśli naprawdę potrzebujesz wielu systemów, musisz bardzo dokładnie przemyśleć granicę między nimi, ponieważ tam właśnie są koszty serializacji. W tym miejscu powinieneś zacząć szukać frameworków takich jak MPI.
źródło
Pierwsza część ma sens (dzielenie aplikacji na różne maszyny, ze względu na wydajność).
Druga część (ładowanie i rozładowywanie bibliotek) nie ma sensu, ponieważ jest to dodatkowy wysiłek i nie poprawi (naprawdę) rzeczy.
Opisany problem lepiej rozwiązać za pomocą dedykowanych maszyn obliczeniowych, ale nie powinny one działać z tą samą (główną) aplikacją.
Klasyczne rozwiązanie wygląda następująco:
Pomiędzy front-endem a maszynami obliczeniowymi możesz mieć dodatkowe rzeczy, takie jak usługi równoważenia obciążenia i monitorowanie wydajności, a wyspecjalizowane przetwarzanie keeing na dedykowanych maszynach jest dobre do buforowania i optymalizacji przepustowości.
Nie oznacza to w żaden sposób dodatkowego ładowania / wyładowywania bibliotek DLL ani żadnego związku z STL.
Oznacza to, że używaj STL wewnętrznie zgodnie z wymaganiami i szereguj swoje dane między elementami (szereguj bufory protokołu i protokołu oraz rodzaje problemów, które rozwiązują).
To powiedziawszy, z ograniczonymi informacjami, które podałeś, wygląda to jak klasyczny problem xy (jak powiedział @Graham).
źródło