Чому створення нового процесу в Windows дорожче, ніж Linux?


101

Я чув, що створення нового процесу у вікні Windows дорожче, ніж у Linux. Це правда? Чи може хтось пояснити технічні причини, чому це дорожче, та надати якісь історичні причини дизайнерських рішень, що стоять за цими причинами?

Відповіді:


68

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, раптом знову відкриває переваги багатопроцесорних процесів і починає часто запускати та перебирати процеси ...


8
За форкелем не завжди йде exec (), а люди дбають про fork () поодинці. Apache 1.3 використовує fork () (без exec) у Linux та потоки в Windows, навіть якщо у багатьох випадках процеси розщеплюються до того, як вони знадобляться та зберігаються в пулі.
Blaisorblade

5
Не забуваючи, звичайно, команду 'vfork', розроблену для описаного вами сценарію "просто викликати exec".
Кріс Хуанг-Лівер

4
Іншим видом програмного забезпечення, яке серйозно впливає на це, є будь-який вид сценаріїв оболонок, що включає координацію декількох процесів. Наприклад, Баш сценарії всередині Cygwin сильно страждають від цього. Розглянемо петлю оболонки, яка породжує багато sed, awk та grep у трубопроводах. Кожна команда породжує процес, і кожна труба породжує нижню частину і новий процес у цій підпакеті. Unix був розроблений з урахуванням такого використання, тому швидке створення процесів залишається нормою.
Dan Molding

5
-1. Смішним є твердження, що програмне забезпечення "погано переноситься", оскільки воно не працює добре на погано розробленій операційній системі, наповненій сукупністю сумісності, що сповільнює створення процесів.
Miles Rout

6
@MilesRout мета перенесення - змінити програмне забезпечення для роботи на новій цільовій системі, враховуючи сильні та слабкі сторони цієї системи. Погане програмне забезпечення з низьким рівнем експлуатації - це програмне забезпечення, яке погано переноситься, незалежно від блоків дорожнього руху, які надає операційна система.
Дизиспірал

28

У Unix є системний виклик "fork", який "розбиває" поточний процес на два і дає вам другий процес, ідентичний першому (по модулю повернення з виклику вилки). Оскільки адресний простір нового процесу вже працює та працює, це повинно бути дешевше, ніж викликати "CreateProcess" у Windows та завантажувати зображення EXE, пов'язані dll тощо.

У випадку з форками ОС може використовувати семантику "копіювати на запис" для сторінок пам'яті, пов'язаних з обома новими процесами, щоб гарантувати, що кожна з них отримає свою власну копію сторінок, які вони згодом змінюють.


22
Цей аргумент справедливий лише тоді, коли ви справді роздвоєні. Якщо ви починаєте новий процес, в Unix вам все одно доведеться розщедритися та виконати. І Windows, і Unix мають копію під час запису. Windows, безумовно, повторно використає завантажений EXE, якщо ви запустите другу копію програми. Я не думаю, що ваше пояснення є правильним, вибачте.
Джоель Спольський

1
Детальніше про exec () та fork () vipinkrsahu.blogspot.com/search/label/system%20programming
webkul

У свою відповідь я додав деякі дані про ефективність. stackoverflow.com/a/51396188/537980 Ви можете бачити, що це швидше.
ctrl-alt-delor

25

Додавши до сказаного 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 речі, такі як двигун сумісності, взагалі не займаються.


16

На додаток до відповіді Роба Уокера: У наш час у вас є такі речі, як Native POSIX Thread Library - якщо хочете. Але тривалий час єдиним способом "делегувати" роботу у світі Unix було використання fork () (і це все ще вважається кращим за багатьох, багатьох обставин). наприклад, якийсь сервер сокетів

socket_accept ()
вилка ()
якщо (дитина)
    handleRequest ()
ще
    goOnBeingParent ()
Тому реалізація вилки мала бути швидкою, і з часом було впроваджено багато оптимізацій. Microsoft схвалила CreateThread або навіть волокна замість створення нових процесів та використання міжпроцесорної комунікації. Я думаю, що не справедливо порівнювати CreateProcess з виделкою, оскільки вони не взаємозамінні. Напевно, більш доцільно порівняти fork / exec з CreateProcess.


