1 8 9 package com.sleepycat.je.dbi; 10 11 import java.util.Iterator ; 12 13 import com.sleepycat.je.DatabaseException; 14 import com.sleepycat.je.EnvironmentStats; 15 import com.sleepycat.je.StatsConfig; 16 import com.sleepycat.je.config.EnvironmentParams; 17 import com.sleepycat.je.latch.LatchSupport; 18 import com.sleepycat.je.tree.BIN; 19 import com.sleepycat.je.tree.DBIN; 20 import com.sleepycat.je.tree.DIN; 21 import com.sleepycat.je.tree.IN; 22 23 29 public class MemoryBudget implements EnvConfigObserver { 30 31 52 53 private final static int LONG_OVERHEAD_32 = 16; 55 private final static int LONG_OVERHEAD_64 = 24; 56 57 private final static int BYTE_ARRAY_OVERHEAD_32 = 16; 59 private final static int BYTE_ARRAY_OVERHEAD_64 = 24; 60 61 private final static int OBJECT_OVERHEAD_32 = 8; 63 private final static int OBJECT_OVERHEAD_64 = 16; 64 65 private final static int ARRAY_ITEM_OVERHEAD_32 = 4; 67 private final static int ARRAY_ITEM_OVERHEAD_64 = 8; 68 69 private final static int HASHMAP_OVERHEAD_32 = 120; 71 private final static int HASHMAP_OVERHEAD_64 = 216; 72 73 private final static int HASHMAP_ENTRY_OVERHEAD_32 = 24; 75 private final static int HASHMAP_ENTRY_OVERHEAD_64 = 48; 76 77 private final static int HASHSET_OVERHEAD_32 = 136; 79 private final static int HASHSET_OVERHEAD_64 = 240; 80 81 private final static int HASHSET_ENTRY_OVERHEAD_32 = 24; 83 private final static int HASHSET_ENTRY_OVERHEAD_64 = 48; 84 85 private final static int TWOHASHMAPS_OVERHEAD_32 = 240; 87 private final static int TWOHASHMAPS_OVERHEAD_64 = 432; 88 89 private final static int TREEMAP_OVERHEAD_32 = 40; 91 private final static int TREEMAP_OVERHEAD_64 = 64; 92 93 private final static int TREEMAP_ENTRY_OVERHEAD_32 = 32; 95 private final static int TREEMAP_ENTRY_OVERHEAD_64 = 53; 96 97 private final static int MAPLN_OVERHEAD_32 = 464; 99 private final static int MAPLN_OVERHEAD_64 = 776; 100 101 private final static int LN_OVERHEAD_32 = 24; 103 private final static int LN_OVERHEAD_64 = 32; 104 105 private final static int DUPCOUNTLN_OVERHEAD_32 = 24; 107 private final static int DUPCOUNTLN_OVERHEAD_64 = 40; 108 109 private final static int BIN_FIXED_OVERHEAD_32_14 = 344; 111 private final static int BIN_FIXED_OVERHEAD_32_15 = 360; 112 private final static int BIN_FIXED_OVERHEAD_64_15 = 528; 113 114 private final static int DIN_FIXED_OVERHEAD_32_14 = 352; 116 private final static int DIN_FIXED_OVERHEAD_32_15 = 360; 117 private final static int DIN_FIXED_OVERHEAD_64_15 = 536; 118 119 private final static int DBIN_FIXED_OVERHEAD_32_14 = 352; 121 private final static int DBIN_FIXED_OVERHEAD_32_15 = 368; 122 private final static int DBIN_FIXED_OVERHEAD_64_15 = 544; 123 124 private final static int IN_FIXED_OVERHEAD_32_14 = 312; 126 private final static int IN_FIXED_OVERHEAD_32_15 = 320; 127 private final static int IN_FIXED_OVERHEAD_64_15 = 472; 128 129 private final static int KEY_OVERHEAD_32 = 16; 131 private final static int KEY_OVERHEAD_64 = 24; 132 133 private final static int LOCK_OVERHEAD_32 = 32; 135 private final static int LOCK_OVERHEAD_64 = 56; 136 137 private final static int LOCKINFO_OVERHEAD_32 = 16; 139 private final static int LOCKINFO_OVERHEAD_64 = 32; 140 141 private final static int WRITE_LOCKINFO_OVERHEAD_32 = 32; 143 private final static int WRITE_LOCKINFO_OVERHEAD_64 = 40; 144 145 149 private final static int TXN_OVERHEAD_32_14 = 167; 151 private final static int TXN_OVERHEAD_32_15 = 175; 152 private final static int TXN_OVERHEAD_64_15 = 293; 153 154 private final static int CHECKPOINT_REFERENCE_SIZE_32_14 = 32 + 156 HASHSET_ENTRY_OVERHEAD_32; 157 private final static int CHECKPOINT_REFERENCE_SIZE_32_15 = 40 + 158 HASHSET_ENTRY_OVERHEAD_32; 159 private final static int CHECKPOINT_REFERENCE_SIZE_64_15 = 56 + 160 HASHSET_ENTRY_OVERHEAD_64; 161 162 163 private final static int UTILIZATION_PROFILE_ENTRY_32 = 96; 165 private final static int UTILIZATION_PROFILE_ENTRY_64 = 144; 166 167 168 private final static int TFS_LIST_INITIAL_OVERHEAD_32 = 464; 170 private final static int TFS_LIST_INITIAL_OVERHEAD_64 = 504; 171 172 private final static int TFS_LIST_SEGMENT_OVERHEAD_32 = 440; 174 private final static int TFS_LIST_SEGMENT_OVERHEAD_64 = 464; 175 176 private final static int LN_INFO_OVERHEAD_32 = 24; 178 private final static int LN_INFO_OVERHEAD_64 = 48; 179 180 181 private final static int LONG_LIST_PER_ITEM_OVERHEAD_32 = 20; 183 private final static int LONG_LIST_PER_ITEM_OVERHEAD_64 = 32; 184 185 public final static int LONG_OVERHEAD; 186 public final static int BYTE_ARRAY_OVERHEAD; 187 public final static int OBJECT_OVERHEAD; 188 public final static int ARRAY_ITEM_OVERHEAD; 189 public final static int HASHMAP_OVERHEAD; 190 public final static int HASHMAP_ENTRY_OVERHEAD; 191 public final static int HASHSET_OVERHEAD; 192 public final static int HASHSET_ENTRY_OVERHEAD; 193 public final static int TWOHASHMAPS_OVERHEAD; 194 public final static int TREEMAP_OVERHEAD; 195 public final static int TREEMAP_ENTRY_OVERHEAD; 196 public final static int MAPLN_OVERHEAD; 197 public final static int LN_OVERHEAD; 198 public final static int DUPCOUNTLN_OVERHEAD; 199 public final static int BIN_FIXED_OVERHEAD; 200 public final static int DIN_FIXED_OVERHEAD; 201 public final static int DBIN_FIXED_OVERHEAD; 202 public final static int IN_FIXED_OVERHEAD; 203 public final static int KEY_OVERHEAD; 204 public final static int LOCK_OVERHEAD; 205 public final static int LOCKINFO_OVERHEAD; 206 public final static int WRITE_LOCKINFO_OVERHEAD; 207 public final static int TXN_OVERHEAD; 208 public final static int CHECKPOINT_REFERENCE_SIZE; 209 public final static int UTILIZATION_PROFILE_ENTRY; 210 public final static int TFS_LIST_INITIAL_OVERHEAD; 211 public final static int TFS_LIST_SEGMENT_OVERHEAD; 212 public final static int LN_INFO_OVERHEAD; 213 public final static int LONG_LIST_PER_ITEM_OVERHEAD; 214 215 private final static String JVM_ARCH_PROPERTY = "sun.arch.data.model"; 216 private final static String FORCE_JVM_ARCH = "je.forceJVMArch"; 217 218 static { 219 boolean is64 = false; 220 boolean isJVM14 = (LatchSupport.getJava5LatchClass() == null); 221 String overrideArch = System.getProperty(FORCE_JVM_ARCH); 222 try { 223 if (overrideArch == null) { 224 String arch = System.getProperty(JVM_ARCH_PROPERTY); 225 if (arch != null) { 226 is64 = Integer.parseInt(arch) == 64; 227 } 228 } else { 229 is64 = Integer.parseInt(overrideArch) == 64; 230 } 231 } catch (NumberFormatException NFE) { 232 NFE.printStackTrace(System.err); 233 } 234 235 if (is64) { 236 if (isJVM14) { 237 RuntimeException RE = new RuntimeException 238 ("1.4 based 64 bit JVM not supported"); 239 RE.printStackTrace(System.err); 240 throw RE; 241 } 242 LONG_OVERHEAD = LONG_OVERHEAD_64; 243 BYTE_ARRAY_OVERHEAD = BYTE_ARRAY_OVERHEAD_64; 244 OBJECT_OVERHEAD = OBJECT_OVERHEAD_64; 245 ARRAY_ITEM_OVERHEAD = ARRAY_ITEM_OVERHEAD_64; 246 HASHMAP_OVERHEAD = HASHMAP_OVERHEAD_64; 247 HASHMAP_ENTRY_OVERHEAD = HASHMAP_ENTRY_OVERHEAD_64; 248 HASHSET_OVERHEAD = HASHSET_OVERHEAD_64; 249 HASHSET_ENTRY_OVERHEAD = HASHSET_ENTRY_OVERHEAD_64; 250 TWOHASHMAPS_OVERHEAD = TWOHASHMAPS_OVERHEAD_64; 251 TREEMAP_OVERHEAD = TREEMAP_OVERHEAD_64; 252 TREEMAP_ENTRY_OVERHEAD = TREEMAP_ENTRY_OVERHEAD_64; 253 MAPLN_OVERHEAD = MAPLN_OVERHEAD_64; 254 LN_OVERHEAD = LN_OVERHEAD_64; 255 DUPCOUNTLN_OVERHEAD = DUPCOUNTLN_OVERHEAD_64; 256 BIN_FIXED_OVERHEAD = BIN_FIXED_OVERHEAD_64_15; 257 DIN_FIXED_OVERHEAD = DIN_FIXED_OVERHEAD_64_15; 258 DBIN_FIXED_OVERHEAD = DBIN_FIXED_OVERHEAD_64_15; 259 IN_FIXED_OVERHEAD = IN_FIXED_OVERHEAD_64_15; 260 TXN_OVERHEAD = TXN_OVERHEAD_64_15; 261 CHECKPOINT_REFERENCE_SIZE = CHECKPOINT_REFERENCE_SIZE_64_15; 262 KEY_OVERHEAD = KEY_OVERHEAD_64; 263 LOCK_OVERHEAD = LOCK_OVERHEAD_64; 264 LOCKINFO_OVERHEAD = LOCKINFO_OVERHEAD_64; 265 WRITE_LOCKINFO_OVERHEAD = WRITE_LOCKINFO_OVERHEAD_64; 266 UTILIZATION_PROFILE_ENTRY = UTILIZATION_PROFILE_ENTRY_64; 267 TFS_LIST_INITIAL_OVERHEAD = TFS_LIST_INITIAL_OVERHEAD_64; 268 TFS_LIST_SEGMENT_OVERHEAD = TFS_LIST_SEGMENT_OVERHEAD_64; 269 LN_INFO_OVERHEAD = LN_INFO_OVERHEAD_64; 270 LONG_LIST_PER_ITEM_OVERHEAD = LONG_LIST_PER_ITEM_OVERHEAD_64; 271 } else { 272 LONG_OVERHEAD = LONG_OVERHEAD_32; 273 BYTE_ARRAY_OVERHEAD = BYTE_ARRAY_OVERHEAD_32; 274 OBJECT_OVERHEAD = OBJECT_OVERHEAD_32; 275 ARRAY_ITEM_OVERHEAD = ARRAY_ITEM_OVERHEAD_32; 276 HASHMAP_OVERHEAD = HASHMAP_OVERHEAD_32; 277 HASHMAP_ENTRY_OVERHEAD = HASHMAP_ENTRY_OVERHEAD_32; 278 HASHSET_OVERHEAD = HASHSET_OVERHEAD_32; 279 HASHSET_ENTRY_OVERHEAD = HASHSET_ENTRY_OVERHEAD_32; 280 TWOHASHMAPS_OVERHEAD = TWOHASHMAPS_OVERHEAD_32; 281 TREEMAP_OVERHEAD = TREEMAP_OVERHEAD_32; 282 TREEMAP_ENTRY_OVERHEAD = TREEMAP_ENTRY_OVERHEAD_32; 283 MAPLN_OVERHEAD = MAPLN_OVERHEAD_32; 284 LN_OVERHEAD = LN_OVERHEAD_32; 285 DUPCOUNTLN_OVERHEAD = DUPCOUNTLN_OVERHEAD_32; 286 if (isJVM14) { 287 BIN_FIXED_OVERHEAD = BIN_FIXED_OVERHEAD_32_14; 288 DIN_FIXED_OVERHEAD = DIN_FIXED_OVERHEAD_32_14; 289 DBIN_FIXED_OVERHEAD = DBIN_FIXED_OVERHEAD_32_14; 290 IN_FIXED_OVERHEAD = IN_FIXED_OVERHEAD_32_14; 291 TXN_OVERHEAD = TXN_OVERHEAD_32_14; 292 CHECKPOINT_REFERENCE_SIZE = CHECKPOINT_REFERENCE_SIZE_32_14; 293 } else { 294 BIN_FIXED_OVERHEAD = BIN_FIXED_OVERHEAD_32_15; 295 DIN_FIXED_OVERHEAD = DIN_FIXED_OVERHEAD_32_15; 296 DBIN_FIXED_OVERHEAD = DBIN_FIXED_OVERHEAD_32_15; 297 IN_FIXED_OVERHEAD = IN_FIXED_OVERHEAD_32_15; 298 TXN_OVERHEAD = TXN_OVERHEAD_32_15; 299 CHECKPOINT_REFERENCE_SIZE = CHECKPOINT_REFERENCE_SIZE_32_15; 300 } 301 KEY_OVERHEAD = KEY_OVERHEAD_32; 302 LOCK_OVERHEAD = LOCK_OVERHEAD_32; 303 LOCKINFO_OVERHEAD = LOCKINFO_OVERHEAD_32; 304 WRITE_LOCKINFO_OVERHEAD = WRITE_LOCKINFO_OVERHEAD_32; 305 UTILIZATION_PROFILE_ENTRY = UTILIZATION_PROFILE_ENTRY_32; 306 TFS_LIST_INITIAL_OVERHEAD = TFS_LIST_INITIAL_OVERHEAD_32; 307 TFS_LIST_SEGMENT_OVERHEAD = TFS_LIST_SEGMENT_OVERHEAD_32; 308 LN_INFO_OVERHEAD = LN_INFO_OVERHEAD_32; 309 LONG_LIST_PER_ITEM_OVERHEAD = LONG_LIST_PER_ITEM_OVERHEAD_32; 310 } 311 } 312 313 314 public final static long MIN_MAX_MEMORY_SIZE = 96 * 1024; 315 public final static String MIN_MAX_MEMORY_SIZE_STRING = 316 Long.toString(MIN_MAX_MEMORY_SIZE); 317 318 private final static long N_64MB = (1 << 26); 319 320 327 328 331 private long treeMemoryUsage; 332 333 336 private long miscMemoryUsage; 337 338 341 private Object memoryUsageSynchronizer = new Object (); 342 343 346 private int nLockTables; 347 348 353 private long[] lockMemoryUsage; 354 355 359 private long maxMemory; 360 private long criticalThreshold; 362 363 private long logBufferBudget; 364 365 366 private long trackerBudget; 367 368 372 private long cacheBudget; 373 374 377 private long inOverhead; 378 private long binOverhead; 379 private long dinOverhead; 380 private long dbinOverhead; 381 382 private EnvironmentImpl envImpl; 383 384 MemoryBudget(EnvironmentImpl envImpl, 385 DbConfigManager configManager) 386 throws DatabaseException { 387 388 this.envImpl = envImpl; 389 390 391 envImpl.addConfigObserver(this); 392 393 394 reset(configManager); 395 396 403 inOverhead = IN.computeOverhead(configManager); 404 binOverhead = BIN.computeOverhead(configManager); 405 dinOverhead = DIN.computeOverhead(configManager); 406 dbinOverhead = DBIN.computeOverhead(configManager); 407 } 408 409 412 public void envConfigUpdate(DbConfigManager configManager) 413 throws DatabaseException { 414 415 420 long oldLogBufferBudget = logBufferBudget; 421 reset(configManager); 422 if (oldLogBufferBudget != logBufferBudget) { 423 envImpl.getLogManager().resetPool(configManager); 424 } 425 } 426 427 430 private void reset(DbConfigManager configManager) 431 throws DatabaseException { 432 433 439 long newMaxMemory = 440 configManager.getLong(EnvironmentParams.MAX_MEMORY); 441 long jvmMemory = getRuntimeMaxMemory(); 442 443 if (newMaxMemory != 0) { 444 445 if (jvmMemory < newMaxMemory) { 446 throw new IllegalArgumentException 447 (EnvironmentParams.MAX_MEMORY.getName() + 448 " has a value of " + newMaxMemory + 449 " but the JVM is only configured for " + 450 jvmMemory + 451 ". Consider using je.maxMemoryPercent."); 452 } 453 if (newMaxMemory < MIN_MAX_MEMORY_SIZE) { 454 throw new IllegalArgumentException 455 (EnvironmentParams.MAX_MEMORY.getName() + 456 " is " + newMaxMemory + 457 " which is less than the minimum: " + 458 MIN_MAX_MEMORY_SIZE); 459 } 460 } else { 461 462 467 if (jvmMemory == Long.MAX_VALUE) { 468 jvmMemory = N_64MB; 469 } 470 471 472 int maxMemoryPercent = 473 configManager.getInt(EnvironmentParams.MAX_MEMORY_PERCENT); 474 newMaxMemory = (maxMemoryPercent * jvmMemory) / 100; 475 } 476 477 486 long newLogBufferBudget = 487 configManager.getLong(EnvironmentParams.LOG_MEM_SIZE); 488 if (newLogBufferBudget == 0) { 489 newLogBufferBudget = newMaxMemory >> 4; 490 } else if (newLogBufferBudget > newMaxMemory / 2) { 491 newLogBufferBudget = newMaxMemory / 2; 492 } 493 494 499 int numBuffers = 500 configManager.getInt(EnvironmentParams.NUM_LOG_BUFFERS); 501 long startingBufferSize = newLogBufferBudget / numBuffers; 502 int logBufferSize = 503 configManager.getInt(EnvironmentParams.LOG_BUFFER_MAX_SIZE); 504 if (startingBufferSize > logBufferSize) { 505 startingBufferSize = logBufferSize; 506 newLogBufferBudget = numBuffers * startingBufferSize; 507 } else if (startingBufferSize < 508 EnvironmentParams.MIN_LOG_BUFFER_SIZE) { 509 startingBufferSize = EnvironmentParams.MIN_LOG_BUFFER_SIZE; 510 newLogBufferBudget = numBuffers * startingBufferSize; 511 } 512 513 long newCriticalThreshold = 514 (newMaxMemory * 515 envImpl.getConfigManager().getInt 516 (EnvironmentParams.EVICTOR_CRITICAL_PERCENTAGE))/100; 517 518 long newTrackerBudget = 519 (newMaxMemory * 520 envImpl.getConfigManager().getInt 521 (EnvironmentParams.CLEANER_DETAIL_MAX_MEMORY_PERCENTAGE))/100; 522 523 528 maxMemory = newMaxMemory; 529 criticalThreshold = newCriticalThreshold; 530 logBufferBudget = newLogBufferBudget; 531 trackerBudget = newTrackerBudget; 532 cacheBudget = newMaxMemory - newLogBufferBudget; 533 nLockTables = 534 configManager.getInt(EnvironmentParams.N_LOCK_TABLES); 535 lockMemoryUsage = new long[nLockTables]; 536 } 537 538 543 public static long getRuntimeMaxMemory() { 544 545 546 if ("Mac OS X".equals(System.getProperty("os.name"))) { 547 String jvmVersion = System.getProperty("java.version"); 548 if (jvmVersion != null && jvmVersion.startsWith("1.4.2")) { 549 return Long.MAX_VALUE; 550 } 551 } 552 553 return Runtime.getRuntime().maxMemory(); 554 } 555 556 559 void initCacheMemoryUsage() 560 throws DatabaseException { 561 562 synchronized (memoryUsageSynchronizer) { 563 treeMemoryUsage = calcTreeCacheUsage(); 564 } 565 assert LatchSupport.countLatchesHeld() == 0; 566 } 567 568 571 public long calcTreeCacheUsage() 572 throws DatabaseException { 573 574 long totalSize = 0; 575 INList inList = envImpl.getInMemoryINs(); 576 577 inList.latchMajor(); 578 try { 579 Iterator iter = inList.iterator(); 580 while (iter.hasNext()) { 581 IN in = (IN) iter.next(); 582 long size = in.getInMemorySize(); 583 totalSize += size; 584 } 585 } finally { 586 inList.releaseMajorLatch(); 587 } 588 return totalSize; 589 } 590 591 596 public void updateTreeMemoryUsage(long increment) { 597 synchronized (memoryUsageSynchronizer) { 598 treeMemoryUsage += increment; 599 } 600 if (getCacheMemoryUsage() > cacheBudget) { 601 envImpl.alertEvictor(); 602 } 603 } 604 605 610 public void updateMiscMemoryUsage(long increment) { 611 synchronized (memoryUsageSynchronizer) { 612 miscMemoryUsage += increment; 613 } 614 if (getCacheMemoryUsage() > cacheBudget) { 615 envImpl.alertEvictor(); 616 } 617 } 618 619 public void updateLockMemoryUsage(long increment, int lockTableIndex) { 620 lockMemoryUsage[lockTableIndex] += increment; 621 if (getCacheMemoryUsage() > cacheBudget) { 622 envImpl.alertEvictor(); 623 } 624 } 625 626 public long accumulateNewUsage(IN in, long newSize) { 627 return in.getInMemorySize() + newSize; 628 } 629 630 public void refreshTreeMemoryUsage(long newSize) { 631 synchronized (memoryUsageSynchronizer) { 632 treeMemoryUsage = newSize; 633 } 634 } 635 636 public long getCacheMemoryUsage() { 637 long accLockMemoryUsage = 0; 638 if (nLockTables == 1) { 639 accLockMemoryUsage = lockMemoryUsage[0]; 640 } else { 641 for (int i = 0; i < nLockTables; i++) { 642 accLockMemoryUsage += lockMemoryUsage[i]; 643 } 644 } 645 return treeMemoryUsage + miscMemoryUsage + accLockMemoryUsage; 646 } 647 648 651 public long getTreeMemoryUsage() { 652 return treeMemoryUsage; 653 } 654 655 public long getLogBufferBudget() { 656 return logBufferBudget; 657 } 658 659 public long getTrackerBudget() { 660 return trackerBudget; 661 } 662 663 public long getMaxMemory() { 664 return maxMemory; 665 } 666 667 public long getCriticalThreshold() { 668 return criticalThreshold; 669 } 670 671 public long getCacheBudget() { 672 return cacheBudget; 673 } 674 675 public long getINOverhead() { 676 return inOverhead; 677 } 678 679 public long getBINOverhead() { 680 return binOverhead; 681 } 682 683 public long getDINOverhead() { 684 return dinOverhead; 685 } 686 687 public long getDBINOverhead() { 688 return dbinOverhead; 689 } 690 691 694 public static int byteArraySize(int arrayLen) { 695 696 700 int size = BYTE_ARRAY_OVERHEAD; 701 if (arrayLen > 4) { 702 size += ((arrayLen - 4 + 7) / 8) * 8; 703 } 704 705 return size; 706 } 707 708 void loadStats(StatsConfig config, EnvironmentStats stats) { 709 stats.setCacheDataBytes(getCacheMemoryUsage()); 710 } 711 } 712 | Popular Tags |