Tại sao việc tạo một quy trình mới trên Windows lại đắt hơn Linux?


100

Tôi nghe nói rằng việc tạo một quy trình mới trên hộp Windows đắt hơn trên Linux. Điều này có đúng không? Ai đó có thể giải thích lý do kỹ thuật tại sao nó đắt hơn và cung cấp bất kỳ lý do lịch sử nào cho các quyết định thiết kế đằng sau những lý do đó không?

Câu trả lời:


68

mweerden: NT đã được thiết kế cho nhiều người dùng ngay từ ngày đầu tiên, vì vậy đây không thực sự là một lý do. Tuy nhiên, bạn nói đúng về việc tạo quy trình đóng một vai trò ít quan trọng hơn trên NT so với trên Unix vì NT, ngược lại với Unix, hỗ trợ đa luồng hơn đa xử lý.

Rob, đúng là fork tương đối rẻ khi sử dụng COW, nhưng trên thực tế, fork chủ yếu được theo sau bởi một người thực thi. Và một giám đốc điều hành cũng phải tải tất cả các hình ảnh. Do đó, thảo luận về hiệu suất của fork chỉ là một phần của sự thật.

Khi thảo luận về tốc độ tạo tiến trình, có lẽ nên phân biệt giữa NT và Windows / Win32. Theo như NT (tức là bản thân hạt nhân), tôi không nghĩ rằng việc tạo quy trình (NtCreateProcess) và tạo luồng (NtCreateThread) chậm hơn đáng kể so với Unix trung bình. Có thể còn một chút nữa đang diễn ra, nhưng tôi không thấy lý do chính cho sự khác biệt về hiệu suất ở đây.

Tuy nhiên, nếu bạn nhìn vào Win32, bạn sẽ nhận thấy rằng nó bổ sung khá nhiều chi phí cho quá trình tạo. Đầu tiên, nó yêu cầu CSRSS phải được thông báo về việc tạo quy trình, liên quan đến LPC. Nó yêu cầu ít nhất kernel32 phải được tải bổ sung và nó phải thực hiện một số mục công việc kế toán bổ sung cần được thực hiện trước khi quá trình này được coi là một quá trình Win32 chính thức. Và đừng quên về tất cả các chi phí bổ sung do phân tích cú pháp tệp kê khai, kiểm tra xem hình ảnh có yêu cầu miếng đệm tương thích hay không, kiểm tra xem các chính sách hạn chế phần mềm có áp dụng không, yada yada.

Điều đó nói rằng, tôi thấy sự chậm lại tổng thể trong tổng số tất cả những việc nhỏ phải được thực hiện ngoài việc tạo thô của một quy trình, không gian VA và luồng ban đầu. Nhưng như đã nói ở phần đầu - do ưa thích đa luồng hơn đa nhiệm, phần mềm duy nhất bị ảnh hưởng nghiêm trọng bởi chi phí bổ sung này là phần mềm Unix được chuyển tải kém. Mặc dù sơ đồ trang web này thay đổi khi phần mềm như Chrome và IE8 đột nhiên khám phá lại lợi ích của quá trình đa xử lý và bắt đầu thường xuyên khởi động và gỡ bỏ các quy trình ...


8
Fork không phải lúc nào cũng được theo sau bởi executive () và mọi người chỉ quan tâm đến fork (). Apache 1.3 sử dụng fork () (không có tệp thi hành) trên Linux và các luồng trên Windows, ngay cả khi trong nhiều trường hợp, các quy trình được chia nhỏ trước khi chúng cần thiết và được giữ trong một nhóm.
Blaisorblade

5
Tất nhiên, không quên, lệnh 'vfork', được thiết kế cho kịch bản 'chỉ cuộc gọi thực thi' mà bạn mô tả.
Chris Huang-Leaver

4
Một loại phần mềm khác bị ảnh hưởng nghiêm trọng bởi điều này là bất kỳ loại kịch bản shell nào liên quan đến sự phối hợp của nhiều quy trình. Chẳng hạn, tập lệnh Bash bên trong Cygwin bị ảnh hưởng rất nhiều từ nó. Hãy xem xét một vòng lặp shell tạo ra rất nhiều sed, awk và grep trong các đường ống. Mỗi lệnh tạo ra một quá trình và mỗi đường ống tạo ra một vỏ con và một quá trình mới trong vỏ con đó. Unix được thiết kế với cách sử dụng rất quan trọng, đó là lý do tại sao việc tạo quy trình nhanh vẫn là tiêu chuẩn ở đó.
Dan Molding,

