Linux보다 Windows에서 새 프로세스를 만드는 데 더 많은 비용이 드는 이유는 무엇입니까?
Windows 상자에서 새 프로세스를 만드는 것이 Linux보다 더 비싸다고 들었습니다. 이것이 사실입니까? 누군가 더 비싼 이유에 대한 기술적 이유를 설명하고 그 이유 뒤에있는 설계 결정에 대한 역사적 이유를 제공 할 수 있습니까?
mweerden : NT는 첫날부터 다중 사용자를 위해 설계되었으므로 이것이 실제로 이유가 아닙니다. 그러나 유닉스와는 대조적으로, 멀티 프로세싱보다 멀티 스레딩을 선호하기 때문에 NT에서 프로세스 생성이 유닉스보다 NT에서 덜 중요한 역할을한다는 점이 맞습니다.
Rob, COW를 사용할 때 포크가 상대적으로 저렴하다는 것은 사실이지만 실제로는 포크 뒤에는 대부분 exec가 따릅니다. 그리고 임원은 모든 이미지도로드해야합니다. 따라서 포크의 성능을 논의하는 것은 진실의 일부일뿐입니다.
프로세스 생성 속도를 논의 할 때 NT와 Windows / Win32를 구분하는 것이 좋습니다. NT (즉 커널 자체)가 진행되는 한, 프로세스 생성 (NtCreateProcess)과 스레드 생성 (NtCreateThread)이 평균 Unix 에서처럼 상당히 느리다고 생각하지 않습니다. 조금 더 진행될 수 있지만 여기서 성능 차이에 대한 주된 이유는 보이지 않습니다.
그러나 Win32를 살펴보면 프로세스 생성에 상당한 오버 헤드가 추가된다는 것을 알 수 있습니다. 첫째, CSRSS가 LPC를 포함하는 프로세스 생성에 대한 알림을 받아야합니다. 최소한 kernel32를 추가로로드해야하며 프로세스가 완전한 Win32 프로세스로 간주되기 전에 수행 할 여러 추가 부기 작업 항목을 수행해야합니다. 그리고 매니페스트 구문 분석, 이미지에 호환성 심이 필요한지 확인, 소프트웨어 제한 정책 적용 여부 확인, yada yada로 인해 부과되는 모든 추가 오버 헤드를 잊지 마십시오.
즉, 프로세스, VA 공간 및 초기 스레드의 원시 생성 외에도 수행해야하는 모든 사소한 작업의 합계에서 전반적인 속도 저하를 봅니다. 그러나 처음에 말했듯이-멀티 태스킹보다 멀티 스레딩을 선호하기 때문에이 추가 비용으로 심각한 영향을받는 유일한 소프트웨어는 제대로 이식되지 않은 Unix 소프트웨어입니다. Chrome 및 IE8과 같은 소프트웨어가 갑자기 다중 처리의 이점을 재발견하고 프로세스를 자주 시작하고 해체하기 시작하면 이러한 상황이 변경되지만 ...
유닉스에는 현재 프로세스를 두 개로 '분할'하는 '포크'시스템 호출이 있으며 첫 번째 프로세스와 동일한 두 번째 프로세스를 제공합니다 (포크 호출의 반환 모듈로). 새 프로세스의 주소 공간이 이미 실행 중이므로 Windows에서 'CreateProcess'를 호출하고 exe 이미지, 관련 dll 등을로드하는 것보다 저렴해야합니다.
포크의 경우 OS는 두 새 프로세스와 관련된 메모리 페이지에 대해 '기록 중 복사'의미 체계를 사용하여 각 프로세스가 이후에 수정하는 페이지의 자체 복사본을 얻도록 할 수 있습니다.
JP가 말한 내용에 추가 : 대부분의 오버 헤드는 프로세스의 Win32 시작에 속합니다.
Windows NT 커널은 실제로 COW 포크를 지원합니다. SFU (Microsoft의 Windows 용 UNIX 환경)는이를 사용합니다. 그러나 Win32는 포크를 지원하지 않습니다. SFU 프로세스는 Win32 프로세스가 아닙니다. SFU는 Win32와 직교합니다. 두 환경 모두 동일한 커널에 구축 된 환경 하위 시스템입니다.
에 대한 out-of-process LPC 호출 외에도 CSRSS
XP 이상에서는 응용 프로그램 호환성 데이터베이스에서 프로그램을 찾기 위해 응용 프로그램 호환성 엔진 에 대한 out-of-process 호출이 있습니다. 이 단계는 성능상의 이유로 WS2003에서 호환성 엔진 을 비활성화 하는 그룹 정책 옵션을 Microsoft가 제공하는 충분한 오버 헤드를 발생시킵니다 .
Win32 런타임 라이브러리 (kernel32.dll 등)는 UNIX, SFU 또는 기본 프로세스에 적용되지 않는 시작시 많은 레지스트리 읽기 및 초기화를 수행합니다.
기본 프로세스 (환경 하위 시스템 없음)는 생성 속도가 매우 빠릅니다. SFU는 프로세스 생성을 위해 Win32보다 훨씬 적게 수행하므로 프로세스도 빠르게 생성됩니다.
2019 년 업데이트 : LXSS 추가 : Linux 용 Windows 하위 시스템
Windows 10 용 SFU를 대체하는 것은 LXSS 환경 하위 시스템입니다. 100 % 커널 모드이며 Win32가 계속 보유하고있는 IPC가 필요하지 않습니다. 이러한 프로세스에 대한 Syscall은 lxss.sys / lxcore.sys로 직접 전달되므로 fork () 또는 기타 프로세스 생성 호출은 생성자에게 총 1 개의 시스템 호출 만 발생합니다. [인스턴스라고하는 데이터 영역]은 모든 LX 프로세스, 스레드 및 런타임 상태를 추적합니다.
LXSS 프로세스는 Win32 프로세스가 아닌 기본 프로세스를 기반으로합니다. 호환성 엔진과 같은 모든 Win32 관련 항목은 전혀 관여하지 않습니다.
Rob Walker의 답변 외에도 : 요즘에는 네이티브 POSIX 스레드 라이브러리와 같은 것이 있습니다. 그러나 오랫동안 유닉스 세계에서 작업을 "위임"하는 유일한 방법은 fork ()를 사용하는 것이 었습니다 (그리고 여전히 많은 상황에서 선호됩니다). 예 : 일종의 소켓 서버
socket_accept () 포크() if (아이) handleRequest () 그밖에 goOnBeingParent ()따라서 포크의 구현은 빨라야하고 시간이 지남에 따라 많은 최적화가 구현되었습니다. Microsoft는 새로운 프로세스를 만들고 프로세스 간 통신을 사용하는 대신 CreateThread 또는 광섬유를 승인했습니다. CreateProcess를 fork와 비교하는 것은 "공정"하지 않다고 생각합니다. fork / exec를 CreateProcess와 비교하는 것이 더 적절할 것입니다.
이 문제의 핵심은 두 시스템의 역사적 사용입니다. Windows (및 그 이전의 DOS)는 원래 개인용 컴퓨터 용 단일 사용자 시스템이었습니다 . 따라서 이러한 시스템은 일반적으로 항상 많은 프로세스를 생성 할 필요가 없습니다. (매우) 간단히 말해서, 프로세스는 외로운 사용자가 요청할 때만 생성됩니다 (우리 인간은 상대적으로 말해서 매우 빠르게 작동하지 않습니다).
Unix 기반 시스템은 원래 다중 사용자 시스템과 서버였습니다. 특히 후자의 경우 특정 작업을 처리하기 위해 프로세스를 분리하는 프로세스 (예 : 메일 또는 http 데몬)가있는 경우가 드물지 않습니다 (예 : 하나의 수신 연결 처리). 이를 수행하는 데 중요한 요소는 저렴한 fork
방법 (Rob Walker ( 47865 )이 언급했듯이 처음에는 새로 생성 된 프로세스에 동일한 메모리를 사용함)입니다. 이는 새 프로세스가 필요한 모든 정보를 즉시 확보하므로 매우 유용합니다.
It is clear that at least historically the need for Unix-based systems to have fast process creation is far greater than for Windows systems. I think this is still the case because Unix-based systems are still very process oriented, while Windows, due to its history, has probably been more thread oriented (threads being useful to make responsive applications).
Disclaimer: I'm by no means an expert on this matter, so forgive me if I got it wrong.
Uh, there seems to be a lot of "it's better this way" sort of justification going on.
I think people could benefit from reading "Showstopper"; the book about the development of Windows NT.
The whole reason the services run as DLL's in one process on Windows NT was that they were too slow as separate processes.
If you got down and dirty you'd find that the library loading strategy is the problem.
On Unices ( in general) the Shared libraries (DLL's) code segments are actually shared.
Windows NT loads a copy of the DLL per process, becauase it manipulates the library code segment (and executable code segment) after loading. (Tells it where is your data ?)
This results in code segments in libraries that are not reusable.
So, the NT process create is actually pretty expensive. And on the down side, it makes DLL's no appreciable saving in memory, but a chance for inter-app dependency problems.
Sometimes it pays in engineering to step back and say, "now, if we were going to design this to really suck, what would it look like?"
I worked with an embedded system that was quite temperamental once upon a time, and one day looked at it and realized it was a cavity magnetron, with the electronics in the microwave cavity. We made it much more stable (and less like a microwave) after that.
The short answer is "software layers and components".
The windows SW architecture has a couple of additional layers and components that don't exist on Unix or are simplified and handled inside the kernel on Unix.
On Unix, fork and exec are direct calls to the kernel.
On Windows, the kernel API is not used directly, there is win32 and certain other components on top of it, so process creation must go through extra layers and then the new process must start up or connect to those layers and components.
For quite some time researchers and corporations have attempted to break up Unix in a vaguely similar way, usually basing their experiments on the Mach kernel; a well-known example is OS X.. Every time they try, though, it gets so slow they end up at least partially merging the pieces back into the kernel either permanently or for production shipments.
As there seems to be some justification of MS-Windows in some of the answers e.g.
- “NT kernel and Win32, are not the same thing. If you program to NT kernel then it is not so bad” — True, but unless you are writing a Posix subsystem, then who cares. You will be writing to win32.
- “It is not fair to compare fork, with ProcessCreate, as they do different things, and Windows does not have fork“ — True, So I will compare like with like. However I will also compare fork, because it has many many use cases, such as process isolation (e.g. each tab of a web browser runs in a different process).
Now let us look at the facts, what is the difference in performance?
Data summerised from http://www.bitsnbites.eu/benchmarking-os-primitives/.
Because bias is inevitable, when summarising, I did it in favour of MS-Windows
Hardware for most tests i7 8 core 3.2GHz. Except Raspberry-Pi running Gnu/Linux
Notes: On linux, fork
is faster that MS-Window's preferred method CreateThread
.
Numbers for process creation type operations (because it is hard to see the value for Linux in the chart).
In order of speed, fastest to slowest (numbers are time, small is better).
- 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 With virus scanner 2850
- Windows Fork (simulate with CreateProcess + fixup) grater than 2850
Numbers for other measurements
- Creating a file.
- Linux 13
- Mac 113
- Windows 225
- Raspberry-Pi (with slow SD card) 241
- Windows with defender and virus scanner etc 12950
- Allocating memory
- Linux 79
- Windows 93
- Mac 152
All that plus there's the fact that on the Win machine most probably an antivirus software will kick in during the CreateProcess... That's usually the biggest slowdown.
It's also worth noting that the security model in Windows is vastly more complicated than in unix-based OSs, which adds a lot of overhead during process creation. Yet another reason why multithreading is preferred to multiprocessing in Windows.
'programing tip' 카테고리의 다른 글
모듈 __file__ 속성은 절대적입니까 아니면 상대적입니까? (0) | 2020.08.22 |
---|---|
InputStream에서 File 객체를 만들 수 있습니까? (0) | 2020.08.22 |
Android 테스트 실행기가 '빈 테스트 도구 모음'을보고하는 이유는 무엇입니까? (0) | 2020.08.22 |
"스트림이 이미 작동되었거나 닫혔습니다"를 방지하기 위해 스트림을 복사합니다. (0) | 2020.08.22 |
Razor에서 Visual Studio 코드 서식 비활성화 (0) | 2020.08.22 |