Você está olhando para o cara que fez essa escolha. David Cutler e sua equipe selecionaram um megabyte como o tamanho de pilha padrão. Nada a ver com .NET ou C #, isso foi resolvido quando eles criaram o Windows NT. Um megabyte é o que ele escolhe quando o cabeçalho EXE de um programa ou a chamada do winapi CreateThread () não especifica o tamanho da pilha explicitamente. Que é a forma normal, quase qualquer programador deixa que o sistema operacional escolha o tamanho.
Essa escolha provavelmente é anterior ao design do Windows NT, a história é muito obscura sobre isso. Seria bom se Cutler escrevesse um livro sobre isso, mas ele nunca foi escritor. Ele tem sido extraordinariamente influente na maneira como os computadores funcionam. Seu primeiro design de sistema operacional foi RSX-11M, um sistema operacional de 16 bits para computadores DEC (Digital Equipment Corporation). Ele influenciou fortemente o CP / M de Gary Kildall, o primeiro sistema operacional decente para microprocessadores de 8 bits. O que influenciou fortemente o MS-DOS.
Seu próximo projeto foi o VMS, um sistema operacional para processadores de 32 bits com suporte para memória virtual. Muito bem sucedido. Seu próximo foi cancelado pela DEC na época em que a empresa começou a se desintegrar, não sendo capaz de competir com hardware de PC barato. Cue Microsoft, eles lhe fizeram uma oferta que ele não podia recusar. Muitos de seus colegas de trabalho também aderiram. Eles trabalharam no VMS v2, mais conhecido como Windows NT. DEC ficou chateado com isso, o dinheiro mudou de mãos para resolver o problema. Se o VMS já escolheu um megabyte é algo que não sei, só conheço o RSX-11 bem o suficiente. Não é improvável.
Chega de história. Um megabyte é muito , um thread real raramente consome mais do que alguns poucos kilobytes. Portanto, um megabyte é realmente um desperdício. No entanto, é o tipo de desperdício que você pode pagar em um sistema operacional de memória virtual paginada por demanda, aquele megabyte é apenas memória virtual . Apenas números para o processador, um para cada 4096 bytes. Na verdade, você nunca usa a memória física, a RAM da máquina, até que a endereça de fato.
É extremamente excessivo em um programa .NET porque o tamanho de um megabyte foi originalmente escolhido para acomodar programas nativos. Que tendem a criar grandes quadros de pilha, armazenando strings e buffers (arrays) na pilha também. Infame por ser um vetor de ataque de malware, um estouro de buffer pode manipular o programa com dados. Não é a forma como os programas .NET funcionam, strings e arrays são alocados no heap do GC e a indexação é verificada. A única maneira de alocar espaço na pilha com C # é com a palavra-chave stackalloc não segura .
O único uso não trivial da pilha no .NET é por jitter. Ele usa a pilha de seu thread para compilar o MSIL para o código de máquina just-in-time. Eu nunca vi ou verifiquei quanto espaço ele requer, depende da natureza do código e se o otimizador está habilitado ou não, mas algumas dezenas de kilobytes é um palpite aproximado. Caso contrário, este site recebeu o nome, um estouro de pilha em um programa .NET é bastante fatal. Não há espaço suficiente (menos de 3 kilobytes) para executar o JIT confiável de qualquer código que tente capturar a exceção. Kaboom para desktop é a única opção.
Por último, mas não menos importante, um programa .NET faz algo bastante improdutivo com a pilha. O CLR irá comprometer a pilha de um thread. Essa é uma palavra cara que significa que ela não apenas reserva o tamanho da pilha, mas também garante que o espaço seja reservado no arquivo de paginação do sistema operacional para que a pilha possa sempre ser trocada quando necessário. Deixar de confirmar é um erro fatal e encerra um programa incondicionalmente. Isso só acontece em máquinas com pouquíssima RAM que executa muitos processos, tal máquina terá se transformado em melaço antes que os programas comecem a morrer. Um possível problema há mais de 15 anos, não hoje. Os programadores que ajustam seu programa para agir como um carro de corrida de F1 usam o <disableCommitThreadStack>
elemento em seu arquivo .config.
Fwiw, Cutler não parou de projetar sistemas operacionais. Essa foto foi feita enquanto ele trabalhava no Azure.
Update, notei que o .NET não confirma mais a pilha. Não tenho certeza de quando ou por que isso aconteceu, já faz muito tempo desde que verifiquei. Acho que essa mudança de design aconteceu em algum lugar perto do .NET 4.5. Mudança bastante sensata.
Thread
construtor. MAS, isso levanta a questão, por que você precisa de uma pilha maior?