5
-1. Tuyên bố rằng phần mềm 'được chuyển tải kém' vì nó không chạy tốt trên một hệ điều hành được thiết kế kém với đầy đủ tính tương thích làm chậm quá trình tạo ra là điều nực cười.
Miles Rout

6
@MilesRout mục tiêu của quá trình chuyển là sửa đổi phần mềm để chạy trên hệ thống đích mới, có lưu ý đến điểm mạnh và điểm thiếu sót của hệ thống đó. Phần mềm được chuyển hoạt động kém phần mềm được chuyển kém, bất kể những rào cản mà hệ điều hành cung cấp.
Dizzyspiral

28

Unix có một lệnh gọi hệ thống 'fork' để 'chia nhỏ' quy trình hiện tại thành hai và cung cấp cho bạn một quy trình thứ hai giống với quy trình đầu tiên (mô đun trở lại từ cuộc gọi fork). Vì không gian địa chỉ của quy trình mới đã được thiết lập và việc chạy này sẽ rẻ hơn so với việc gọi 'CreateProcess' trong Windows và để nó tải hình ảnh exe, dlls liên quan, v.v.

Trong trường hợp rẽ nhánh, hệ điều hành có thể sử dụng ngữ nghĩa 'copy-on-write' cho các trang bộ nhớ được liên kết với cả hai quy trình mới để đảm bảo rằng mỗi quy trình nhận được bản sao của các trang mà họ sửa đổi sau đó.


22
Lập luận này chỉ đúng khi bạn thực sự rèn luyện. Nếu bạn đang bắt đầu một quy trình mới, trên Unix, bạn vẫn phải fork và thực thi. Cả Windows và Unix đều có tính năng sao chép khi ghi. Windows chắc chắn sẽ sử dụng lại EXE đã tải nếu bạn chạy bản sao thứ hai của một ứng dụng. Tôi không nghĩ rằng lời giải thích của bạn là đúng, xin lỗi.
Joel Spolsky

1
Thông tin thêm về thi hành () và fork () vipinkrsahu.blogspot.com/search/label/system%20programming
webkul

Tôi đã thêm một số dữ liệu hiệu suất trong câu trả lời của mình. stackoverflow.com/a/51396188/537980 Bạn có thể thấy rằng nó nhanh hơn.
ctrl-alt-delor

25

Thêm vào những gì JP đã nói: phần lớn chi phí thuộc về khởi động Win32 cho quá trình này.

Nhân Windows NT thực sự hỗ trợ COW fork. SFU (môi trường UNIX của Microsoft dành cho Windows) sử dụng chúng. Tuy nhiên, Win32 không hỗ trợ fork. Quy trình SFU không phải là quy trình Win32. SFU là trực giao với Win32: cả hai đều là hệ thống con của môi trường được xây dựng trên cùng một hạt nhân.

Ngoài các lệnh gọi LPC ngoài quy trình tới CSRSS, trong XP trở lên còn có lệnh gọi ngoài quy trình tới công cụ tương thích ứng dụng để tìm chương trình trong cơ sở dữ liệu tương thích ứng dụng. Bước này gây ra đủ chi phí mà Microsoft cung cấp tùy chọn chính sách nhóm để vô hiệu hóa công cụ tương thích trên WS2003 vì lý do hiệu suất.

Các thư viện thời gian chạy Win32 (kernel32.dll, v.v.) cũng thực hiện nhiều lần đọc và khởi tạo sổ đăng ký khi khởi động không áp dụng cho UNIX, SFU hoặc các quy trình gốc.

Các quy trình gốc (không có hệ thống con môi trường) được tạo rất nhanh. SFU thực hiện ít hơn Win32 rất nhiều trong việc tạo quy trình, vì vậy các quy trình của nó cũng được tạo nhanh.

CẬP NHẬT CHO NĂM 2019: thêm LXSS: Hệ thống con Windows cho Linux

