Source Code Cross Referenced for MemoryBudget.java in  » JMX » je » com » sleepycat » je » dbi » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » JMX » je » com.sleepycat.je.dbi 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*-
002:         * See the file LICENSE for redistribution information.
003:         *
004:         * Copyright (c) 2002,2008 Oracle.  All rights reserved.
005:         *
006:         * $Id: MemoryBudget.java,v 1.54.2.10 2008/01/07 15:14:09 cwl Exp $
007:         */
008:
009:        package com.sleepycat.je.dbi;
010:
011:        import java.util.Iterator;
012:
013:        import com.sleepycat.je.DatabaseException;
014:        import com.sleepycat.je.EnvironmentStats;
015:        import com.sleepycat.je.StatsConfig;
016:        import com.sleepycat.je.config.EnvironmentParams;
017:        import com.sleepycat.je.latch.LatchSupport;
018:        import com.sleepycat.je.tree.BIN;
019:        import com.sleepycat.je.tree.DBIN;
020:        import com.sleepycat.je.tree.DIN;
021:        import com.sleepycat.je.tree.IN;
022:
023:        /**
024:         * MemoryBudget calculates the available memory for JE and how to apportion
025:         * it between cache and log buffers. It is meant to centralize all memory
026:         * calculations. Objects that ask for memory budgets should get settings from
027:         * this class, rather than using the configuration parameter values directly.
028:         */
029:        public class MemoryBudget implements  EnvConfigObserver {
030:
031:            /*
032:             * Object overheads. These are set statically with advance measurements.
033:             * Java doesn't provide a way of assessing object size dynamically. These
034:             * overheads will not be precise, but are close enough to let the system
035:             * behave predictably.
036:             *
037:             * _32 values are the same on Windows and Solaris.
038:             * _64 values are from 1.5.0_05 on Solaris.
039:             * _14 values are from 1.4.2 on Windows and Solaris.
040:             * _15 values are from 1.5.0_05 on Solaris and Windows.
041:             *
042:             * Specifically:
043:             *
044:             * java.vm.version=1.5.0_05_b05 os.name=SunOS
045:             * java.vm.version=1.4.2_05_b04 os.name=SunOS
046:             * java.vm.version=1.5.0_04_b05, os.name=Windows XP
047:             * java.vm.version=1.4.2_06-b03, os.name=Windows XP
048:             *
049:             * The integer following the // below is the Sizeof argument used to
050:             * compute the value.
051:             */
052:
053:            // 7
054:            private final static int LONG_OVERHEAD_32 = 16;
055:            private final static int LONG_OVERHEAD_64 = 24;
056:
057:            // 8
058:            private final static int ARRAY_OVERHEAD_32 = 16;
059:            private final static int ARRAY_OVERHEAD_64 = 24;
060:
061:            private final static int ARRAY_SIZE_INCLUDED_32 = 4;
062:            private final static int ARRAY_SIZE_INCLUDED_64 = 0;
063:
064:            // 2
065:            private final static int OBJECT_OVERHEAD_32 = 8;
066:            private final static int OBJECT_OVERHEAD_64 = 16;
067:
068:            // (4 - ARRAY_OVERHEAD) / 256
069:            // 64b: 4 is 2072
070:            private final static int OBJECT_ARRAY_ITEM_OVERHEAD_32 = 4;
071:            private final static int OBJECT_ARRAY_ITEM_OVERHEAD_64 = 8;
072:
073:            // 20
074:            private final static int HASHMAP_OVERHEAD_32 = 120;
075:            private final static int HASHMAP_OVERHEAD_64 = 216;
076:
077:            // 21 - OBJECT_OVERHEAD - HASHMAP_OVERHEAD
078:            // 64b: 21 is max(280,...,287) on Linux/Solaris 1.5/1.6
079:            private final static int HASHMAP_ENTRY_OVERHEAD_32 = 24;
080:            private final static int HASHMAP_ENTRY_OVERHEAD_64 = 55;
081:
082:            // 22
083:            private final static int HASHSET_OVERHEAD_32 = 136;
084:            private final static int HASHSET_OVERHEAD_64 = 240;
085:
086:            // 23 - OBJECT_OVERHEAD - HASHSET_OVERHEAD
087:            // 64b: 23 is max(304,...,311) on Linux/Solaris
088:            private final static int HASHSET_ENTRY_OVERHEAD_32 = 24;
089:            private final static int HASHSET_ENTRY_OVERHEAD_64 = 55;
090:
091:            // HASHMAP_OVERHEAD * 2
092:            private final static int TWOHASHMAPS_OVERHEAD_32 = 240;
093:            private final static int TWOHASHMAPS_OVERHEAD_64 = 432;
094:
095:            // 34
096:            private final static int TREEMAP_OVERHEAD_32 = 40;
097:            private final static int TREEMAP_OVERHEAD_64_15 = 64;
098:            private final static int TREEMAP_OVERHEAD_64_16 = 80;
099:
100:            // 35 - OBJECT_OVERHEAD - TREEMAP_OVERHEAD
101:            // 64b: 35 is 144 on 1.5 and 160 on 1.6, result is 64 for both
102:            private final static int TREEMAP_ENTRY_OVERHEAD_32 = 32;
103:            private final static int TREEMAP_ENTRY_OVERHEAD_64 = 64;
104:
105:            // 36
106:            // 64b: 36 is 800 on 1.5 and max(840,853) on Linux/Solaris 1.6
107:            private final static int MAPLN_OVERHEAD_32 = 464;
108:            private final static int MAPLN_OVERHEAD_64_15 = 800;
109:            private final static int MAPLN_OVERHEAD_64_16 = 853;
110:
111:            // 9
112:            private final static int LN_OVERHEAD_32 = 24;
113:            private final static int LN_OVERHEAD_64 = 40;
114:
115:            // 19
116:            private final static int DUPCOUNTLN_OVERHEAD_32 = 24;
117:            private final static int DUPCOUNTLN_OVERHEAD_64 = 48;
118:
119:            // 12
120:            private final static int BIN_FIXED_OVERHEAD_32_14 = 344;
121:            private final static int BIN_FIXED_OVERHEAD_32_15 = 360;
122:            private final static int BIN_FIXED_OVERHEAD_64_15 = 528;
123:            private final static int BIN_FIXED_OVERHEAD_64_16 = 568;
124:
125:            // 18
126:            private final static int DIN_FIXED_OVERHEAD_32_14 = 352;
127:            private final static int DIN_FIXED_OVERHEAD_32_15 = 360;
128:            private final static int DIN_FIXED_OVERHEAD_64_15 = 536;
129:            private final static int DIN_FIXED_OVERHEAD_64_16 = 576;
130:
131:            // 17
132:            private final static int DBIN_FIXED_OVERHEAD_32_14 = 352;
133:            private final static int DBIN_FIXED_OVERHEAD_32_15 = 368;
134:            private final static int DBIN_FIXED_OVERHEAD_64_15 = 544;
135:            private final static int DBIN_FIXED_OVERHEAD_64_16 = 584;
136:
137:            // 13
138:            private final static int IN_FIXED_OVERHEAD_32_14 = 312;
139:            private final static int IN_FIXED_OVERHEAD_32_15 = 320;
140:            private final static int IN_FIXED_OVERHEAD_64_15 = 472;
141:            private final static int IN_FIXED_OVERHEAD_64_16 = 512;
142:
143:            // 6
144:            private final static int KEY_OVERHEAD_32 = 16;
145:            private final static int KEY_OVERHEAD_64 = 24;
146:
147:            // 24
148:            private final static int LOCK_OVERHEAD_32 = 24;
149:            private final static int LOCK_OVERHEAD_64 = 48;
150:
151:            // 25
152:            private final static int LOCKINFO_OVERHEAD_32 = 16;
153:            private final static int LOCKINFO_OVERHEAD_64 = 32;
154:
155:            // 37
156:            private final static int WRITE_LOCKINFO_OVERHEAD_32 = 24;
157:            private final static int WRITE_LOCKINFO_OVERHEAD_64 = 32;
158:
159:            /*
160:             * Txn memory is the size for the Txn + a hashmap entry
161:             * overhead for being part of the transaction table.
162:             */
163:            // 15
164:            private final static int TXN_OVERHEAD_32_14 = 167;
165:            private final static int TXN_OVERHEAD_32_15 = 175;
166:            private final static int TXN_OVERHEAD_64 = 253;
167:
168:            // 26
169:            private final static int CHECKPOINT_REFERENCE_SIZE_32_14 = 32 + HASHSET_ENTRY_OVERHEAD_32;
170:            private final static int CHECKPOINT_REFERENCE_SIZE_32_15 = 40 + HASHSET_ENTRY_OVERHEAD_32;
171:            private final static int CHECKPOINT_REFERENCE_SIZE_64 = 56 + HASHSET_ENTRY_OVERHEAD_64;
172:
173:            /* The per-log-file bytes used in UtilizationProfile. */
174:            // 29 / 500
175:            private final static int UTILIZATION_PROFILE_ENTRY_32 = 96;
176:            private final static int UTILIZATION_PROFILE_ENTRY_64 = 144;
177:
178:            /* Tracked File Summary overheads. */
179:            // 31
180:            private final static int TFS_LIST_INITIAL_OVERHEAD_32 = 464;
181:            private final static int TFS_LIST_INITIAL_OVERHEAD_64 = 504;
182:
183:            // 30
184:            private final static int TFS_LIST_SEGMENT_OVERHEAD_32 = 440;
185:            private final static int TFS_LIST_SEGMENT_OVERHEAD_64 = 464;
186:
187:            // 33
188:            private final static int LN_INFO_OVERHEAD_32 = 24;
189:            private final static int LN_INFO_OVERHEAD_64 = 48;
190:
191:            // 38
192:            private final static int FILESUMMARYLN_OVERHEAD_32 = 104;
193:            private final static int FILESUMMARYLN_OVERHEAD_64 = 160;
194:
195:            /* Approximate element size in an ArrayList of Long. */
196:            // (28 - 27) / 100
197:            private final static int LONG_LIST_PER_ITEM_OVERHEAD_32 = 20;
198:            private final static int LONG_LIST_PER_ITEM_OVERHEAD_64 = 32;
199:
200:            public final static int LONG_OVERHEAD;
201:            public final static int ARRAY_OVERHEAD;
202:            public final static int ARRAY_SIZE_INCLUDED;
203:            public final static int OBJECT_OVERHEAD;
204:            public final static int OBJECT_ARRAY_ITEM_OVERHEAD;
205:            public final static int HASHMAP_OVERHEAD;
206:            public final static int HASHMAP_ENTRY_OVERHEAD;
207:            public final static int HASHSET_OVERHEAD;
208:            public final static int HASHSET_ENTRY_OVERHEAD;
209:            public final static int TWOHASHMAPS_OVERHEAD;
210:            public final static int TREEMAP_OVERHEAD;
211:            public final static int TREEMAP_ENTRY_OVERHEAD;
212:            public final static int MAPLN_OVERHEAD;
213:            public final static int LN_OVERHEAD;
214:            public final static int DUPCOUNTLN_OVERHEAD;
215:            public final static int BIN_FIXED_OVERHEAD;
216:            public final static int DIN_FIXED_OVERHEAD;
217:            public final static int DBIN_FIXED_OVERHEAD;
218:            public final static int IN_FIXED_OVERHEAD;
219:            public final static int KEY_OVERHEAD;
220:            public final static int LOCK_OVERHEAD;
221:            public final static int LOCKINFO_OVERHEAD;
222:            public final static int WRITE_LOCKINFO_OVERHEAD;
223:            public final static int TXN_OVERHEAD;
224:            public final static int CHECKPOINT_REFERENCE_SIZE;
225:            public final static int UTILIZATION_PROFILE_ENTRY;
226:            public final static int TFS_LIST_INITIAL_OVERHEAD;
227:            public final static int TFS_LIST_SEGMENT_OVERHEAD;
228:            public final static int LN_INFO_OVERHEAD;
229:            public final static int FILESUMMARYLN_OVERHEAD;
230:            public final static int LONG_LIST_PER_ITEM_OVERHEAD;
231:
232:            /* Primitive long array item size is the same on all platforms. */
233:            public final static int PRIMITIVE_LONG_ARRAY_ITEM_OVERHEAD = 8;
234:
235:            private final static String JVM_ARCH_PROPERTY = "sun.arch.data.model";
236:            private final static String FORCE_JVM_ARCH = "je.forceJVMArch";
237:
238:            static {
239:                String javaVersion = System.getProperty("java.version");
240:                boolean isJVM15 = javaVersion != null
241:                        && javaVersion.startsWith("1.5.");
242:                boolean isJVM14 = (LatchSupport.getJava5LatchClass() == null);
243:
244:                boolean is64 = false;
245:                String overrideArch = System.getProperty(FORCE_JVM_ARCH);
246:                try {
247:                    if (overrideArch == null) {
248:                        String arch = System.getProperty(JVM_ARCH_PROPERTY);
249:                        if (arch != null) {
250:                            is64 = Integer.parseInt(arch) == 64;
251:                        }
252:                    } else {
253:                        is64 = Integer.parseInt(overrideArch) == 64;
254:                    }
255:                } catch (NumberFormatException NFE) {
256:                    NFE.printStackTrace(System.err);
257:                }
258:
259:                if (is64) {
260:                    if (isJVM14) {
261:                        RuntimeException RE = new RuntimeException(
262:                                "1.4 based 64 bit JVM not supported");
263:                        RE.printStackTrace(System.err);
264:                        throw RE;
265:                    }
266:                    LONG_OVERHEAD = LONG_OVERHEAD_64;
267:                    ARRAY_OVERHEAD = ARRAY_OVERHEAD_64;
268:                    ARRAY_SIZE_INCLUDED = ARRAY_SIZE_INCLUDED_64;
269:                    OBJECT_OVERHEAD = OBJECT_OVERHEAD_64;
270:                    OBJECT_ARRAY_ITEM_OVERHEAD = OBJECT_ARRAY_ITEM_OVERHEAD_64;
271:                    HASHMAP_OVERHEAD = HASHMAP_OVERHEAD_64;
272:                    HASHMAP_ENTRY_OVERHEAD = HASHMAP_ENTRY_OVERHEAD_64;
273:                    HASHSET_OVERHEAD = HASHSET_OVERHEAD_64;
274:                    HASHSET_ENTRY_OVERHEAD = HASHSET_ENTRY_OVERHEAD_64;
275:                    TWOHASHMAPS_OVERHEAD = TWOHASHMAPS_OVERHEAD_64;
276:                    if (isJVM15) {
277:                        TREEMAP_OVERHEAD = TREEMAP_OVERHEAD_64_15;
278:                        MAPLN_OVERHEAD = MAPLN_OVERHEAD_64_15;
279:                        BIN_FIXED_OVERHEAD = BIN_FIXED_OVERHEAD_64_15;
280:                        DIN_FIXED_OVERHEAD = DIN_FIXED_OVERHEAD_64_15;
281:                        DBIN_FIXED_OVERHEAD = DBIN_FIXED_OVERHEAD_64_15;
282:                        IN_FIXED_OVERHEAD = IN_FIXED_OVERHEAD_64_15;
283:                    } else {
284:                        TREEMAP_OVERHEAD = TREEMAP_OVERHEAD_64_16;
285:                        MAPLN_OVERHEAD = MAPLN_OVERHEAD_64_16;
286:                        BIN_FIXED_OVERHEAD = BIN_FIXED_OVERHEAD_64_16;
287:                        DIN_FIXED_OVERHEAD = DIN_FIXED_OVERHEAD_64_16;
288:                        DBIN_FIXED_OVERHEAD = DBIN_FIXED_OVERHEAD_64_16;
289:                        IN_FIXED_OVERHEAD = IN_FIXED_OVERHEAD_64_16;
290:                    }
291:                    TREEMAP_ENTRY_OVERHEAD = TREEMAP_ENTRY_OVERHEAD_64;
292:                    LN_OVERHEAD = LN_OVERHEAD_64;
293:                    DUPCOUNTLN_OVERHEAD = DUPCOUNTLN_OVERHEAD_64;
294:                    TXN_OVERHEAD = TXN_OVERHEAD_64;
295:                    CHECKPOINT_REFERENCE_SIZE = CHECKPOINT_REFERENCE_SIZE_64;
296:                    KEY_OVERHEAD = KEY_OVERHEAD_64;
297:                    LOCK_OVERHEAD = LOCK_OVERHEAD_64;
298:                    LOCKINFO_OVERHEAD = LOCKINFO_OVERHEAD_64;
299:                    WRITE_LOCKINFO_OVERHEAD = WRITE_LOCKINFO_OVERHEAD_64;
300:                    UTILIZATION_PROFILE_ENTRY = UTILIZATION_PROFILE_ENTRY_64;
301:                    TFS_LIST_INITIAL_OVERHEAD = TFS_LIST_INITIAL_OVERHEAD_64;
302:                    TFS_LIST_SEGMENT_OVERHEAD = TFS_LIST_SEGMENT_OVERHEAD_64;
303:                    LN_INFO_OVERHEAD = LN_INFO_OVERHEAD_64;
304:                    FILESUMMARYLN_OVERHEAD = FILESUMMARYLN_OVERHEAD_64;
305:                    LONG_LIST_PER_ITEM_OVERHEAD = LONG_LIST_PER_ITEM_OVERHEAD_64;
306:                } else {
307:                    LONG_OVERHEAD = LONG_OVERHEAD_32;
308:                    ARRAY_OVERHEAD = ARRAY_OVERHEAD_32;
309:                    ARRAY_SIZE_INCLUDED = ARRAY_SIZE_INCLUDED_32;
310:                    OBJECT_OVERHEAD = OBJECT_OVERHEAD_32;
311:                    OBJECT_ARRAY_ITEM_OVERHEAD = OBJECT_ARRAY_ITEM_OVERHEAD_32;
312:                    HASHMAP_OVERHEAD = HASHMAP_OVERHEAD_32;
313:                    HASHMAP_ENTRY_OVERHEAD = HASHMAP_ENTRY_OVERHEAD_32;
314:                    HASHSET_OVERHEAD = HASHSET_OVERHEAD_32;
315:                    HASHSET_ENTRY_OVERHEAD = HASHSET_ENTRY_OVERHEAD_32;
316:                    TWOHASHMAPS_OVERHEAD = TWOHASHMAPS_OVERHEAD_32;
317:                    TREEMAP_OVERHEAD = TREEMAP_OVERHEAD_32;
318:                    TREEMAP_ENTRY_OVERHEAD = TREEMAP_ENTRY_OVERHEAD_32;
319:                    MAPLN_OVERHEAD = MAPLN_OVERHEAD_32;
320:                    LN_OVERHEAD = LN_OVERHEAD_32;
321:                    DUPCOUNTLN_OVERHEAD = DUPCOUNTLN_OVERHEAD_32;
322:                    if (isJVM14) {
323:                        BIN_FIXED_OVERHEAD = BIN_FIXED_OVERHEAD_32_14;
324:                        DIN_FIXED_OVERHEAD = DIN_FIXED_OVERHEAD_32_14;
325:                        DBIN_FIXED_OVERHEAD = DBIN_FIXED_OVERHEAD_32_14;
326:                        IN_FIXED_OVERHEAD = IN_FIXED_OVERHEAD_32_14;
327:                        TXN_OVERHEAD = TXN_OVERHEAD_32_14;
328:                        CHECKPOINT_REFERENCE_SIZE = CHECKPOINT_REFERENCE_SIZE_32_14;
329:                    } else {
330:                        BIN_FIXED_OVERHEAD = BIN_FIXED_OVERHEAD_32_15;
331:                        DIN_FIXED_OVERHEAD = DIN_FIXED_OVERHEAD_32_15;
332:                        DBIN_FIXED_OVERHEAD = DBIN_FIXED_OVERHEAD_32_15;
333:                        IN_FIXED_OVERHEAD = IN_FIXED_OVERHEAD_32_15;
334:                        TXN_OVERHEAD = TXN_OVERHEAD_32_15;
335:                        CHECKPOINT_REFERENCE_SIZE = CHECKPOINT_REFERENCE_SIZE_32_15;
336:                    }
337:                    KEY_OVERHEAD = KEY_OVERHEAD_32;
338:                    LOCK_OVERHEAD = LOCK_OVERHEAD_32;
339:                    LOCKINFO_OVERHEAD = LOCKINFO_OVERHEAD_32;
340:                    WRITE_LOCKINFO_OVERHEAD = WRITE_LOCKINFO_OVERHEAD_32;
341:                    UTILIZATION_PROFILE_ENTRY = UTILIZATION_PROFILE_ENTRY_32;
342:                    TFS_LIST_INITIAL_OVERHEAD = TFS_LIST_INITIAL_OVERHEAD_32;
343:                    TFS_LIST_SEGMENT_OVERHEAD = TFS_LIST_SEGMENT_OVERHEAD_32;
344:                    LN_INFO_OVERHEAD = LN_INFO_OVERHEAD_32;
345:                    FILESUMMARYLN_OVERHEAD = FILESUMMARYLN_OVERHEAD_32;
346:                    LONG_LIST_PER_ITEM_OVERHEAD = LONG_LIST_PER_ITEM_OVERHEAD_32;
347:                }
348:            }
349:
350:            /* public for unit tests. */
351:            public final static long MIN_MAX_MEMORY_SIZE = 96 * 1024;
352:            public final static String MIN_MAX_MEMORY_SIZE_STRING = Long
353:                    .toString(MIN_MAX_MEMORY_SIZE);
354:
355:            /* This value prevents cache churn for apps with a high write rate. */
356:            private final static int DEFAULT_MIN_BTREE_CACHE_SIZE = 500 * 1024;
357:
358:            private final static long N_64MB = (1 << 26);
359:
360:            /*
361:             * Note that this class contains long fields that are accessed by multiple
362:             * threads, and access to these fields is intentionally not synchronized.
363:             * Although inaccuracies may result, correcting them is not worth the cost
364:             * of synchronizing every time we adjust the treeMemoryUsage or
365:             * miscMemoryUsage.
366:             */
367:
368:            /*
369:             * Amount of memory cached for tree objects.
370:             */
371:            private long treeMemoryUsage;
372:
373:            /*
374:             * Amount of memory cached for Txn and other objects.
375:             */
376:            private long miscMemoryUsage;
377:
378:            /*
379:             * Used to protect treeMemoryUsage and miscMemoryUsage updates.
380:             */
381:            private Object memoryUsageSynchronizer = new Object();
382:
383:            /*
384:             * Number of lock tables (cache of EnvironmentParams.N_LOCK_TABLES).
385:             */
386:            private int nLockTables;
387:
388:            /*
389:             * Amount of memory cached for locks. Protected by the
390:             * LockManager.lockTableLatches[lockTableIndex].
391:             */
392:            private long[] lockMemoryUsage;
393:
394:            /*
395:             * Memory available to JE, based on je.maxMemory and the memory available
396:             * to this process.
397:             */
398:            private long maxMemory;
399:            private long criticalThreshold; // experimental mark for sync eviction.
400:
401:            /* Memory available to log buffers. */
402:            private long logBufferBudget;
403:
404:            /* Maximum allowed use of the misc budget by the UtilizationTracker. */
405:            private long trackerBudget;
406:
407:            /*
408:             * Memory to hold internal nodes and misc memory (locks), controlled by the
409:             * evictor.  Does not include the log buffers.
410:             */
411:            private long cacheBudget;
412:
413:            /* Mininum to prevent cache churn. */
414:            private long minTreeMemoryUsage;
415:
416:            /*
417:             * Overheads that are a function of node capacity.
418:             */
419:            private long inOverhead;
420:            private long binOverhead;
421:            private long dinOverhead;
422:            private long dbinOverhead;
423:
424:            private EnvironmentImpl envImpl;
425:
426:            MemoryBudget(EnvironmentImpl envImpl, DbConfigManager configManager)
427:                    throws DatabaseException {
428:
429:                this .envImpl = envImpl;
430:
431:                /* Request notification of mutable property changes. */
432:                envImpl.addConfigObserver(this );
433:
434:                /* Peform first time budget initialization. */
435:                reset(configManager, true);
436:
437:                /*
438:                 * Calculate IN and BIN overheads, which are a function of
439:                 * capacity. These values are stored in this class so that they can be
440:                 * calculated once per environment. The logic to do the calculations is
441:                 * left in the respective node classes so it can be done properly in
442:                 * the domain of those objects.
443:                 */
444:                inOverhead = IN.computeOverhead(configManager);
445:                binOverhead = BIN.computeOverhead(configManager);
446:                dinOverhead = DIN.computeOverhead(configManager);
447:                dbinOverhead = DBIN.computeOverhead(configManager);
448:            }
449:
450:            /**
451:             * Respond to config updates.
452:             */
453:            public void envConfigUpdate(DbConfigManager configManager)
454:                    throws DatabaseException {
455:
456:                /*
457:                 * Reinitialize the cache budget and the log buffer pool, in that
458:                 * order.  Do not reset the log buffer pool if the log buffer budget
459:                 * hasn't changed, since that is expensive and may cause I/O.
460:                 */
461:                long oldLogBufferBudget = logBufferBudget;
462:                reset(configManager, false);
463:                if (oldLogBufferBudget != logBufferBudget) {
464:                    envImpl.getLogManager().resetPool(configManager);
465:                }
466:            }
467:
468:            /**
469:             * Initialize at construction time and when the cache is resized.
470:             */
471:            private void reset(DbConfigManager configManager,
472:                    boolean resetLockMemoryUsage) throws DatabaseException {
473:
474:                /*
475:                 * Calculate the total memory allotted to JE.
476:                 * 1. If je.maxMemory is specified, use that. Check that it's
477:                 * not more than the jvm memory.
478:                 * 2. Otherwise, take je.maxMemoryPercent * JVM max memory.
479:                 */
480:                long newMaxMemory = configManager
481:                        .getLong(EnvironmentParams.MAX_MEMORY);
482:                long jvmMemory = getRuntimeMaxMemory();
483:
484:                if (newMaxMemory != 0) {
485:                    /* Application specified a cache size number, validate it. */
486:                    if (jvmMemory < newMaxMemory) {
487:                        throw new IllegalArgumentException(
488:                                EnvironmentParams.MAX_MEMORY.getName()
489:                                        + " has a value of "
490:                                        + newMaxMemory
491:                                        + " but the JVM is only configured for "
492:                                        + jvmMemory
493:                                        + ". Consider using je.maxMemoryPercent.");
494:                    }
495:                    if (newMaxMemory < MIN_MAX_MEMORY_SIZE) {
496:                        throw new IllegalArgumentException(
497:                                EnvironmentParams.MAX_MEMORY.getName() + " is "
498:                                        + newMaxMemory
499:                                        + " which is less than the minimum: "
500:                                        + MIN_MAX_MEMORY_SIZE);
501:                    }
502:                } else {
503:
504:                    /*
505:                     * When no explicit cache size is specified and the JVM memory size
506:                     * is unknown, assume a default sized (64 MB) heap.  This produces
507:                     * a reasonable cache size when no heap size is known.
508:                     */
509:                    if (jvmMemory == Long.MAX_VALUE) {
510:                        jvmMemory = N_64MB;
511:                    }
512:
513:                    /* Use the configured percentage of the JVM memory size. */
514:                    int maxMemoryPercent = configManager
515:                            .getInt(EnvironmentParams.MAX_MEMORY_PERCENT);
516:                    newMaxMemory = (maxMemoryPercent * jvmMemory) / 100;
517:                }
518:
519:                /*
520:                 * Calculate the memory budget for log buffering.  If the LOG_MEM_SIZE
521:                 * parameter is not set, start by using 7% (1/16th) of the cache
522:                 * size. If it is set, use that explicit setting.
523:                 *
524:                 * No point in having more log buffers than the maximum size. If
525:                 * this starting point results in overly large log buffers,
526:                 * reduce the log buffer budget again.
527:                 */
528:                long newLogBufferBudget = configManager
529:                        .getLong(EnvironmentParams.LOG_MEM_SIZE);
530:                if (newLogBufferBudget == 0) {
531:                    newLogBufferBudget = newMaxMemory >> 4;
532:                } else if (newLogBufferBudget > newMaxMemory / 2) {
533:                    newLogBufferBudget = newMaxMemory / 2;
534:                }
535:
536:                /*
537:                 * We have a first pass at the log buffer budget. See what
538:                 * size log buffers result. Don't let them be too big, it would
539:                 * be a waste.
540:                 */
541:                int numBuffers = configManager
542:                        .getInt(EnvironmentParams.NUM_LOG_BUFFERS);
543:                long startingBufferSize = newLogBufferBudget / numBuffers;
544:                int logBufferSize = configManager
545:                        .getInt(EnvironmentParams.LOG_BUFFER_MAX_SIZE);
546:                if (startingBufferSize > logBufferSize) {
547:                    startingBufferSize = logBufferSize;
548:                    newLogBufferBudget = numBuffers * startingBufferSize;
549:                } else if (startingBufferSize < EnvironmentParams.MIN_LOG_BUFFER_SIZE) {
550:                    startingBufferSize = EnvironmentParams.MIN_LOG_BUFFER_SIZE;
551:                    newLogBufferBudget = numBuffers * startingBufferSize;
552:                }
553:
554:                long newCriticalThreshold = (newMaxMemory * envImpl
555:                        .getConfigManager().getInt(
556:                                EnvironmentParams.EVICTOR_CRITICAL_PERCENTAGE)) / 100;
557:
558:                long newTrackerBudget = (newMaxMemory * envImpl
559:                        .getConfigManager()
560:                        .getInt(
561:                                EnvironmentParams.CLEANER_DETAIL_MAX_MEMORY_PERCENTAGE)) / 100;
562:
563:                long newMinTreeMemoryUsage = configManager
564:                        .getLong(EnvironmentParams.MIN_TREE_MEMORY);
565:
566:                /*
567:                 * If all has gone well, update the budget fields.  Once the log buffer
568:                 * budget is determined, the remainder of the memory is left for tree
569:                 * nodes.
570:                 */
571:                maxMemory = newMaxMemory;
572:                criticalThreshold = newCriticalThreshold;
573:                logBufferBudget = newLogBufferBudget;
574:                trackerBudget = newTrackerBudget;
575:                cacheBudget = newMaxMemory - newLogBufferBudget;
576:                minTreeMemoryUsage = Math.min(newMinTreeMemoryUsage,
577:                        cacheBudget);
578:                if (resetLockMemoryUsage) {
579:                    nLockTables = configManager
580:                            .getInt(EnvironmentParams.N_LOCK_TABLES);
581:                    lockMemoryUsage = new long[nLockTables];
582:                }
583:            }
584:
585:            /**
586:             * Returns Runtime.maxMemory(), accounting for a MacOS bug.
587:             * May return Long.MAX_VALUE if there is no inherent limit.
588:             * Used by unit tests as well as by this class.
589:             */
590:            public static long getRuntimeMaxMemory() {
591:
592:                /* Runtime.maxMemory is unreliable on MacOS Java 1.4.2. */
593:                if ("Mac OS X".equals(System.getProperty("os.name"))) {
594:                    String jvmVersion = System.getProperty("java.version");
595:                    if (jvmVersion != null && jvmVersion.startsWith("1.4.2")) {
596:                        return Long.MAX_VALUE; /* Undetermined heap size. */
597:                    }
598:                }
599:
600:                return Runtime.getRuntime().maxMemory();
601:            }
602:
603:            /**
604:             * Initialize the starting environment memory state.
605:             */
606:            void initCacheMemoryUsage() throws DatabaseException {
607:
608:                /*
609:                 * The memoryUsageSynchronizer mutex is at the bottom of the lock
610:                 * hierarchy and should always be taken last. Since
611:                 * calcTreeCacheUsage() takes the INList latch, we get the usage value
612:                 * outside the mutex and then assign the value, in order to preserve
613:                 * correct lock hierarchy.  That said, initCacheMemoryUsage should be
614:                 * called while the system is quiescent, and there should be no lock
615:                 * conflict possible even if the locks were taken in reverse. [#15364]
616:                 */
617:                long calculatedUsage = calcTreeCacheUsage();
618:                synchronized (memoryUsageSynchronizer) {
619:                    treeMemoryUsage = calculatedUsage;
620:                }
621:                assert LatchSupport.countLatchesHeld() == 0;
622:            }
623:
624:            /**
625:             * Public for testing.
626:             */
627:            public long calcTreeCacheUsage() throws DatabaseException {
628:
629:                long totalSize = 0;
630:                INList inList = envImpl.getInMemoryINs();
631:
632:                inList.latchMajor();
633:                try {
634:                    Iterator iter = inList.iterator();
635:                    while (iter.hasNext()) {
636:                        IN in = (IN) iter.next();
637:                        long size = in.getInMemorySize();
638:                        totalSize += size;
639:                    }
640:                } finally {
641:                    inList.releaseMajorLatch();
642:                }
643:                return totalSize;
644:            }
645:
646:            /**
647:             * Returns whether eviction of INList information is allowed.
648:             * To prevent extreme cache churn, eviction of Btree information is
649:             * prohibited unless the tree memory usage is above this minimum value.
650:             */
651:            public boolean isTreeUsageAboveMinimum() {
652:                return treeMemoryUsage > minTreeMemoryUsage;
653:            }
654:
655:            /**
656:             * For unit tests.
657:             */
658:            public long getMinTreeMemoryUsage() {
659:                return minTreeMemoryUsage;
660:            }
661:
662:            /**
663:             * Update the environment wide tree memory count, wake up the evictor if
664:             * necessary.
665:             * @param increment note that increment may be negative.
666:             */
667:            public void updateTreeMemoryUsage(long increment) {
668:                synchronized (memoryUsageSynchronizer) {
669:                    treeMemoryUsage += increment;
670:                }
671:                if (getCacheMemoryUsage() > cacheBudget) {
672:                    envImpl.alertEvictor();
673:                }
674:            }
675:
676:            /**
677:             * Update the environment wide misc memory count, wake up the evictor if
678:             * necessary.
679:             * @param increment note that increment may be negative.
680:             */
681:            public void updateMiscMemoryUsage(long increment) {
682:                synchronized (memoryUsageSynchronizer) {
683:                    miscMemoryUsage += increment;
684:                }
685:                if (getCacheMemoryUsage() > cacheBudget) {
686:                    envImpl.alertEvictor();
687:                }
688:            }
689:
690:            public void updateLockMemoryUsage(long increment, int lockTableIndex) {
691:                lockMemoryUsage[lockTableIndex] += increment;
692:                if (getCacheMemoryUsage() > cacheBudget) {
693:                    envImpl.alertEvictor();
694:                }
695:            }
696:
697:            public long accumulateNewUsage(IN in, long newSize) {
698:                return in.getInMemorySize() + newSize;
699:            }
700:
701:            public void refreshTreeMemoryUsage(long newSize) {
702:                synchronized (memoryUsageSynchronizer) {
703:                    treeMemoryUsage = newSize;
704:                }
705:            }
706:
707:            public long getCacheMemoryUsage() {
708:                long accLockMemoryUsage = accumulateLockUsage();
709:
710:                return treeMemoryUsage + miscMemoryUsage + accLockMemoryUsage;
711:            }
712:
713:            private long accumulateLockUsage() {
714:                long accLockMemoryUsage = 0;
715:                if (nLockTables == 1) {
716:                    accLockMemoryUsage = lockMemoryUsage[0];
717:                } else {
718:                    for (int i = 0; i < nLockTables; i++) {
719:                        accLockMemoryUsage += lockMemoryUsage[i];
720:                    }
721:                }
722:                return accLockMemoryUsage;
723:            }
724:
725:            /**
726:             * Used for unit testing.
727:             */
728:            public long getTreeMemoryUsage() {
729:                return treeMemoryUsage;
730:            }
731:
732:            /**
733:             * Used for unit testing.
734:             */
735:            public long getMiscMemoryUsage() {
736:                return miscMemoryUsage;
737:            }
738:
739:            public long getLogBufferBudget() {
740:                return logBufferBudget;
741:            }
742:
743:            public long getTrackerBudget() {
744:                return trackerBudget;
745:            }
746:
747:            public long getMaxMemory() {
748:                return maxMemory;
749:            }
750:
751:            public long getCriticalThreshold() {
752:                return criticalThreshold;
753:            }
754:
755:            public long getCacheBudget() {
756:                return cacheBudget;
757:            }
758:
759:            public long getINOverhead() {
760:                return inOverhead;
761:            }
762:
763:            public long getBINOverhead() {
764:                return binOverhead;
765:            }
766:
767:            public long getDINOverhead() {
768:                return dinOverhead;
769:            }
770:
771:            public long getDBINOverhead() {
772:                return dbinOverhead;
773:            }
774:
775:            /**
776:             * Returns the memory size occupied by a byte array of a given length.  All
777:             * arrays (regardless of element type) have the same overhead for a zero
778:             * length array.  On 32b Java, there are 4 bytes included in that fixed
779:             * overhead that can be used for the first N elements -- however many fit
780:             * in 4 bytes.  On 64b Java, there is no extra space included.  In all
781:             * cases, space is allocated in 8 byte chunks.
782:             */
783:            public static int byteArraySize(int arrayLen) {
784:
785:                /*
786:                 * ARRAY_OVERHEAD accounts for N bytes of data, which is 4 bytes on 32b
787:                 * Java and 0 bytes on 64b Java.  Data larger than N bytes is allocated
788:                 * in 8 byte increments.
789:                 */
790:                int size = ARRAY_OVERHEAD;
791:                if (arrayLen > ARRAY_SIZE_INCLUDED) {
792:                    size += ((arrayLen - ARRAY_SIZE_INCLUDED + 7) / 8) * 8;
793:                }
794:
795:                return size;
796:            }
797:
798:            public static int shortArraySize(int arrayLen) {
799:                return byteArraySize(arrayLen * 2);
800:            }
801:
802:            public static int intArraySize(int arrayLen) {
803:                return byteArraySize(arrayLen * 4);
804:            }
805:
806:            public static int objectArraySize(int arrayLen) {
807:                return byteArraySize(arrayLen * OBJECT_ARRAY_ITEM_OVERHEAD);
808:            }
809:
810:            void loadStats(StatsConfig config, EnvironmentStats stats) {
811:                stats.setCacheDataBytes(getCacheMemoryUsage());
812:                stats.setAdminBytes(miscMemoryUsage);
813:                stats.setLockBytes(accumulateLockUsage());
814:            }
815:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.