2
Про ваш останній пункт: fork () не можна обмінятись із CreateProcess (), але можна також сказати, що Windows повинна реалізувати fork () тоді, оскільки це дає більшу гнучкість.
Blaisorblade

Ах, дієслово До Бджоли.
acib708

Але fork + exec в Linux, швидше, ніж CreateThread в MS-Windows. А Linux може самостійно робити вилки, щоб бути ще швидшими. Однак, якщо ви порівнюєте його, МС повільніше.
ctrl-alt-delor

13

Ключовим у цьому питанні є історичне використання обох систем, я думаю. Windows (і DOS до цього) спочатку були однокористувацькими системами для персональних комп'ютерів. Таким чином, ці системи зазвичай не повинні створювати багато процесів постійно; (дуже) просто кажучи, процес створюється лише тоді, коли цей одинокий користувач вимагає цього (а ми, люди, не дуже швидко, відносно кажучи).

Системи на базі Unix спочатку були багатокористувацькими системами та серверами. Особливо для останніх не рідкість наявність процесів (наприклад, пошта або http-демон), які розділяють процеси для обробки конкретних завдань (наприклад, піклування про одне вхідне з'єднання). Важливим фактором цього є дешевий forkметод (який, як зазначав Роб Уокер ( 47865 ), спочатку використовує ту саму пам'ять для новоствореного процесу), що дуже корисно, оскільки новий процес одразу має всю необхідну йому інформацію.

Зрозуміло, що принаймні історично потреба у системах на базі Unix у швидкому створенні процесів набагато більша, ніж для систем Windows. Я думаю, що це все ще так, тому що системи на базі Unix все ще дуже орієнтовані на процеси, тоді як Windows, завдяки своїй історії, ймовірно, була більш орієнтована на потоки (теми корисні для створення чутливих додатків).

Відмова: Я аж ніяк не експерт у цьому питанні, тому вибачте мене, якщо я помилився.


9

Ну, схоже, існує багато виправдань, що "краще так".

Я думаю, що люди могли б отримати користь від читання "Showstopper"; книга про розробку Windows NT.

Вся причина, по якій служби працюють як DLL в одному процесі в Windows NT, полягала в тому, що вони були занадто повільними, як окремі процеси.

Якщо ви забруднилися, ви побачите, що проблема стратегії завантаження бібліотеки.

У Unices (загалом) сегменти коду спільних бібліотек (DLL) фактично поділяються.

Windows NT завантажує копію DLL за процес, оскільки він маніпулює сегментом коду бібліотеки (та виконуваним сегментом коду) після завантаження. (Розповідає, де ваші дані?)

Це призводить до сегментів коду в бібліотеках, які не можна використовувати повторно.

Отже, процес створення NT насправді досить дорогий. І з нижньої сторони, це робить DLL не помітною економією пам’яті, а шансом для проблем між додатками.

Іноді в інженерії платять, щоб відступити назад і сказати, "зараз, якби ми збиралися спроектувати це, щоб насправді смоктати, як би це виглядало?"

Я працював із вбудованою системою, яка була досить темпераментною колись, і одного разу переглянула це і зрозуміла, що це магнетрон з порожниною, з електронікою в мікрохвильовій порожнині. Після цього ми зробили це набагато стійкішим (і менш схожим на мікрохвильову піч).


3
Сегменти коду можуть використовуватись повторно, доки DLL завантажується за бажаною базовою адресою. Традиційно слід переконатися, що ви встановлюєте безконфліктні базові адреси для всіх DLL-файлів, які завантажуватимуться у ваші процеси, але це не працює з ASLR.
Майк Діммік

Є якийсь інструмент для відновлення всіх DLL-файлів, чи не так? Не впевнений, що це стосується ASLR.
Зан Лінкс

3
Обмін розділами коду працює і в системах з підтримкою ASLR.
Йоганнес

@MikeDimmick, тому всі, створюючи DLL, повинні співпрацювати, щоб уникнути конфліктів або виправити їх на системному рівні перед завантаженням?
ctrl-alt-delor

9

Коротка відповідь - "програмні шари та компоненти".

Архітектура Windows SW має кілька додаткових шарів і компонентів, які не існують на Unix або спрощені та обробляються всередині ядра в Unix.

У Unix fork та exec - це прямі дзвінки до ядра.

