목표
일반 thread 와 가상 thread 속도 비교하기(IO작업)
일반 thread 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; import java.time.Instant; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit;
public class PlatformThreadTest { public static void main(String[] args) throws Exception { var client = HttpClient.newHttpClient(); var request = HttpRequest.newBuilder() .uri(new URI("http://localhost:4000/")) .build();
int totalRequests = 100000; int batchSize = 100; int numBatches = totalRequests / batchSize;
Instant start = Instant.now();
for (int batch = 0; batch < numBatches; batch++) { var executor = Executors.newFixedThreadPool(batchSize); CompletableFuture<?>[] futures = new CompletableFuture<?>[batchSize];
for (int i = 0; i < batchSize; i++) { futures[i] = CompletableFuture.runAsync(() -> { try { HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); } catch (Exception e) { e.printStackTrace(); } }, executor); }
CompletableFuture.allOf(futures).join(); executor.shutdown(); executor.awaitTermination(1, TimeUnit.MINUTES); }
Instant end = Instant.now(); System.out.println("Time taken with platform threads: " + Duration.between(start, end).toMillis() + " ms"); } }
|
가상 thread 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; import java.time.Instant; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit;
public class VirtualThreadTest { public static void main(String[] args) throws Exception { var client = HttpClient.newHttpClient(); var request = HttpRequest.newBuilder() .uri(new URI("http://localhost:4000/")) .build();
int totalRequests = 100000; int batchSize = 100; int numBatches = totalRequests / batchSize;
Instant start = Instant.now();
for (int batch = 0; batch < numBatches; batch++) { var executor = Executors.newVirtualThreadPerTaskExecutor(); CompletableFuture<?>[] futures = new CompletableFuture<?>[batchSize];
for (int i = 0; i < batchSize; i++) { futures[i] = CompletableFuture.runAsync(() -> { try { HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); } catch (Exception e) { e.printStackTrace(); } }, executor); }
CompletableFuture.allOf(futures).join(); executor.shutdown(); executor.awaitTermination(1, TimeUnit.MINUTES); }
Instant end = Instant.now(); System.out.println("Time taken with virtual threads: " + Duration.between(start, end).toMillis() + " ms"); } }
|
server 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const http = require('http');
const hostname = '127.0.0.1'; const port = 4000;
const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello, World!\n'); });
server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
|
- client 10만 request 결과
- 일반 thread 12초
- 가상 thread 6초
정리
일반, 가상 쓰레드로 각각 10만번 요청했을 때 6, 12초가 걸렸다.
cpu 연산에서는 차이가 없겠지만 IO 작업이 주 일때는 가상 쓰레드를 이용하자