|
7 | 7 | import org.slf4j.LoggerFactory; |
8 | 8 |
|
9 | 9 | import java.sql.Connection; |
| 10 | +import java.sql.PreparedStatement; |
10 | 11 | import java.sql.SQLException; |
| 12 | +import java.util.ArrayList; |
| 13 | +import java.util.List; |
11 | 14 | import java.util.Random; |
12 | 15 |
|
13 | 16 | import static org.assertj.core.api.AssertionsForClassTypes.assertThat; |
@@ -36,6 +39,7 @@ private ConnectionPool createPool() { |
36 | 39 | config.setMinConnections(2); |
37 | 40 | config.setMaxConnections(100); |
38 | 41 | config.setAutoCommit(true); |
| 42 | + config.affinityProvider(Thread::currentThread); |
39 | 43 |
|
40 | 44 | return new ConnectionPool("testspeed", config); |
41 | 45 | } |
@@ -64,6 +68,60 @@ public void test() throws SQLException { |
64 | 68 | assertThat(avgNanos).isLessThan(300); |
65 | 69 | } |
66 | 70 |
|
| 71 | + /** |
| 72 | + * Shows the benefit of affinity support. |
| 73 | + * <p> |
| 74 | + * This test starts 10 threads, where each thread has its own set of statements. |
| 75 | + * The problem is, if each thread takes the first free connection, which is most |
| 76 | + * likely the connection from an other thread, the cached pstmts are useless. |
| 77 | + * <p> |
| 78 | + * When we return the last used connection, we can increase the pstmt hit ratio: |
| 79 | + * <p> |
| 80 | + * With affinity support: psc[hit:19.800 miss:200 put:20.000 rem:0] |
| 81 | + * <p> |
| 82 | + * Without affinity support: psc[hit:7.231 miss:12.769 put:20.000 rem:12.279] |
| 83 | + */ |
| 84 | + @Test |
| 85 | + public void testMultiThread() throws Exception { |
| 86 | + warm(); |
| 87 | + |
| 88 | + total = 0; |
| 89 | + List<Thread> threads = new ArrayList<>(); |
| 90 | + for (int threadCount = 0; threadCount < 10; threadCount++) { |
| 91 | + threads.add(createThread()); |
| 92 | + } |
| 93 | + |
| 94 | + long startNano = System.nanoTime(); |
| 95 | + for (Thread thread : threads) { |
| 96 | + thread.start(); |
| 97 | + } |
| 98 | + for (Thread thread : threads) { |
| 99 | + thread.join(); |
| 100 | + } |
| 101 | + long exeNanos = System.nanoTime() - startNano; |
| 102 | + |
| 103 | + logger.info("exeNanos[{}]", exeNanos); |
| 104 | + } |
| 105 | + |
| 106 | + private Thread createThread() { |
| 107 | + return new Thread(() -> { |
| 108 | + try { |
| 109 | + for (int j = 0; j < 100; j++) { |
| 110 | + for (int k = 0; k < 20; k++) { |
| 111 | + try (Connection conn = pool.getConnection()) { |
| 112 | + try (PreparedStatement stmt = conn.prepareStatement("select '" + Thread.currentThread().getName() + "', " + k)) { |
| 113 | + stmt.execute(); |
| 114 | + } |
| 115 | + conn.rollback(); |
| 116 | + } |
| 117 | + } |
| 118 | + } |
| 119 | + } catch (SQLException e) { |
| 120 | + e.printStackTrace(); |
| 121 | + } |
| 122 | + }); |
| 123 | + } |
| 124 | + |
67 | 125 | private void perform() throws SQLException { |
68 | 126 | for (int i = 0; i < 1_000_000; i++) { |
69 | 127 | getAndCloseSome(); |
|
0 commit comments