Algumas pessoas diriam que dois tópicos são muitos - eu não estou nesse campo :-)
Aqui está o meu conselho: meça, não adivinhe. Uma sugestão é torná-lo configurável e, inicialmente, defini-lo como 100, depois libere seu software para o estado selvagem e monitore o que acontece.
Se o uso de seu segmento atingir um pico de 3, 100 será demais. Se permanecer em 100 a maior parte do dia, aumente para 200 e veja o que acontece.
Você pode realmente ter seu próprio código monitorando o uso e ajustando a configuração para a próxima vez que iniciar, mas isso provavelmente é um exagero.
Para esclarecimentos e elaboração:
Eu não estou defendendo a rolagem do seu próprio subsistema de pool de threads, por qualquer meio use o que você possui. Mas, como você estava perguntando sobre um bom ponto de corte para encadeamentos, presumo que a implementação do conjunto de encadeamentos tenha a capacidade de limitar o número máximo de encadeamentos criados (o que é uma coisa boa).
Eu escrevi código de pool de threads e de conexão com o banco de dados e eles têm os seguintes recursos (que eu acredito que são essenciais para o desempenho):
- um número mínimo de encadeamentos ativos.
- um número máximo de threads.
- desligando threads que não são usados há um tempo.
O primeiro define uma linha de base para o desempenho mínimo em termos do cliente do conjunto de encadeamentos (esse número de encadeamentos está sempre disponível para uso). O segundo define uma restrição ao uso de recursos por encadeamentos ativos. O terceiro retorna à linha de base em tempos de silêncio, para minimizar o uso de recursos.
Você precisa equilibrar o uso de recursos de ter threads não utilizados (A) com o uso de recursos de não ter threads suficientes para fazer o trabalho (B).
(A) geralmente é uso de memória (pilhas e assim por diante), uma vez que um encadeamento que não funciona não estará usando muito da CPU. (B) geralmente será um atraso no processamento de solicitações à medida que elas chegarem, conforme for necessário aguardar a disponibilidade de um encadeamento.
É por isso que você mede. Como você afirma, a grande maioria dos seus threads estará aguardando uma resposta do banco de dados para que eles não estejam em execução. Existem dois fatores que afetam quantos threads você deve permitir.
O primeiro é o número de conexões de banco de dados disponíveis. Esse pode ser um limite rígido, a menos que você possa aumentá-lo no DBMS - presumo que seu DBMS possa ter um número ilimitado de conexões nesse caso (embora você deva medir isso também).
Então, o número de threads que você deve ter depende do seu uso histórico. O mínimo que você deve executar é o número mínimo que você já executou + A%, com um mínimo absoluto de (por exemplo, e configurá-lo como A) 5.
O número máximo de threads deve ser o seu máximo histórico + B%.
Você também deve monitorar as mudanças de comportamento. Se, por algum motivo, seu uso atingir 100% da disponibilidade por um tempo significativo (para afetar o desempenho dos clientes), você deverá aumentar o máximo permitido até que seja novamente B% mais alto.
Em resposta ao "o que exatamente devo medir?" questão:
O que você deve medir especificamente é a quantidade máxima de encadeamentos em uso simultâneo (por exemplo, aguardando um retorno da chamada do DB) sob carga. Em seguida, adicione um fator de segurança de 10%, por exemplo (enfatizado, pois outros pôsteres parecem usar meus exemplos como recomendações fixas).
Além disso, isso deve ser feito no ambiente de produção para ajuste. Não há problema em obter uma estimativa antecipadamente, mas você nunca sabe qual produção será o seu caminho (e é por isso que todas essas coisas devem ser configuráveis em tempo de execução). Isso é para capturar uma situação como duplicação inesperada das chamadas de clientes que chegam.