Я чув, що створення нового процесу у вікні Windows дорожче, ніж у Linux. Це правда? Чи може хтось пояснити технічні причини, чому це дорожче, та надати якісь історичні причини дизайнерських рішень, що стоять за цими причинами?
Я чув, що створення нового процесу у вікні Windows дорожче, ніж у Linux. Це правда? Чи може хтось пояснити технічні причини, чому це дорожче, та надати якісь історичні причини дизайнерських рішень, що стоять за цими причинами?
Відповіді:
mweerden: NT був розроблений для багатокористувацьких з першого дня, тому це насправді не є причиною. Однак ви маєте рацію, що створення процесів відіграє менш важливу роль у NT, ніж для Unix, оскільки NT, на відміну від Unix, сприяє багатопотоковій роботі над багатопроцесорними процесами.
Роб, це правда, що вилка є відносно дешевою, коли використовується COW, але, по суті, за виделкою в основному слідує exec. І exec також повинен завантажувати всі зображення. Тому обговорення продуктивності вилки є лише частиною правди.
Обговорюючи швидкість створення процесів, можливо, непогано розрізняти NT та Windows / Win32. Що стосується NT (тобто самого ядра), я не думаю, що створення процесів (NtCreateProcess) та створення потоків (NtCreateThread) значно повільніше, ніж у середньому Unix. Можливо, буде трохи більше, але я не бачу основної причини для різниці в продуктивності.
Якщо ви подивитеся на Win32, то помітите, що це створює досить багато накладних витрат на створення процесів. Для одного, він вимагає повідомляти CSRSS про створення процесу, що передбачає LPC. Для цього потрібно додатково завантажувати щонайменше kernel32, і він повинен виконати ряд додаткових робіт із бухгалтерського обліку, які необхідно виконати до того, як процес буде вважатися повноцінним процесом Win32. І не будемо забувати про всі додаткові накладні витрати, накладені на аналіз маніфестів, перевірку того, чи потрібне зображення суцільність сумісності, перевірку, чи застосовуються політики обмеження програмного забезпечення, yada yada.
Це означає, що я бачу загальне уповільнення у сумі всіх тих дрібниць, які потрібно зробити, крім додаткового створення процесу, простору VA та початкової нитки. Але, як було сказано на початку - через перевагу багатопотокової роботи над багатозадачністю, єдиним програмним забезпеченням, яке серйозно постраждало від цих додаткових витрат, є погано перенесене програмне забезпечення Unix. Хоча ця ситуація змінюється, коли програмне забезпечення, як Chrome та IE8, раптом знову відкриває переваги багатопроцесорних процесів і починає часто запускати та перебирати процеси ...
У Unix є системний виклик "fork", який "розбиває" поточний процес на два і дає вам другий процес, ідентичний першому (по модулю повернення з виклику вилки). Оскільки адресний простір нового процесу вже працює та працює, це повинно бути дешевше, ніж викликати "CreateProcess" у Windows та завантажувати зображення EXE, пов'язані dll тощо.
У випадку з форками ОС може використовувати семантику "копіювати на запис" для сторінок пам'яті, пов'язаних з обома новими процесами, щоб гарантувати, що кожна з них отримає свою власну копію сторінок, які вони згодом змінюють.
Додавши до сказаного JP: більша частина накладних витрат належить запуску Win32 для цього процесу.
Ядро Windows NT насправді підтримує вилку COW. Використовує їх SFU (середовище Microsoft UNIX для Windows). Однак Win32 не підтримує форк. Процеси SFU не є процесами Win32. SFU є ортогональним для Win32: вони обидві підсистеми середовища, побудовані на одному ядрі.
Окрім запущених викликів LPC до CSRSS
, у XP та пізніших випадках відбувається виклик поза процесом до двигуна сумісності програм, щоб знайти програму в базі даних сумісності програм. Цей крок спричинює достатньо накладних витрат, що Microsoft надає можливість групової політики відключити механізм сумісності на WS2003 з міркувань продуктивності.
Бібліотеки виконання Win32 (kernel32.dll і т.д.) також роблять багато зчитування реєстру та ініціалізацію при запуску, які не застосовуються до UNIX, SFU або нативних процесів.
Рідні процеси (без підсистеми середовища) створюються дуже швидко. SFU робить набагато менше, ніж Win32 для створення процесів, тому його процеси також швидко створюються.
ОНОВЛЕННЯ НА 2019 рік: додайте LXSS: підсистему Windows для Linux
Заміна SFU для Windows 10 - це підсистема середовища LXSS. Він у 100% режимі ядра і не вимагає жодного з тих IPC, які Win32 продовжує мати. Syscall для цих процесів спрямований безпосередньо на lxss.sys / lxcore.sys, тому fork () або інший процес створення виклику коштує лише 1 системний виклик для творця, всього. [Область даних, що називається екземпляр], відстежує всі процеси LX, потоки та стан виконання LX.
Процеси LXSS засновані на нативних процесах, а не на процесах Win32. Усі специфічні для Win32 речі, такі як двигун сумісності, взагалі не займаються.
На додаток до відповіді Роба Уокера: У наш час у вас є такі речі, як Native POSIX Thread Library - якщо хочете. Але тривалий час єдиним способом "делегувати" роботу у світі Unix було використання fork () (і це все ще вважається кращим за багатьох, багатьох обставин). наприклад, якийсь сервер сокетів
socket_accept () вилка () якщо (дитина) handleRequest () ще goOnBeingParent ()Тому реалізація вилки мала бути швидкою, і з часом було впроваджено багато оптимізацій. Microsoft схвалила CreateThread або навіть волокна замість створення нових процесів та використання міжпроцесорної комунікації. Я думаю, що не справедливо порівнювати CreateProcess з виделкою, оскільки вони не взаємозамінні. Напевно, більш доцільно порівняти fork / exec з CreateProcess.
Ключовим у цьому питанні є історичне використання обох систем, я думаю. Windows (і DOS до цього) спочатку були однокористувацькими системами для персональних комп'ютерів. Таким чином, ці системи зазвичай не повинні створювати багато процесів постійно; (дуже) просто кажучи, процес створюється лише тоді, коли цей одинокий користувач вимагає цього (а ми, люди, не дуже швидко, відносно кажучи).
Системи на базі Unix спочатку були багатокористувацькими системами та серверами. Особливо для останніх не рідкість наявність процесів (наприклад, пошта або http-демон), які розділяють процеси для обробки конкретних завдань (наприклад, піклування про одне вхідне з'єднання). Важливим фактором цього є дешевий fork
метод (який, як зазначав Роб Уокер ( 47865 ), спочатку використовує ту саму пам'ять для новоствореного процесу), що дуже корисно, оскільки новий процес одразу має всю необхідну йому інформацію.
Зрозуміло, що принаймні історично потреба у системах на базі Unix у швидкому створенні процесів набагато більша, ніж для систем Windows. Я думаю, що це все ще так, тому що системи на базі Unix все ще дуже орієнтовані на процеси, тоді як Windows, завдяки своїй історії, ймовірно, була більш орієнтована на потоки (теми корисні для створення чутливих додатків).
Відмова: Я аж ніяк не експерт у цьому питанні, тому вибачте мене, якщо я помилився.
Ну, схоже, існує багато виправдань, що "краще так".
Я думаю, що люди могли б отримати користь від читання "Showstopper"; книга про розробку Windows NT.
Вся причина, по якій служби працюють як DLL в одному процесі в Windows NT, полягала в тому, що вони були занадто повільними, як окремі процеси.
Якщо ви забруднилися, ви побачите, що проблема стратегії завантаження бібліотеки.
У Unices (загалом) сегменти коду спільних бібліотек (DLL) фактично поділяються.
Windows NT завантажує копію DLL за процес, оскільки він маніпулює сегментом коду бібліотеки (та виконуваним сегментом коду) після завантаження. (Розповідає, де ваші дані?)
Це призводить до сегментів коду в бібліотеках, які не можна використовувати повторно.
Отже, процес створення NT насправді досить дорогий. І з нижньої сторони, це робить DLL не помітною економією пам’яті, а шансом для проблем між додатками.
Іноді в інженерії платять, щоб відступити назад і сказати, "зараз, якби ми збиралися спроектувати це, щоб насправді смоктати, як би це виглядало?"
Я працював із вбудованою системою, яка була досить темпераментною колись, і одного разу переглянула це і зрозуміла, що це магнетрон з порожниною, з електронікою в мікрохвильовій порожнині. Після цього ми зробили це набагато стійкішим (і менш схожим на мікрохвильову піч).
Архітектура Windows SW має кілька додаткових шарів і компонентів, які не існують на Unix або спрощені та обробляються всередині ядра в Unix.
У Unix fork та exec - це прямі дзвінки до ядра.
У Windows API ядра не використовується безпосередньо, поверх нього є win32 та деякі інші компоненти, тому створення процесу повинно проходити через додаткові шари, а потім новий процес повинен запускатися або підключатися до цих шарів і компонентів.
Довгий час дослідники та корпорації намагалися розбити Unix нечітко схожим способом, зазвичай грунтуючись на своїх експериментах на ядрі Маха ; добре відомий приклад є OS X. . Щоразу, коли вони намагаються, це стає настільки повільним, що в кінцевому підсумку вони принаймні частково об'єднують шматки назад в ядро або назавжди, або на виробничі відвантаження.
Оскільки, здається, є деякі обґрунтування MS-Windows у деяких відповідях, наприклад
Дані, зафіксовані на веб-сайті http://www.bitsnbites.eu/benchmarking-os-primitive/ .
Оскільки упередження неминуче, підбиваючи підсумки, я зробив це на користь обладнання MS-Windows
для більшості тестів i7 8 ядерного 3,2 ГГц. За винятком Raspberry-Pi під керуванням Gnu / Linux
Примітки. У Linux, fork
швидше, ніж у MS-Window кращий метод CreateThread
.
У порядку швидкості найшвидший на повільний (цифри - час, малі - краще).
Крім того, на тому, що на машині Win, швидше за все, антивірусне програмне забезпечення запуститься під час CreateProcess ... Це, як правило, найбільше уповільнення.
Варто також зазначити, що модель безпеки в Windows набагато складніше, ніж в ОС на базі Unix, що додає багато накладних витрат під час створення процесів. Ще одна причина, чому багатопотокове читання віддають перевагу багатопроцесорному обробці в Windows.
fork()