Ustawienia pamięci z tysiącami wątków

Bawię się z JVM (Oracle 1.7 64 bit) na Linux-ie (AMD 6 Core, 16 GB RAM), aby zobaczyć, jak liczba wątków w aplikacji wpływa na wydajność. Mam nadzieję zmierzyć, w którym momencie przełączanie kontekstu obniża wydajność.

Stworzyłem małą aplikację, która tworzy pulę wykonywania wątków:

Executors.newFixedThreadPool(numThreads)

Dostosowuję sięnumThreads za każdym razem, gdy uruchamiam program, aby zobaczyć jego efekt.

Następnie przesyłamnumThread zadania (wystąpieniajava.util.concurrent.Callable) do basenu. Każdy z nich zwiększaAtomicInteger, działa trochę (tworzy tablicę losowych liczb całkowitych i tasuje ją), a potem trochę śpi. Chodzi o symulację wywołania usługi internetowej. Wreszcie zadanie ponownie przesyła się do puli, więc zawsze mamnumThreads praca działa.

Zmierzam przepustowość, podobnie jak liczbę zadań przetwarzanych na minutę.

Dzięki kilku tysiącom wątków mogę przetwarzać do 400 000 zadań na minutę. Powyżej 8000 wątków wyniki zaczynają się znacznie różnić, co sugeruje, że zmiana kontekstu staje się problemem. Ale mogę nadal zwiększać liczbę wątków do 30 000 i nadal uzyskiwać wyższą przepustowość (od 420 000 do 570 000 miejsc pracy na minutę).

Teraz pytanie: dostajęjava.lang.OutOfMemoryError: Unable to create new native thread z ponad 31 000 miejsc pracy. Próbowałem ustawienia-Xmx6000M co nie pomaga. Próbowałem się bawić-Xss ale to też nie pomaga.

Przeczytałem toulimit może być przydatny, ale coraz większyulimit -u 64000 nic nie zmieniłem.

Dla informacji:

[root@apollo ant]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 127557
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

Pytanie nr 1: Co muszę zrobić, aby stworzyć większą pulę wątków?

Pytanie 2: Na jakim etapie powinienem się spodziewać przełączenia kontekstu, co naprawdę zmniejsza przepustowość i powoduje, że proces zatrzymuje się?

Oto kilka wyników, po tym jak zmodyfikowałem go, aby wykonać trochę więcej przetwarzania (jak sugerowano) i zacząłem rejestrować średni czas odpowiedzi (jak również zasugerowano).

// ( (n_cores x t_request) / (t_request - t_wait) ) + 1
// 300 ms wait, 10ms work, roughly 310ms per job => ideal response time, 310ms
// ideal num threads = 1860 / 10 + 1 = 187 threads
//
// results:
//
//   100 =>  19,000 thruput,  312ms response, cpu < 50%
//   150 =>  28,500 thruput,  314ms response, cpu 50%
//   180 =>  34,000 thruput,  318ms response, cpu 60%
//   190 =>  35,800 thruput,  317ms response, cpu 65%
//   200 =>  37,800 thruput,  319ms response, cpu 70%
//   230 =>  42,900 thruput,  321ms response, cpu 80%
//   270 =>  50,000 thruput,  324ms response, cpu 80%
//   350 =>  64,000 thruput,  329ms response, cpu 90%
//   400 =>  72,000 thruput,  335ms response, cpu >90%
//   500 =>  87,500 thruput,  343ms response, cpu >95%
//   700 => 100,000 thruput,  430ms response, cpu >99%
//  1000 => 100,000 thruput,  600ms response, cpu >99%
//  2000 => 105,000 thruput, 1100ms response, cpu >99%
//  5000 => 131,000 thruput, 1600ms response, cpu >99%
// 10000 => 131,000 thruput, 2700ms response, cpu >99%,  16GB Virtual size
// 20000 => 140,000 thruput, 4000ms response, cpu >99%,  27GB Virtual size
// 30000 => 133,000 thruput, 2800ms response, cpu >99%,  37GB Virtual size
// 40000 =>       - thruput,    -ms response, cpu >99%, >39GB Virtual size => java.lang.OutOfMemoryError: unable to create new native thread

Interpretuję je jako:

1) Nawet jeśli aplikacja śpi przez 96,7% czasu, co nadal pozostawia wiele przełączania wątków do wykonania 2) Przełączanie kontekstu jest mierzalne i jest pokazywane w czasie odpowiedzi.

Interesujące jest to, że podczas strojenia aplikacji możesz wybrać akceptowalny czas odpowiedzi, powiedzmy 400ms, i zwiększyć liczbę wątków, aż uzyskasz ten czas odpowiedzi, co w tym przypadku pozwoliłoby aplikacji na przetworzenie około 95 tysięcy żądań minuta.

Często ludzie mówią, że idealna liczba wątków jest bliska liczbie rdzeni. W aplikacjach, które mają czas oczekiwania (zablokowane wątki, powiedzmy, że oczekują na odpowiedź bazy danych lub usługi internetowej), obliczenia muszą to uwzględnić (zobacz moje równanie powyżej). Ale nawet ten teoretyczny ideał nie jest rzeczywistym ideałem, gdy patrzysz na wyniki lub gdy nastawiasz na określony czas reakcji.

questionAnswers(2)

yourAnswerToTheQuestion