Począwszy od sgcWebSockets 2022.9.0 procedura obsługi IOHandler IOCP serwera Indy została przepisana od podstaw i poprawiona pod względem wydajności. IOHandler IOCP jest dostępny wyłącznie w pakiecie sgcWebSockets Enterprise.
Używając IOCP możesz uniknąć problemu „jeden-wątek-na-klienta", w którym wydajność drastycznie spada wraz ze wzrostem liczby obsługiwanych połączeń. IOCP udostępnia kilka wątków obsługujących wielu klientów jednocześnie. Wątki są zawieszone i nie zużywają cykli procesora, dopóki nie ma nic do przetworzenia.
Configuration
Aby włączyć IOCP dla serwerów Indy, przejdź do właściwości IOHandlerOptions i wybierz iohIOCP jako typ IOHandler.
Server.IOHandlerOptions.IOHandlerType := iohIOCP; Server.IOHandlerOptions.IOCP.IOCPThreads := 0; // liczba wątków IOCP zostanie obliczona automatycznie na podstawie liczby procesorów. Server.IOHandlerOptions.IOCP.WorkOpThreads := 0;
1. IOCPThreads — wątki używane do asynchronicznych żądań IOCP (operacje nakładkowe). Domyślna wartość to zero, co oznacza, że liczba wątków jest obliczana na podstawie liczby procesorów (wyjątek: Delphi 7 i 2007, gdzie liczba wątków jest ustawiana na 32, ponieważ funkcja cpucount nie jest obsługiwana).
2. WorkOpThreads — należy włączyć wyłącznie wtedy, gdy chcesz, aby połączenia były zawsze przetwarzane w tym samym wątku. Przy IOCP żądania są przetwarzane przez pulę wątków i każde żądanie (dla tego samego połączenia) może być obsłużone w innym wątku. Jeśli chcesz obsługiwać każde połączenie w tym samym wątku, ustaw w WorkOpThreads liczbę wątków do tego przeznaczonych. Wpływa to na wydajność serwera — zaleca się ustawianie wartości większej od zera wyłącznie wtedy, gdy ta funkcja jest niezbędna.
Włączenie IOCP dla serwerów Windows jest zalecane, gdy potrzebujesz obsługiwać tysiące połączeń. Jeśli serwer obsługuje maksymalnie 100 jednoczesnych połączeń, możesz pozostać przy domyślnym modelu wątków Indy.
Performance Test
Prosty test pokaże różnice między modelem wątków Indy a IOCP. Test łączy się z serwerem za pomocą protokołu WebSocket, a zużycie procesora i pamięci zostanie przedstawione w poniższej tabeli. Procentowe zużycie procesora mierzone jest podczas bezczynności serwera.
| Liczba połączeń | Indy Default IOHandler | Indy IOCP IOHandler |
| 100 | 0% (4.1MB) | 0% (3.9MB) |
| 500 | 0% (17.1MB) | 0% (7.7MB) |
| 1000 | 0% (32.2MB) | 0% (12.4MB) |
| 1500 | 7.3% (46.8MB) | 0% (17.1MB) |
| 2000 | 15.4% (61.6MB) | 0% (21.9MB) |
| 2500 | 51.9% (76.5MB) | 0% (26.5MB) |
| 3000 | 68.8% (91.7MB) | 0% (31.2MB) |
| 3500 | 72.3% (106MB) | 0% (35.9MB) |
Serwer Indy zaczął doświadczać spowolnień przy ponad 3000 jednoczesnych połączeń, najprawdopodobniej z powodu przełączania kontekstu wątków — zużycie procesora było bardzo wysokie podczas bezczynności serwera.
Serwer IOCP nie zużywał procesora w stanie bezczynności, a zużycie pamięci było również niższe.
Kolejny test mierzy czas potrzebny do połączenia 3000 klientów: każdy wysyła wiadomość po połączeniu się z serwerem, a serwer ją odbija.
| Indy Default IOHandler | Indy IOCP IOHandler | |
| Połącz 3000 klientów i odeślij wiadomość | 15.32 seconds | 6.89 seconds |
Testy wydajności zostały przeprowadzone na systemie Windows Server 2022 z 16 rdzeniami i 32 GB pamięci RAM.
