mweerden: NT został zaprojektowany dla wielu użytkowników od pierwszego dnia, więc nie jest to tak naprawdę powód. Jednak masz rację co do tego, że tworzenie procesów odgrywa mniejszą rolę w NT niż w Uniksie, ponieważ NT, w przeciwieństwie do Uniksa, faworyzuje wielowątkowość nad wieloprocesowość.
Rob, to prawda, że fork jest stosunkowo tani, gdy używa się COW, ale w rzeczywistości po fork jest przeważnie wykonywany przez exec. Ponadto program exec musi załadować wszystkie obrazy. Dlatego omawianie działania widelca jest tylko częścią prawdy.
Omawiając szybkość tworzenia procesów, prawdopodobnie dobrym pomysłem jest rozróżnienie między NT i Windows / Win32. Jeśli chodzi o NT (czyli samo jądro), nie sądzę, aby tworzenie procesów (NtCreateProcess) i wątków (NtCreateThread) było znacznie wolniejsze niż na przeciętnym Uniksie. Może się trochę więcej działo, ale nie widzę tutaj głównej przyczyny różnicy w wydajności.
Jeśli jednak spojrzysz na Win32, zauważysz, że dodaje on sporo narzutów do tworzenia procesów. Po pierwsze, wymaga powiadomienia CSRSS o utworzeniu procesu, który obejmuje LPC. Wymaga dodatkowego załadowania przynajmniej kernel32 i musi wykonać szereg dodatkowych czynności księgowych, które należy wykonać, zanim proces zostanie uznany za pełnoprawny proces Win32. I nie zapominajmy o wszystkich dodatkowych obciążeniach wynikających z analizowania manifestów, sprawdzania, czy obraz wymaga podkładki zgodności, sprawdzania, czy obowiązują zasady ograniczeń oprogramowania, yada yada.
To powiedziawszy, widzę ogólne spowolnienie w sumie tych wszystkich drobiazgów, które należy zrobić, oprócz surowego tworzenia procesu, przestrzeni VA i początkowego wątku. Ale jak powiedziano na początku - ze względu na faworyzowanie wielowątkowości nad wielozadaniowością, jedynym oprogramowaniem, które jest poważnie dotknięte tym dodatkowym kosztem, jest słabo przeportowane oprogramowanie Unix. Chociaż sytuacja ta zmienia się, gdy oprogramowanie takie jak Chrome i IE8 nagle odkrywa na nowo zalety przetwarzania wieloprocesowego i zaczyna często uruchamiać i przerywać procesy ...
Unix posiada wywołanie systemowe „fork”, które „dzieli” bieżący proces na dwie części i daje ci drugi proces, identyczny z pierwszym (modulo powrót z wywołania fork). Ponieważ przestrzeń adresowa nowego procesu jest już uruchomiona i działa, powinno to być tańsze niż wywołanie `` CreateProcess '' w systemie Windows i załadowanie obrazu exe, powiązanych bibliotek dll itp.
W przypadku rozwidlenia system operacyjny może używać semantyki „kopiuj przy zapisie” dla stron pamięci powiązanych z obydwoma nowymi procesami, aby zapewnić, że każdy z nich otrzyma własną kopię stron, które następnie modyfikuje.
źródło
Dodając do tego, co powiedział JP: większość narzutów należy do uruchamiania Win32 dla procesu.
Jądro Windows NT faktycznie obsługuje rozwidlenie COW. Używa ich SFU (środowisko Microsoft UNIX dla Windows). Jednak Win32 nie obsługuje rozwidlenia. Procesy SFU nie są procesami Win32. SFU jest ortogonalne do Win32: oba są podsystemami środowiska zbudowanymi na tym samym jądrze.
Oprócz wywołań LPC poza procesem
CSRSS
, w XP i nowszych występuje wywołanie poza procesem do silnika zgodności aplikacji w celu znalezienia programu w bazie danych zgodności aplikacji. Ten krok powoduje wystarczające obciążenie, że firma Microsoft udostępnia opcję zasad grupy, aby wyłączyć silnik zgodności w WS2003 ze względu na wydajność.Biblioteki środowiska wykonawczego Win32 (kernel32.dll itp.) Również wykonują wiele odczytów rejestru i inicjalizacji podczas uruchamiania, które nie mają zastosowania do procesów UNIX, SFU lub natywnych.
Tworzenie procesów natywnych (bez podsystemu środowiska) jest bardzo szybkie. SFU robi dużo mniej niż Win32 przy tworzeniu procesów, więc jego procesy są również szybkie w tworzeniu.
AKTUALIZACJA NA 2019: dodaj LXSS: podsystem Windows dla systemu Linux
Zastąpienie SFU w Windows 10 to podsystem środowiska LXSS. Jest to tryb 100% jądra i nie wymaga żadnego IPC, które nadal ma Win32. Syscall dla tych procesów jest kierowany bezpośrednio do lxss.sys / lxcore.sys, więc fork () lub inny proces tworzący wywołanie kosztuje łącznie tylko 1 wywołanie systemowe dla twórcy. [Obszar danych zwany instancją] śledzi wszystkie procesy LX, wątki i stan środowiska wykonawczego.
Procesy LXSS są oparte na procesach natywnych, a nie procesach Win32. Wszystkie elementy specyficzne dla Win32, takie jak silnik zgodności, nie są w ogóle zaangażowane.
źródło
Oprócz odpowiedzi Roba Walkera: Obecnie masz takie rzeczy, jak Native POSIX Thread Library - jeśli chcesz. Ale przez długi czas jedynym sposobem na „delegowanie” pracy w świecie unixowym było użycie fork () (i nadal jest preferowane w wielu, wielu okolicznościach). np. jakiś serwer gniazd
Dlatego implementacja fork musiała być szybka iz biegiem czasu wprowadzono wiele optymalizacji. Microsoft poparł CreateThread, a nawet włókna, zamiast tworzyć nowe procesy i używać komunikacji międzyprocesowej. Myślę, że porównywanie CreateProcess z forkiem jest niesprawiedliwe, ponieważ nie są one wymienne. Prawdopodobnie bardziej odpowiednie jest porównanie fork / exec z CreateProcess.źródło
Myślę, że kluczem do tej sprawy jest historyczne wykorzystanie obu systemów. Windows (i wcześniej DOS) były pierwotnie systemami dla jednego użytkownika dla komputerów osobistych . W związku z tym systemy te zazwyczaj nie muszą cały czas tworzyć wielu procesów; (bardzo) mówiąc prosto, proces jest tworzony tylko wtedy, gdy zażąda tego jeden samotny użytkownik (a my, ludzie, nie działamy bardzo szybko, mówiąc względnie).
Systemy oparte na Uniksie były pierwotnie systemami i serwerami dla wielu użytkowników. Szczególnie w przypadku tych ostatnich nierzadko zdarza się, że procesy (np. Demony poczty lub http) rozdzielają procesy w celu obsługi określonych zadań (np. Obsługi jednego połączenia przychodzącego). Ważnym czynnikiem w tym jest tania
fork
metoda (która, jak wspomniał Rob Walker ( 47865 ), początkowo wykorzystuje tę samą pamięć dla nowo utworzonego procesu), która jest bardzo przydatna, ponieważ nowy proces natychmiast otrzymuje wszystkie potrzebne informacje.Jest oczywiste, że przynajmniej historycznie potrzeba szybkiego tworzenia procesów przez systemy Unix jest znacznie większa niż w przypadku systemów Windows. Myślę, że nadal tak jest, ponieważ systemy oparte na Uniksie są nadal bardzo zorientowane na procesy, podczas gdy Windows, ze względu na swoją historię, był prawdopodobnie bardziej zorientowany na wątki (wątki są przydatne do tworzenia responsywnych aplikacji).
Zastrzeżenie: w żadnym wypadku nie jestem ekspertem w tej sprawie, więc wybacz mi, jeśli się pomyliłem.
źródło
Uh, wydaje się, że dzieje się wiele usprawiedliwień typu „tak jest lepiej”.
Myślę, że ludzie mogliby skorzystać na przeczytaniu „Showstopper”; książka o rozwoju Windows NT.
Głównym powodem, dla którego usługi działają jako biblioteki DLL w jednym procesie w systemie Windows NT, było to, że były zbyt wolne jako oddzielne procesy.
Jeśli upadłeś i zabrudziłeś, przekonasz się, że problem stanowi strategia ładowania biblioteki.
W systemach Unices (ogólnie) segmenty kodu bibliotek współużytkowanych (DLL) są faktycznie współużytkowane.
Windows NT ładuje kopię biblioteki DLL na proces, ponieważ manipuluje segmentem kodu biblioteki (i segmentem kodu wykonywalnego) po załadowaniu. (Mówi mu, gdzie są twoje dane?)
Skutkuje to segmentami kodu w bibliotekach, których nie można ponownie wykorzystać.
Tak więc tworzenie procesu NT jest w rzeczywistości dość kosztowne. Z drugiej strony sprawia, że DLL nie ma znacznego zapisu w pamięci, ale jest szansą na problemy z zależnościami między aplikacjami.
Czasami w inżynierii opłaca się cofnąć się i powiedzieć: „Teraz, gdybyśmy mieli to zaprojektować tak, by było do niczego, jak by to wyglądało?”
Pracowałem z wbudowanym systemem, który był kiedyś dość temperamentny i pewnego dnia spojrzałem na niego i zdałem sobie sprawę, że to magnetron wnękowy z elektroniką w komorze mikrofalowej. Potem zrobiliśmy to dużo bardziej stabilnym (i mniej jak kuchenka mikrofalowa).
źródło
Krótka odpowiedź brzmi: „warstwy oprogramowania i komponenty”.
Architektura Windows SW ma kilka dodatkowych warstw i komponentów, które nie istnieją w Uniksie lub są uproszczone i obsługiwane wewnątrz jądra w Uniksie.
W Uniksie, fork i exec to bezpośrednie wywołania jądra.
W systemie Windows API jądra nie jest używane bezpośrednio, na jego szczycie znajduje się win32 i pewne inne komponenty, więc tworzenie procesu musi przejść przez dodatkowe warstwy, a następnie nowy proces musi się uruchomić lub połączyć się z tymi warstwami i komponentami.
Od dłuższego czasu badacze i korporacje próbują rozbić Uniksa w dość podobny sposób, zwykle opierając swoje eksperymenty na jądrze Mach ; dobrze znanym przykładem jest OS X .. Jednak za każdym razem, gdy próbują, robi się to tak wolno, że przynajmniej częściowo scalają elementy z powrotem do jądra na stałe lub w celu wysyłki produkcyjnej.
źródło
Ponieważ wydaje się, że w niektórych odpowiedziach istnieje uzasadnienie dla MS-Windows, np
Spójrzmy teraz na fakty, jaka jest różnica w wydajności?
Dane podsumowano z http://www.bitsnbites.eu/benchmarking-os-primitives/ .
Ponieważ stronniczość jest nieunikniona, podsumowując, zrobiłem to na korzyść sprzętu MS-Windows
w większości testów i7 8 core 3.2GHz. Z wyjątkiem Raspberry-Pi z Gnu / Linux
Uwagi: W Linuksie
fork
jest szybsza metoda niż preferowana metoda MS-WindowCreateThread
.Liczby operacji typu tworzenia procesów (ponieważ trudno jest zobaczyć wartość dla Linuksa na wykresie).
W kolejności według szybkości od najszybszej do najwolniejszej (liczby oznaczają czas, mała oznacza lepszą).
Liczby dla innych pomiarów
źródło
Wszystko to plus fakt, że na komputerze z Winem najprawdopodobniej włączy się oprogramowanie antywirusowe podczas CreateProcess ... To zwykle największe spowolnienie.
źródło
Warto również zauważyć, że model zabezpieczeń w systemie Windows jest znacznie bardziej skomplikowany niż w systemach operacyjnych opartych na systemie UNIX, co zwiększa obciążenie podczas tworzenia procesów. Jeszcze jeden powód, dla którego wielowątkowość jest preferowana od wieloprocesowości w systemie Windows.
źródło
fork()