Thay thế SFU cho Windows 10 là hệ thống con môi trường LXSS. Đây là chế độ hạt nhân 100% và không yêu cầu bất kỳ IPC nào mà Win32 tiếp tục có. Syscall cho các quy trình này được chuyển trực tiếp đến lxss.sys / lxcore.sys, do đó, fork () hoặc lệnh gọi tạo quy trình khác chỉ tốn tổng cộng 1 lần gọi hệ thống cho trình tạo. [Một vùng dữ liệu được gọi là phiên bản] theo dõi tất cả các quy trình, luồng và trạng thái thời gian chạy của LX.

Các quy trình LXSS dựa trên các quy trình gốc, không phải quy trình Win32. Tất cả những thứ cụ thể của Win32 như công cụ tương thích đều không được tham gia.


16

Ngoài câu trả lời của Rob Walker: Ngày nay bạn có những thứ như Thư viện chủ đề POSIX gốc - nếu bạn muốn. Nhưng trong một thời gian dài, cách duy nhất để "ủy quyền" công việc trong thế giới unix là sử dụng fork () (và nó vẫn được ưa chuộng trong nhiều trường hợp). ví dụ: một số loại máy chủ ổ cắm

socket_accept ()
cái nĩa()
nếu (con)
    handleRequest ()
khác
    goOnBeingParent ()
Do đó, việc triển khai fork phải nhanh chóng và rất nhiều tối ưu hóa đã được thực hiện theo thời gian. Microsoft xác nhận CreateThread hoặc thậm chí các sợi thay vì tạo các quy trình mới và sử dụng giao tiếp giữa các quy trình. Tôi nghĩ không "công bằng" khi so sánh CreateProcess với fork vì chúng không thể hoán đổi cho nhau. Có lẽ thích hợp hơn nếu so sánh fork / executive với CreateProcess.


2
Về điểm cuối cùng của bạn: fork () không thể trao đổi với CreateProcess (), nhưng người ta cũng có thể nói rằng Windows nên triển khai fork () sau đó, vì điều đó mang lại sự linh hoạt hơn.
Blaisorblade

À, động từ To Bee.
acib708

Nhưng fork + execute trong Linux, nhanh hơn CreateThread trên MS-Windows. Và Linux có thể tự thực hiện fork để nhanh hơn nữa. Tuy nhiên bạn so sánh nó, MS là chậm hơn.
ctrl-alt-delor

13

Mấu chốt của vấn đề này là lịch sử sử dụng của cả hai hệ thống, tôi nghĩ. Windows (và DOS trước đó) ban đầu là hệ thống một người dùng cho máy tính cá nhân . Như vậy, các hệ thống này thường không phải tạo nhiều quy trình mọi lúc; (rất) nói một cách đơn giản, một quy trình chỉ được tạo ra khi một người dùng cô đơn này yêu cầu nó (và con người chúng ta hoạt động không nhanh lắm, nói một cách tương đối).

Các hệ thống dựa trên Unix ban đầu là hệ thống nhiều người dùng và máy chủ. Đặc biệt là đối với loại thứ hai, không có gì lạ khi có các quy trình (ví dụ: mail hoặc http daemon) tách các quy trình ra để xử lý các công việc cụ thể (ví dụ: chăm sóc một kết nối đến). Một yếu tố quan trọng để làm điều này là forkphương pháp rẻ tiền (như Rob Walker ( 47865 ) đã đề cập , ban đầu sử dụng cùng một bộ nhớ cho quy trình mới được tạo) rất hữu ích vì quy trình mới ngay lập tức có tất cả thông tin mà nó cần.

Rõ ràng là ít nhất trong lịch sử, nhu cầu về các hệ thống dựa trên Unix để tạo quy trình nhanh là lớn hơn nhiều so với các hệ thống Windows. Tôi nghĩ điều này vẫn xảy ra bởi vì các hệ thống dựa trên Unix vẫn được định hướng theo quy trình, trong khi Windows, do lịch sử của nó, có lẽ đã được định hướng nhiều hơn (các luồng hữu ích để tạo các ứng dụng đáp ứng).

Tuyên bố từ chối trách nhiệm: Tôi hoàn toàn không phải là chuyên gia về vấn đề này, vì vậy hãy tha thứ cho tôi nếu tôi sai.


9

Uh, dường như có rất nhiều lời biện minh "tốt hơn là theo cách này" đang diễn ra.

