@@ -207,212 +207,9 @@ private String csv(String value) {
207207 String escaped = value .replace ("\" " , "\" \" " ).replace ("\\ " , "\\ \\ " );
208208 return '"' + escaped + '"' ;
209209 }
210- /**
211- * 5. LOCK CONTENTION LOAD - Maximum database lock pressure and concurrent access
212- * Creates lock contention scenarios with multiple threads competing for same resources
213- */
214- public void createLockContentionLoad (int numberOfThreads , int durationSeconds ) {
215- logger .warn ("Starting LOCK CONTENTION load test with {} threads for {} seconds - This will create MASSIVE lock contention!" ,
216- numberOfThreads , durationSeconds );
217- long startTime = System .currentTimeMillis ();
218- long endTime = startTime + (durationSeconds * 1000L );
219-
220- try {
221- // Create a shared list to track thread results
222- List <String > threadResults = new ArrayList <>();
223- List <Thread > threads = new ArrayList <>();
224-
225- // Create multiple competing threads
226- for (int t = 0 ; t < numberOfThreads ; t ++) {
227- final int threadId = t ;
228- Thread lockContentionThread = new Thread (() -> {
229- try {
230- createLockContentionForThread (threadId , endTime , threadResults );
231- } catch (Exception e ) {
232- logger .error ("Error in lock contention thread {}" , threadId , e );
233- }
234- });
235-
236- lockContentionThread .setName ("LockContentionThread-" + threadId );
237- threads .add (lockContentionThread );
238- }
239-
240- // Start all threads simultaneously
241- logger .info ("Starting {} lock contention threads..." , numberOfThreads );
242- for (Thread thread : threads ) {
243- thread .start ();
244- }
245-
246- // Wait for all threads to complete
247- for (Thread thread : threads ) {
248- try {
249- thread .join ();
250- } catch (InterruptedException e ) {
251- Thread .currentThread ().interrupt ();
252- logger .warn ("Interrupted while waiting for thread: {}" , thread .getName ());
253- }
254- }
255-
256- long actualEndTime = System .currentTimeMillis ();
257- logger .warn ("Completed LOCK CONTENTION load test in {} ms with {} threads. Results: {}" ,
258- (actualEndTime - startTime ), numberOfThreads , threadResults .size ());
259-
260- } catch (Exception e ) {
261- logger .error ("Error during lock contention load test" , e );
262- throw new RuntimeException ("Error during lock contention load test: " + e .getMessage (), e );
263- }
264- }
265-
266- private void createLockContentionForThread (int threadId , long endTime , List <String > threadResults ) {
267- Faker faker = new Faker (new Locale ("en-US" ));
268- int operationCount = 0 ;
269-
270- while (System .currentTimeMillis () < endTime ) {
271- DefaultTransactionDefinition def = new DefaultTransactionDefinition ();
272- def .setPropagationBehavior (TransactionDefinition .PROPAGATION_REQUIRES_NEW );
273-
274- // Vary isolation levels to create different lock behaviors
275- switch (threadId % 4 ) {
276- case 0 :
277- def .setIsolationLevel (TransactionDefinition .ISOLATION_READ_COMMITTED );
278- break ;
279- case 1 :
280- def .setIsolationLevel (TransactionDefinition .ISOLATION_REPEATABLE_READ );
281- break ;
282- case 2 :
283- def .setIsolationLevel (TransactionDefinition .ISOLATION_SERIALIZABLE );
284- break ;
285- default :
286- def .setIsolationLevel (TransactionDefinition .ISOLATION_READ_UNCOMMITTED );
287- break ;
288- }
289-
290- TransactionStatus status = transactionManager .getTransaction (def );
291-
292- try {
293- // Strategy 1: Compete for same high-value records (guaranteed contention)
294- if (operationCount % 5 == 0 ) {
295- // All threads fight for the same "high value" records
296- List <Map <String , Object >> contestedRecords = jdbcTemplate .queryForList (
297- "SELECT * FROM clinic_activity_logs WHERE numeric_value BETWEEN 90000 AND 100000 " +
298- "ORDER BY numeric_value DESC LIMIT 10 FOR UPDATE" );
299-
300- // Update these contested records
301- for (Map <String , Object > record : contestedRecords ) {
302- jdbcTemplate .update (
303- "UPDATE clinic_activity_logs SET payload = ?, numeric_value = ? WHERE id = ?" ,
304- "CONTESTED_UPDATE_THREAD_" + threadId + "_OP_" + operationCount + " " + faker .lorem ().sentence (20 ),
305- faker .number ().numberBetween (90000 , 100000 ),
306- record .get ("id" ));
307- }
308- }
309-
310- // Strategy 2: Create deadlock scenarios (lock ordering conflicts)
311- else if (operationCount % 5 == 1 ) {
312- if (threadId % 2 == 0 ) {
313- // Even threads: Lock A then B
314- jdbcTemplate .queryForList (
315- "SELECT * FROM clinic_activity_logs WHERE id BETWEEN 1 AND 50 ORDER BY id FOR UPDATE" );
316- Thread .sleep (10 ); // Small delay to increase deadlock chance
317- jdbcTemplate .queryForList (
318- "SELECT * FROM clinic_activity_logs WHERE id BETWEEN 51 AND 100 ORDER BY id FOR UPDATE" );
319- } else {
320- // Odd threads: Lock B then A (reverse order = deadlock risk)
321- jdbcTemplate .queryForList (
322- "SELECT * FROM clinic_activity_logs WHERE id BETWEEN 51 AND 100 ORDER BY id DESC FOR UPDATE" );
323- Thread .sleep (10 );
324- jdbcTemplate .queryForList (
325- "SELECT * FROM clinic_activity_logs WHERE id BETWEEN 1 AND 50 ORDER BY id DESC FOR UPDATE" );
326- }
327- }
328-
329- // Strategy 3: Table-level lock contention
330- else if (operationCount % 5 == 2 ) {
331- // Force table scan with update (creates many row locks)
332- jdbcTemplate .update (
333- "UPDATE clinic_activity_logs SET payload = payload || ? WHERE activity_type = ? AND LENGTH(payload) < 5000" ,
334- " [THREAD_" + threadId + "_SCAN_UPDATE]" ,
335- ACTIVITY_TYPES .get (threadId % ACTIVITY_TYPES .size ()));
336- }
337-
338- // Strategy 4: Bulk operations causing lock escalation
339- else if (operationCount % 5 == 3 ) {
340- // Large batch update (may cause lock escalation)
341- jdbcTemplate .update (
342- "UPDATE clinic_activity_logs SET numeric_value = numeric_value + ? " +
343- "WHERE activity_type = ? AND numeric_value BETWEEN ? AND ?" ,
344- threadId ,
345- ACTIVITY_TYPES .get (threadId % ACTIVITY_TYPES .size ()),
346- threadId * 10000 ,
347- (threadId + 1 ) * 10000 );
348- }
349-
350- // Strategy 5: Long-running transaction with many locks
351- else {
352- // Hold multiple locks for extended period
353- for (int i = 0 ; i < 20 ; i ++) {
354- int targetId = (threadId * 1000 + i ) % 10000 + 1 ;
355- jdbcTemplate .queryForList (
356- "SELECT * FROM clinic_activity_logs WHERE id = ? FOR UPDATE" , targetId );
357-
358- jdbcTemplate .update (
359- "UPDATE clinic_activity_logs SET payload = ? WHERE id = ?" ,
360- "LONG_RUNNING_THREAD_" + threadId + "_LOCK_" + i + " " + faker .lorem ().sentence (10 ),
361- targetId );
362-
363- if (i % 5 == 0 ) {
364- Thread .sleep (5 ); // Hold locks longer
365- }
366- }
367- }
368-
369- transactionManager .commit (status );
370- operationCount ++;
371-
372- // Add random small delays to vary timing
373- if (operationCount % 10 == 0 ) {
374- Thread .sleep (faker .number ().numberBetween (1 , 10 ));
375- }
376-
377- } catch (Exception e ) {
378- if (!status .isCompleted ()) {
379- transactionManager .rollback (status );
380- }
381-
382- // Log deadlocks and lock timeouts (these are expected!)
383- if (e .getMessage () != null &&
384- (e .getMessage ().contains ("deadlock" ) ||
385- e .getMessage ().contains ("lock" ) ||
386- e .getMessage ().contains ("timeout" ))) {
387- logger .debug ("Expected lock contention in thread {}: {}" , threadId , e .getMessage ());
388- } else {
389- logger .error ("Unexpected error in lock contention thread {}" , threadId , e );
390- }
391-
392- try {
393- Thread .sleep (5 ); // Brief pause after error
394- } catch (InterruptedException ie ) {
395- Thread .currentThread ().interrupt ();
396- break ;
397- }
398- }
399- }
400-
401- synchronized (threadResults ) {
402- threadResults .add ("Thread-" + threadId + ": " + operationCount + " operations" );
403- }
404-
405- logger .info ("Lock contention thread {} completed {} operations" , threadId , operationCount );
406- }
407210
408- /**
409- * 6. I/O INTENSIVE LOAD - Maximum disk I/O pressure with minimal CPU/Memory usage
410- * Creates massive I/O operations with random access patterns to stress storage subsystem
411- * Uses simple queries with large data transfers to keep I/O busy while minimizing CPU/Memory usage
412- * Focuses on disk I/O bottlenecks that can be improved by faster storage or read replicas
413- */
414211 public void createIOIntensiveLoad (int durationMinutes , int numThreads , int limit ) {
415- logger .warn ("Starting I/O INTENSIVE load test for {} minutes with {} threads and {} limit - This will MAX OUT disk I/O operations!" ,
212+ logger .warn ("Starting I/O INTENSIVE load test for {} minutes with {} threads and {} limit - This will MAX OUT disk I/O operations!" ,
416213 durationMinutes , numThreads , limit );
417214 long startTime = System .currentTimeMillis ();
418215 long endTime = startTime + (durationMinutes * 60 * 1000L );
0 commit comments