У Windows API ядра не використовується безпосередньо, поверх нього є win32 та деякі інші компоненти, тому створення процесу повинно проходити через додаткові шари, а потім новий процес повинен запускатися або підключатися до цих шарів і компонентів.

Довгий час дослідники та корпорації намагалися розбити Unix нечітко схожим способом, зазвичай грунтуючись на своїх експериментах на ядрі Маха ; добре відомий приклад є OS X. . Щоразу, коли вони намагаються, це стає настільки повільним, що в кінцевому підсумку вони принаймні частково об'єднують шматки назад в ядро ​​або назавжди, або на виробничі відвантаження.


Шари не обов'язково сповільнюють роботу: я написав драйвер пристрою з великою кількістю шарів на C. Чистий код, грамотне програмування, легко читати. Це було швидше (незначно), ніж версія, написана у високооптимізованому асемблері, без шарів.
ctrl-alt-delor

Іронія полягає в тому, що NT - це величезне ядро ​​(а не мікроядро)
ctrl-alt-delor

2

Оскільки, здається, є деякі обґрунтування MS-Windows у деяких відповідях, наприклад

  • «Ядро NT і Win32 - це не одне і те ж. Якщо ви програмуєте на ядро ​​NT, то це не так вже й погано »- Правда, але якщо ви не пишете підсистему Posix, то хто це хвилює. Ви будете писати на win32.
  • "Несправедливо порівнювати вилки з ProcessCreate, оскільки вони роблять різні речі, а у Windows немає вилки" - Правда, тому я порівню, як з подібними. Однак я також порівняю форк, оскільки він має багато випадків використання, наприклад, ізоляція процесу (наприклад, кожна вкладка веб-браузера працює в іншому процесі).

Тепер давайте розглянемо факти, в чому різниця у продуктивності?

Дані, зафіксовані на веб-сайті http://www.bitsnbites.eu/benchmarking-os-primitive/ .
Оскільки упередження неминуче, підбиваючи підсумки, я зробив це на користь обладнання MS-Windows
для більшості тестів i7 8 ядерного 3,2 ГГц. За винятком Raspberry-Pi під керуванням Gnu / Linux

Порівняння різних базових операцій на Gnu / Linux, Apple-Mac та Windows (менші - краще)

Порівняння процесу MS-Windows створюють проти Linux

Примітки. У Linux, forkшвидше, ніж у MS-Window кращий метод CreateThread.

Числа для операцій створення процесів типу (оскільки на діаграмі важко побачити значення для Linux).

У порядку швидкості найшвидший на повільний (цифри - час, малі - краще).

  • Linux CreateThread 12
  • Mac CreateThread 15
  • Linux Fork 19
  • Windows CreateThread 25
  • Linux CreateProcess (fork + exec) 45
  • Mac Fork 105
  • Mac CreateProcess (fork + exec) 453
  • Raspberry-Pi CreateProcess (fork + exec) 501
  • Windows CreateProcess 787
  • Windows CreateProcess За допомогою сканера на віруси 2850
  • Windows Fork (імітуйте за допомогою CreateProcess + fixup) терка ніж 2850

Числа для інших вимірювань

  • Створення файлу.
    • Linux 13
    • Mac 113
    • Windows 225
    • Raspberry-Pi (з повільною SD-карткою) 241
    • Windows із захисником та сканером вірусів тощо 12950
  • Виділення пам'яті
    • Linux 79
    • Windows 93
    • Мак 152

1

Крім того, на тому, що на машині Win, швидше за все, антивірусне програмне забезпечення запуститься під час CreateProcess ... Це, як правило, найбільше уповільнення.


1
Так, це найбільше, але не єдине значне уповільнення.
ctrl-alt-delor

1

Варто також зазначити, що модель безпеки в Windows набагато складніше, ніж в ОС на базі Unix, що додає багато накладних витрат під час створення процесів. Ще одна причина, чому багатопотокове читання віддають перевагу багатопроцесорному обробці в Windows.


1
Я б очікував, що більш складна модель безпеки буде більш захищеною; але факти показують інакше.
Лежи Райан

4
SELinux також дуже складна модель безпеки, і вона не накладає значних накладних витратfork()
Spudd86

6
@LieRyan, У дизайні програмного забезпечення (на мій досвід) складніший дуже рідко означає більш безпечний.
Вудро Дуглас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.