KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > dbi > MemoryBudget


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: MemoryBudget.java,v 1.54 2006/11/03 19:30:45 cwl Exp $
7  */

8
9 package com.sleepycat.je.dbi;
10
11 import java.util.Iterator JavaDoc;
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 /**
24  * MemoryBudget calculates the available memory for JE and how to apportion
25  * it between cache and log buffers. It is meant to centralize all memory
26  * calculations. Objects that ask for memory budgets should get settings from
27  * this class, rather than using the configuration parameter values directly.
28  */

29 public class MemoryBudget implements EnvConfigObserver {
30
31     /*
32      * Object overheads. These are set statically with advance measurements.
33      * Java doesn't provide a way of assessing object size dynamically. These
34      * overheads will not be precise, but are close enough to let the system
35      * behave predictably.
36      *
37      * _32 values are the same on Windows and Solaris.
38      * _64 values are from 1.5.0_05 on Solaris.
39      * _14 values are from 1.4.2 on Windows and Solaris.
40      * _15 values are from 1.5.0_05 on Solaris and Windows.
41      *
42      * Specifically:
43      *
44      * java.vm.version=1.5.0_05_b05 os.name=SunOS
45      * java.vm.version=1.4.2_05_b04 os.name=SunOS
46      * java.vm.version=1.5.0_04_b05, os.name=Windows XP
47      * java.vm.version=1.4.2_06-b03, os.name=Windows XP
48      *
49      * The integer following the // below is the Sizeof argument used to
50      * compute the value.
51      */

52
53     // 7
54
private final static int LONG_OVERHEAD_32 = 16;
55     private final static int LONG_OVERHEAD_64 = 24;
56
57     // 8 - 2560
58
private final static int BYTE_ARRAY_OVERHEAD_32 = 16;
59     private final static int BYTE_ARRAY_OVERHEAD_64 = 24;
60
61     // 2
62
private final static int OBJECT_OVERHEAD_32 = 8;
63     private final static int OBJECT_OVERHEAD_64 = 16;
64
65     // (4 - BYTE_ARRAY_OVERHEAD_32) / 256
66
private final static int ARRAY_ITEM_OVERHEAD_32 = 4;
67     private final static int ARRAY_ITEM_OVERHEAD_64 = 8;
68
69     // 20
70
private final static int HASHMAP_OVERHEAD_32 = 120;
71     private final static int HASHMAP_OVERHEAD_64 = 216;
72
73     // 21 - OBJECT_OVERHEAD_32 - HASHMAP_OVERHEAD_32
74
private final static int HASHMAP_ENTRY_OVERHEAD_32 = 24;
75     private final static int HASHMAP_ENTRY_OVERHEAD_64 = 48;
76
77     // 22
78
private final static int HASHSET_OVERHEAD_32 = 136;
79     private final static int HASHSET_OVERHEAD_64 = 240;
80
81     // 23 - OBJECT_OVERHEAD_32 - HASHSET_OVERHEAD_32
82
private final static int HASHSET_ENTRY_OVERHEAD_32 = 24;
83     private final static int HASHSET_ENTRY_OVERHEAD_64 = 48;
84
85     // 2 * HASHMAP_OVERHEAD_32
86
private final static int TWOHASHMAPS_OVERHEAD_32 = 240;
87     private final static int TWOHASHMAPS_OVERHEAD_64 = 432;
88
89     // 34
90
private final static int TREEMAP_OVERHEAD_32 = 40;
91     private final static int TREEMAP_OVERHEAD_64 = 64;
92
93     // 35 - OBJECT_OVERHEAD_32 - TREEMAP_OVERHEAD_32
94
private final static int TREEMAP_ENTRY_OVERHEAD_32 = 32;
95     private final static int TREEMAP_ENTRY_OVERHEAD_64 = 53;
96
97     // 36
98
private final static int MAPLN_OVERHEAD_32 = 464;
99     private final static int MAPLN_OVERHEAD_64 = 776;
100
101     // 9
102
private final static int LN_OVERHEAD_32 = 24;
103     private final static int LN_OVERHEAD_64 = 32;
104
105     // 19
106
private final static int DUPCOUNTLN_OVERHEAD_32 = 24;
107     private final static int DUPCOUNTLN_OVERHEAD_64 = 40;
108
109     // 12
110
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     // 18
115
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     // 17
120
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     // 13
125
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     // 6
130
private final static int KEY_OVERHEAD_32 = 16;
131     private final static int KEY_OVERHEAD_64 = 24;
132
133     // 24
134
private final static int LOCK_OVERHEAD_32 = 32;
135     private final static int LOCK_OVERHEAD_64 = 56;
136
137     // 25
138
private final static int LOCKINFO_OVERHEAD_32 = 16;
139     private final static int LOCKINFO_OVERHEAD_64 = 32;
140
141     // 37
142
private final static int WRITE_LOCKINFO_OVERHEAD_32 = 32;
143     private final static int WRITE_LOCKINFO_OVERHEAD_64 = 40;
144
145     /*
146      * Txn memory is the size for the Txn + a hashmap entry
147      * overhead for being part of the transaction table.
148      */

149     // 15
150
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     // 26
155
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     /* The per-log-file bytes used in UtilizationProfile. */
163     // 29 / 500
164
private final static int UTILIZATION_PROFILE_ENTRY_32 = 96;
165     private final static int UTILIZATION_PROFILE_ENTRY_64 = 144;
166
167     /* Tracked File Summary overheads. */
168     // 31
169
private final static int TFS_LIST_INITIAL_OVERHEAD_32 = 464;
170     private final static int TFS_LIST_INITIAL_OVERHEAD_64 = 504;
171
172     // 30
173
private final static int TFS_LIST_SEGMENT_OVERHEAD_32 = 440;
174     private final static int TFS_LIST_SEGMENT_OVERHEAD_64 = 464;
175
176     // 33
177
private final static int LN_INFO_OVERHEAD_32 = 24;
178     private final static int LN_INFO_OVERHEAD_64 = 48;
179
180     /* Approximate element size in an ArrayList of Long. */
181     // (28 - 27) / 100
182
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 JavaDoc JVM_ARCH_PROPERTY = "sun.arch.data.model";
216     private final static String JavaDoc FORCE_JVM_ARCH = "je.forceJVMArch";
217
218     static {
219     boolean is64 = false;
220     boolean isJVM14 = (LatchSupport.getJava5LatchClass() == null);
221     String JavaDoc overrideArch = System.getProperty(FORCE_JVM_ARCH);
222     try {
223         if (overrideArch == null) {
224         String JavaDoc 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 JavaDoc NFE) {
232         NFE.printStackTrace(System.err);
233     }
234
235     if (is64) {
236         if (isJVM14) {
237         RuntimeException JavaDoc RE = new RuntimeException JavaDoc
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     /* public for unit tests. */
314     public final static long MIN_MAX_MEMORY_SIZE = 96 * 1024;
315     public final static String JavaDoc MIN_MAX_MEMORY_SIZE_STRING =
316     Long.toString(MIN_MAX_MEMORY_SIZE);
317
318     private final static long N_64MB = (1 << 26);
319
320     /*
321      * Note that this class contains long fields that are accessed by multiple
322      * threads, and access to these fields is intentionally not synchronized.
323      * Although inaccuracies may result, correcting them is not worth the cost
324      * of synchronizing every time we adjust the treeMemoryUsage or
325      * miscMemoryUsage.
326      */

327
328     /*
329      * Amount of memory cached for tree objects.
330      */

331     private long treeMemoryUsage;
332
333     /*
334      * Amount of memory cached for Txn and other objects.
335      */

336     private long miscMemoryUsage;
337
338     /*
339      * Used to protect treeMemoryUsage and miscMemoryUsage updates.
340      */

341     private Object JavaDoc memoryUsageSynchronizer = new Object JavaDoc();
342
343     /*
344      * Number of lock tables (cache of EnvironmentParams.N_LOCK_TABLES).
345      */

346     private int nLockTables;
347
348     /*
349      * Amount of memory cached for locks. Protected by the
350      * LockManager.lockTableLatches[lockTableIndex]. Individual elements of
351      * array may be negative, but the sum will be >= 0.
352      */

353     private long[] lockMemoryUsage;
354
355     /*
356      * Memory available to JE, based on je.maxMemory and the memory available
357      * to this process.
358      */

359     private long maxMemory;
360     private long criticalThreshold; // experimental mark for sync eviction.
361

362     /* Memory available to log buffers. */
363     private long logBufferBudget;
364                            
365     /* Maximum allowed use of the misc budget by the UtilizationTracker. */
366     private long trackerBudget;
367
368     /*
369      * Memory to hold internal nodes and misc memory (locks), controlled by the
370      * evictor. Does not include the log buffers.
371      */

372     private long cacheBudget;
373     
374     /*
375      * Overheads that are a function of node capacity.
376      */

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         /* Request notification of mutable property changes. */
391         envImpl.addConfigObserver(this);
392
393         /* Peform first time budget initialization. */
394         reset(configManager);
395
396         /*
397          * Calculate IN and BIN overheads, which are a function of
398          * capacity. These values are stored in this class so that they can be
399          * calculated once per environment. The logic to do the calculations is
400          * left in the respective node classes so it can be done properly in
401          * the domain of those objects.
402          */

403         inOverhead = IN.computeOverhead(configManager);
404         binOverhead = BIN.computeOverhead(configManager);
405         dinOverhead = DIN.computeOverhead(configManager);
406         dbinOverhead = DBIN.computeOverhead(configManager);
407     }
408
409     /**
410      * Respond to config updates.
411      */

412     public void envConfigUpdate(DbConfigManager configManager)
413         throws DatabaseException {
414
415         /*
416          * Reinitialize the cache budget and the log buffer pool, in that
417          * order. Do not reset the log buffer pool if the log buffer budget
418          * hasn't changed, since that is expensive and may cause I/O.
419          */

420         long oldLogBufferBudget = logBufferBudget;
421         reset(configManager);
422         if (oldLogBufferBudget != logBufferBudget) {
423             envImpl.getLogManager().resetPool(configManager);
424         }
425     }
426
427     /**
428      * Initialize at construction time and when the cache is resized.
429      */

430     private void reset(DbConfigManager configManager)
431         throws DatabaseException {
432
433         /*
434          * Calculate the total memory allotted to JE.
435          * 1. If je.maxMemory is specified, use that. Check that it's
436          * not more than the jvm memory.
437          * 2. Otherwise, take je.maxMemoryPercent * JVM max memory.
438          */

439         long newMaxMemory =
440             configManager.getLong(EnvironmentParams.MAX_MEMORY);
441         long jvmMemory = getRuntimeMaxMemory();
442
443         if (newMaxMemory != 0) {
444             /* Application specified a cache size number, validate it. */
445             if (jvmMemory < newMaxMemory) {
446                 throw new IllegalArgumentException JavaDoc
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 JavaDoc
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             /*
463              * When no explicit cache size is specified and the JVM memory size
464              * is unknown, assume a default sized (64 MB) heap. This produces
465              * a reasonable cache size when no heap size is known.
466              */

467             if (jvmMemory == Long.MAX_VALUE) {
468                 jvmMemory = N_64MB;
469             }
470
471             /* Use the configured percentage of the JVM memory size. */
472             int maxMemoryPercent =
473                 configManager.getInt(EnvironmentParams.MAX_MEMORY_PERCENT);
474             newMaxMemory = (maxMemoryPercent * jvmMemory) / 100;
475         }
476
477         /*
478      * Calculate the memory budget for log buffering. If the LOG_MEM_SIZE
479      * parameter is not set, start by using 7% (1/16th) of the cache
480      * size. If it is set, use that explicit setting.
481      *
482      * No point in having more log buffers than the maximum size. If
483      * this starting point results in overly large log buffers,
484      * reduce the log buffer budget again.
485          */

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         /*
495          * We have a first pass at the log buffer budget. See what
496          * size log buffers result. Don't let them be too big, it would
497          * be a waste.
498          */

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         /*
524          * If all has gone well, update the budget fields. Once the log buffer
525          * budget is determined, the remainder of the memory is left for tree
526          * nodes.
527          */

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     /**
539      * Returns Runtime.maxMemory(), accounting for a MacOS bug.
540      * May return Long.MAX_VALUE if there is no inherent limit.
541      * Used by unit tests as well as by this class.
542      */

543     public static long getRuntimeMaxMemory() {
544
545         /* Runtime.maxMemory is unreliable on MacOS Java 1.4.2. */
546         if ("Mac OS X".equals(System.getProperty("os.name"))) {
547             String JavaDoc jvmVersion = System.getProperty("java.version");
548             if (jvmVersion != null && jvmVersion.startsWith("1.4.2")) {
549                 return Long.MAX_VALUE; /* Undetermined heap size. */
550             }
551         }
552
553         return Runtime.getRuntime().maxMemory();
554     }
555
556     /**
557      * Initialize the starting environment memory state
558      */

559     void initCacheMemoryUsage()
560         throws DatabaseException {
561
562     synchronized (memoryUsageSynchronizer) {
563         treeMemoryUsage = calcTreeCacheUsage();
564     }
565         assert LatchSupport.countLatchesHeld() == 0;
566     }
567
568     /**
569      * Public for testing.
570      */

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 JavaDoc 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     /**
592      * Update the environment wide tree memory count, wake up the evictor if
593      * necessary.
594      * @param increment note that increment may be negative.
595      */

596     public void updateTreeMemoryUsage(long increment) {
597     synchronized (memoryUsageSynchronizer) {
598         treeMemoryUsage += increment;
599     }
600         if (getCacheMemoryUsage() > cacheBudget) {
601             envImpl.alertEvictor();
602         }
603     }
604
605     /**
606      * Update the environment wide misc memory count, wake up the evictor if
607      * necessary.
608      * @param increment note that increment may be negative.
609      */

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     /**
649      * Used for unit testing.
650      */

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     /**
692      * Returns the memory size occupied by a byte array of a given length.
693      */

694     public static int byteArraySize(int arrayLen) {
695
696         /*
697          * BYTE_ARRAY_OVERHEAD accounts for 4 bytes of data. Data larger than
698          * 4 bytes is allocated in 8 byte increments.
699          */

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