480 } |
482 } |
481 |
483 |
482 public static void testMemoryUsage() throws Exception { |
484 public static void testMemoryUsage() throws Exception { |
483 // Test that memory usage is reduced after deduplication |
485 // Test that memory usage is reduced after deduplication |
484 OutputAnalyzer output; |
486 OutputAnalyzer output; |
485 final String usagePattern = "Heap Memory Usage: (\\d+)"; |
487 final String heapMemoryUsagePattern = "Heap Memory Usage: (\\d+)"; |
|
488 final String arrayHeaderSizePattern = "Array Header Size: (\\d+)"; |
486 |
489 |
487 // Run without deduplication |
490 // Run without deduplication |
488 output = MemoryUsageTest.run(false); |
491 output = MemoryUsageTest.run(false); |
489 output.shouldHaveExitValue(0); |
492 output.shouldHaveExitValue(0); |
490 final long memoryUsageWithoutDedup = Long.parseLong(output.firstMatch(usagePattern, 1)); |
493 final long heapMemoryUsageWithoutDedup = Long.parseLong(output.firstMatch(heapMemoryUsagePattern, 1)); |
|
494 final long arrayHeaderSizeWithoutDedup = Long.parseLong(output.firstMatch(arrayHeaderSizePattern, 1)); |
491 |
495 |
492 // Run with deduplication |
496 // Run with deduplication |
493 output = MemoryUsageTest.run(true); |
497 output = MemoryUsageTest.run(true); |
494 output.shouldHaveExitValue(0); |
498 output.shouldHaveExitValue(0); |
495 final long memoryUsageWithDedup = Long.parseLong(output.firstMatch(usagePattern, 1)); |
499 final long heapMemoryUsageWithDedup = Long.parseLong(output.firstMatch(heapMemoryUsagePattern, 1)); |
|
500 final long arrayHeaderSizeWithDedup = Long.parseLong(output.firstMatch(arrayHeaderSizePattern, 1)); |
|
501 |
|
502 // Sanity check to make sure one instance isn't using compressed class pointers and the other not |
|
503 if (arrayHeaderSizeWithoutDedup != arrayHeaderSizeWithDedup) { |
|
504 throw new Exception("Unexpected difference between array header sizes"); |
|
505 } |
496 |
506 |
497 // Calculate expected memory usage with deduplication enabled. This calculation does |
507 // Calculate expected memory usage with deduplication enabled. This calculation does |
498 // not take alignment and padding into account, so it's a conservative estimate. |
508 // not take alignment and padding into account, so it's a conservative estimate. |
499 final long sizeOfChar = 2; // bytes |
509 final long sizeOfChar = unsafe.ARRAY_CHAR_INDEX_SCALE; |
500 final long bytesSaved = (LargeNumberOfStrings - 1) * (StringLength * sizeOfChar + unsafe.ARRAY_CHAR_BASE_OFFSET); |
510 final long sizeOfCharArray = StringLength * sizeOfChar + arrayHeaderSizeWithoutDedup; |
501 final long memoryUsageWithDedupExpected = memoryUsageWithoutDedup - bytesSaved; |
511 final long bytesSaved = (LargeNumberOfStrings - 1) * sizeOfCharArray; |
|
512 final long heapMemoryUsageWithDedupExpected = heapMemoryUsageWithoutDedup - bytesSaved; |
502 |
513 |
503 System.out.println("Memory usage summary:"); |
514 System.out.println("Memory usage summary:"); |
504 System.out.println(" memoryUsageWithoutDedup: " + memoryUsageWithoutDedup); |
515 System.out.println(" heapMemoryUsageWithoutDedup: " + heapMemoryUsageWithoutDedup); |
505 System.out.println(" memoryUsageWithDedup: " + memoryUsageWithDedup); |
516 System.out.println(" heapMemoryUsageWithDedup: " + heapMemoryUsageWithDedup); |
506 System.out.println(" memoryUsageWithDedupExpected: " + memoryUsageWithDedupExpected); |
517 System.out.println(" heapMemoryUsageWithDedupExpected: " + heapMemoryUsageWithDedupExpected); |
507 |
518 |
508 if (memoryUsageWithDedup > memoryUsageWithDedupExpected) { |
519 if (heapMemoryUsageWithDedup > heapMemoryUsageWithDedupExpected) { |
509 throw new Exception("Unexpected memory usage, memoryUsageWithDedup should less or equal to memoryUsageWithDedupExpected"); |
520 throw new Exception("Unexpected memory usage, heapMemoryUsageWithDedup should be less or equal to heapMemoryUsageWithDedupExpected"); |
510 } |
521 } |
511 } |
522 } |
512 } |
523 } |