Quickie, explicação incompleta:
Em um comutador de thread, há muito menos contexto que você precisa salvar / carregar. Especificamente, a memória é compartilhada. O kernel não precisa fazer nenhuma página de páginas sujas, e truques de VM para puxar toda a memória para um novo processo (embora algumas páginas específicas possam precisar ser inseridas). Existem outras estruturas de dados específicas do processo no kernel (digamos, a tabela de descritores de arquivos abertos) que não precisam ser trocadas.
Como efeito colateral, também é muito mais provável que você consiga usar o que está nos caches do processador nesse ponto. um novo processo provavelmente precisa iniciar um cache frio.
Sim, existem ferramentas para compartilhar memória (memória compartilhada IPC, pipes) entre processos, mas nenhuma é tão limpa / fácil quanto a memória comum em um processo. Você não pode crescer um bloco de memória compartilhada como você pode com realloc () e tal. Qualquer coisa além da memória compartilhada significa que você precisa de várias cópias de estruturas de dados, uma em cada processo, com truques para copiar as alterações conforme necessário.
Especificamente, o apache possui vários modelos para diferentes sistemas operacionais. O modelo original era pré-fork, dando isolamento do processo em troca de troca de processos pesados. Isso funcionou bem com os UNIXes que eram comuns no momento da primeira escrita, onde alguns não tinham threads. O Windows era tão ruim com multiprocessos que o apache tinha para fazer encadeamentos - os processos no Windows (pelo menos no momento do apache 1.2 / 2.0) eram muito pesados. O Linux tem processos muito leves, em que a comutação está próxima do tempo de troca de linha, por isso ficou normalmente pré-fork. O Solaris tem um modelo de thread "LWP" complexo e funciona melhor em um modelo híbrido de thread / fork.