Tôi nghĩ rằng mọi người có thể được hưởng lợi từ việc đọc "Showstopper"; cuốn sách về sự phát triển của Windows NT.

Toàn bộ lý do khiến các dịch vụ chạy dưới dạng DLL trong một quá trình trên Windows NT là chúng quá chậm như các quá trình riêng biệt.

Nếu bạn thất vọng và bẩn thỉu, bạn sẽ thấy rằng chiến lược tải thư viện là vấn đề.

Trên Unices (nói chung), các đoạn mã của Thư viện được chia sẻ (DLL) thực sự được chia sẻ.

Windows NT tải một bản sao của DLL cho mỗi quá trình, vì nó thao tác phân đoạn mã thư viện (và đoạn mã thực thi) sau khi tải. (Cho nó biết dữ liệu của bạn ở đâu?)

Điều này dẫn đến các đoạn mã trong thư viện không thể sử dụng lại được.

Vì vậy, quá trình tạo NT thực sự khá tốn kém. Và mặt trái, nó làm cho DLL không tiết kiệm đáng kể trong bộ nhớ, mà là cơ hội cho các vấn đề phụ thuộc giữa các ứng dụng.

Đôi khi, kỹ thuật phải trả giá khi lùi lại và nói, "bây giờ, nếu chúng ta định thiết kế cái này để thực sự hấp dẫn, nó sẽ trông như thế nào?"

Tôi đã từng làm việc với một hệ thống nhúng khá thất thường, và một ngày nọ nhìn vào nó và nhận ra đó là một magnetron trong khoang, với các thiết bị điện tử trong khoang vi sóng. Sau đó, chúng tôi đã làm cho nó ổn định hơn nhiều (và ít giống lò vi sóng hơn).


3
Các phân đoạn mã có thể được sử dụng lại miễn là DLL tải tại địa chỉ cơ sở ưa thích của nó. Theo truyền thống, bạn nên đảm bảo rằng bạn đặt các địa chỉ cơ sở không xung đột cho tất cả các DLL sẽ tải vào các quy trình của bạn, nhưng điều đó không hoạt động với ASLR.
Mike Dimmick 17/09/08

Có một số công cụ để căn cứ lại tất cả các DLL, phải không? Không chắc chắn những gì nó làm với ASLR.
Zan Lynx

3
Chia sẻ các phần mã cũng hoạt động trên các hệ thống hỗ trợ ASLR.
Johannes vượt qua

@MikeDimmick vậy mọi người, tạo DLL phải hợp tác, để đảm bảo rằng không có xung đột hay bạn vá tất cả chúng ở cấp hệ thống trước khi tải?
ctrl-alt-delor

9

Câu trả lời ngắn gọn là "các lớp và thành phần phần mềm".

Kiến trúc Windows SW có một vài lớp và thành phần bổ sung không tồn tại trên Unix hoặc được đơn giản hóa và xử lý bên trong hạt nhân trên Unix.

Trên Unix, fork và execute là các lệnh gọi trực tiếp đến hạt nhân.

Trên Windows, kernel API không được sử dụng trực tiếp, có win32 và một số thành phần khác nằm trên nó, vì vậy quá trình tạo quy trình phải đi qua các lớp bổ sung và sau đó quy trình mới phải khởi động hoặc kết nối với các lớp và thành phần đó.

Trong một thời gian khá lâu, các nhà nghiên cứu và tập đoàn đã cố gắng phá vỡ Unix theo một cách khá giống nhau, thường dựa trên các thí nghiệm của họ trên nhân Mach ; một ví dụ nổi tiếng là OS X. . Tuy nhiên, mỗi khi họ cố gắng, nó trở nên chậm đến mức họ kết thúc ít nhất một phần hợp nhất các mảnh trở lại hạt nhân vĩnh viễn hoặc cho các lô hàng sản xuất.


Các lớp không nhất thiết phải làm chậm mọi thứ: Tôi đã viết một trình điều khiển thiết bị, với rất nhiều lớp, trong C. Mã sạch, lập trình thông thạo, dễ đọc. Nó nhanh hơn (một chút), so với phiên bản được viết bằng trình hợp dịch được tối ưu hóa cao, không có lớp.
ctrl-alt-delor

Điều trớ trêu là NT là một hạt nhân khổng lồ (không phải là một hạt nhân vi)
ctrl-alt-delor

2

Vì dường như có một số biện minh về MS-Windows trong một số câu trả lời, ví dụ:

  • “Hạt nhân NT và Win32, không giống nhau. Nếu bạn lập trình với hạt nhân NT thì nó không đến nỗi tệ ”- Đúng, nhưng trừ khi bạn đang viết một hệ thống con Posix, thì ai quan tâm. Bạn sẽ viết cho win32.
  • “Thật không công bằng khi so sánh fork với ProcessCreate, vì chúng làm những việc khác nhau, còn Windows thì không có fork” - Đúng, Vì vậy, tôi sẽ so sánh like với like. Tuy nhiên, tôi cũng sẽ so sánh fork, vì nó có nhiều trường hợp sử dụng, chẳng hạn như cách ly quy trình (ví dụ: mỗi tab của trình duyệt web chạy trong một quy trình khác nhau).

Bây giờ chúng ta hãy xem xét sự thật, sự khác biệt trong hiệu suất là gì?

Dữ liệu được tổng hợp từ http://www.bitsnbites.eu/benchmarking-os-primaries/ .
Bởi vì sự thiên vị là không thể tránh khỏi, khi tóm tắt, tôi đã làm điều đó có lợi cho Phần cứng MS-Windows
cho hầu hết các bài kiểm tra i7 8 nhân 3.2GHz. Ngoại trừ Raspberry-Pi chạy Gnu / Linux

So sánh các hoạt động cơ bản khác nhau, trên Gnu / Linux, Apple-Mac và Windows của Microsoft (nhỏ hơn thì tốt hơn)

So sánh quy trình tạo MS-Windows so với Linux

Lưu ý: Trên linux, forknhanh hơn là phương pháp ưa thích của MS-Window CreateThread.

Các số cho kiểu hoạt động tạo quy trình (vì khó thấy giá trị của Linux trong biểu đồ).

Theo thứ tự tốc độ, nhanh nhất đến chậm nhất (số là thời gian, càng nhỏ càng tốt).

  • Linux CreateThread 12
  • Mac CreateThread 15
  • Linux Fork 19
  • Windows CreateThread 25
  • Linux CreateProcess (fork + executive) 45
  • Mac Fork 105
  • Mac CreateProcess (fork + executive) 453
  • Raspberry-Pi CreateProcess (fork + executive) 501
  • Windows CreateProcess 787
  • Windows CreateProcess Với trình quét virus 2850
  • Windows Fork (mô phỏng bằng CreateProcess + fixup) nhiều hơn 2850

Số cho các phép đo khác

  • Tạo một tệp.
    • Linux 13
    • Mac 113
    • Windows 225
    • Raspberry-Pi (với thẻ SD chậm) 241
    • Windows với trình bảo vệ và trình quét vi rút, v.v. 12950
  • Phân bổ bộ nhớ
    • Linux 79
    • Windows 93
    • Mac 152

1

Tất cả những điều đó cộng với thực tế là trên máy Win có lẽ phần mềm chống vi-rút sẽ hoạt động trong quá trình CreateProcess ... Đó thường là sự chậm chạp lớn nhất.


1
Vâng, đó là sự chậm lại lớn nhất, nhưng không phải là sự chậm lại đáng kể duy nhất.
ctrl-alt-delor

1

Cũng cần lưu ý rằng mô hình bảo mật trong Windows phức tạp hơn nhiều so với các hệ điều hành dựa trên unix, điều này làm tăng thêm rất nhiều chi phí trong quá trình tạo. Tuy nhiên, một lý do khác tại sao đa luồng được ưa thích hơn đa xử lý trong Windows.


1
Tôi mong đợi một mô hình bảo mật phức tạp hơn sẽ an toàn hơn; nhưng sự thật cho thấy khác.
Lie Ryan

4
SELinux cũng là một mô hình bảo mật rất phức tạp, và nó không áp đặt một chi phí đáng kể trênfork()
Spudd86

6
@LieRyan, Trong thiết kế phần mềm (theo kinh nghiệm của tôi), rất hiếm khi phức tạp hơn có nghĩa là an toàn hơn.
Woodrow Douglass
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.