001    // Stats.java, created by wbeebee
002    // Copyright (C) 2001 Wes Beebee <wbeebee@mit.edu>
003    // Licensed under the terms of the GNU GPL; see COPYING for details.
004    package javax.realtime;
005    
006    /** <code>Stats</code> keeps track of Runtime statistics of how many
007     *  objects are created, access checks done from which MemoryArea to 
008     *  which MemoryArea, etc.  Stats.print() allows you to print out 
009     *  this information and must be present right before termination of
010     *  any program which you want to collect these statistics from.
011     *
012     * @author Wes Beebee <<a href="mailto:wbeebee@mit.edu">wbeebee@mit.edu</a>>
013     */
014    
015    public final class Stats {
016        
017        /** Count how many access checks are done in total. */
018        private static long accessChecks = 0;
019    
020        /** Count how many new objects are created. */
021        private static long newObjects = 0;
022    
023        /** Count how many array objects are created. */
024        private static long newArrayObjects = 0;
025        
026        /** How many HeapMemory -> HeapMemory assignments? */
027        private static long HEAP_TO_HEAP = 0;
028    
029        /** How many HeapMemory -> ScopedMemory assignments? */
030        private static long HEAP_TO_SCOPE = 0;
031    
032        /** How many HeapMemory -> ImmortalMemory assignments? */
033        private static long HEAP_TO_IMMORTAL = 0;
034    
035        /** How many ScopedMemory -> HeapMemory assignments? */
036        private static long SCOPE_TO_HEAP = 0;
037    
038        /** How many ScopedMemory -> ScopedMemory assignments? */
039        private static long SCOPE_TO_SCOPE = 0;
040    
041        /** How many ScopedMemory -> ImmortalMemory assignments? */
042        private static long SCOPE_TO_IMMORTAL = 0;
043    
044        /** How many ImmortalMemory -> HeapMemory assignments? */
045        private static long IMMORTAL_TO_HEAP = 0;
046    
047        /** How many ImmortalMemory -> ScopedMemory assignments? */
048        private static long IMMORTAL_TO_SCOPE = 0;
049    
050        /** How many ImmortalMemory -> ImmortalMemory assignments? */
051        private static long IMMORTAL_TO_IMMORTAL = 0;
052        
053        /** How many objects were allocated out of HeapMemory? */
054        private static long NEW_HEAP = 0;
055        
056        /** How many objects were allocated out of ScopedMemory? */
057        private static long NEW_SCOPE = 0;
058    
059        /** How many objects were allocated out of ImmortalMemory? */
060        private static long NEW_IMMORTAL = 0;
061    
062        /** How many array objects were allocated out of HeapMemory? */
063        private static long NEW_ARRAY_HEAP = 0;
064    
065        /** How many array objects were allocated out of ScopedMemory? */
066        private static long NEW_ARRAY_SCOPE = 0;
067    
068        /** How many array objects were allocated out of ImmortalMemory? */
069        private static long NEW_ARRAY_IMMORTAL = 0;
070    
071        /** How many checks to the heap were there? */
072        public static long heapChecks = 0;
073        
074        /** How many pointers to the heap were dereferenced? */
075        public static long heapRefs = 0;
076    
077        /** How many checks on READ of a base pointer were there? */
078        public static long READ_CHECKS = 0;
079    
080        /** How many base pointers on READ were actually pointing to the heap? */
081        public static long READ_REFS = 0;
082        
083        /** How many checks on WRITE to a location were there? */
084        public static long WRITE_CHECKS = 0;
085        
086        /** How many checks on WRITE to a location previously pointing to the heap?
087         */
088        public static long WRITE_REFS = 0;
089        
090        /** How many checks on NATIVECALL returns were there? */
091        public static long NATIVECALL_CHECKS = 0;
092        
093        /** How many NATIVECALL's returned something that pointed to the heap? */
094        public static long NATIVECALL_REFS = 0;
095    
096        /** How many checks on CALL returns were there? */
097        public static long CALL_CHECKS = 0;
098    
099        /** How many CALL's returned something that pointed to the heap? */
100        public static long CALL_REFS = 0;
101    
102        /** How many checks on METHOD calls were there? */
103        public static long METHOD_CHECKS = 0;
104    
105        /** How many parameters passed into METHODs were actually pointing to 
106         *  the heap? 
107         */
108        public static long METHOD_REFS = 0;
109    
110        /** Should we still be collecting heap reference statistics? */
111        public static long COLLECT_HEAP_STATS = 1;
112    
113        /** Has anything been added? */
114        /** If not, it's possible that the user
115         *  did not compile with the _STATS compiler option to add Runtime
116         *  statistics to the compiled output. 
117         */
118        private static boolean touched = false;
119        
120        /** Add an access check from one MemoryArea to another MemoryArea. 
121         */
122        public synchronized final static void addCheck(MemoryArea from,
123                                          MemoryArea to) {
124            touched = true;
125            if (from.heap) {
126                if (to.heap) {
127                    HEAP_TO_HEAP++;
128                } else if (to.scoped) {
129                    HEAP_TO_SCOPE++;
130                } else {
131                    HEAP_TO_IMMORTAL++;
132                }
133            } else if (from.scoped) {
134                if (to.heap) {
135                    SCOPE_TO_HEAP++;
136                } else if (to.scoped) {
137                    SCOPE_TO_SCOPE++;
138                } else {
139                    SCOPE_TO_IMMORTAL++;
140                }
141            } else {
142                if (to.heap) {
143                    IMMORTAL_TO_HEAP++;
144                } else if (to.scoped) {
145                    IMMORTAL_TO_SCOPE++;
146                } else {
147                    IMMORTAL_TO_IMMORTAL++;
148                }
149            }
150            accessChecks++; 
151        }
152    
153        /** Add a new object to the statistics for that MemoryArea. 
154         */
155        public synchronized final static void addNewObject(MemoryArea to) {
156            touched = true;
157            if (to.heap) {
158                NEW_HEAP++;
159            } else if (to.scoped) {
160                NEW_SCOPE++;
161            } else {
162                NEW_IMMORTAL++;
163            }
164            newObjects++;
165        }
166        
167        /** Add a new array object to the statistics for that MemoryArea. 
168         */
169        public synchronized final static void addNewArrayObject(MemoryArea to) {
170            touched = true;
171            if (to.heap) {
172                NEW_ARRAY_HEAP++;
173            } else if (to.scoped) {
174                NEW_ARRAY_SCOPE++;
175            } else {
176                NEW_ARRAY_IMMORTAL++;
177            }
178            newArrayObjects++;
179        }
180        
181        /** Print out the statistics for this program.  You must place
182         *  Stats.print() at the end of your programs if you want to
183         *  display the Runtime statistics of your program.  You also
184         *  need to compile with the _STATS option to tell the compiler 
185         *  to output calls to the above methods in order to collect these
186         *  statistics.  Note that when _STATS is on, you cannot say 
187         *  anything about the runtime of the program, because it takes
188         *  significant time to collect information about your program.
189         */
190    
191        public synchronized final static void print() {
192            COLLECT_HEAP_STATS = 0;
193            if (touched) {
194                NoHeapRealtimeThread.print("-------------------------------------\n");
195                NoHeapRealtimeThread.print("Dynamic statistics for Realtime Java:\n");
196                NoHeapRealtimeThread.print("Number of access checks: ");
197                NoHeapRealtimeThread.print(accessChecks);
198                NoHeapRealtimeThread.print("\nNumber of objects created: ");
199                NoHeapRealtimeThread.print(newObjects);
200                NoHeapRealtimeThread.print("\nNumber of array objects created: ");
201                NoHeapRealtimeThread.print(newArrayObjects);
202                NoHeapRealtimeThread.print("\n-------------------------------------\n");
203                
204                NoHeapRealtimeThread.print("Checks:\n  Heap     -> Heap:    ");
205                NoHeapRealtimeThread.print(HEAP_TO_HEAP);
206                NoHeapRealtimeThread.print("\n  Heap     -> Scope:   ");
207                NoHeapRealtimeThread.print(HEAP_TO_SCOPE);
208                NoHeapRealtimeThread.print("\n  Heap     -> Immortal:");
209                NoHeapRealtimeThread.print(HEAP_TO_IMMORTAL);
210                NoHeapRealtimeThread.print("\n  Scope    -> Heap:    ");
211                NoHeapRealtimeThread.print(SCOPE_TO_HEAP);
212                NoHeapRealtimeThread.print("\n  Scope    -> Scope:   ");
213                NoHeapRealtimeThread.print(SCOPE_TO_SCOPE);
214                NoHeapRealtimeThread.print("\n  Scope    -> Immortal:");
215                NoHeapRealtimeThread.print(SCOPE_TO_IMMORTAL);
216                NoHeapRealtimeThread.print("\n  Immortal -> Heap:    ");
217                NoHeapRealtimeThread.print(IMMORTAL_TO_HEAP);
218                NoHeapRealtimeThread.print("\n  Immortal -> Scope:   ");
219                NoHeapRealtimeThread.print(IMMORTAL_TO_SCOPE);
220                NoHeapRealtimeThread.print("\n  Immortal -> Immortal:");
221                NoHeapRealtimeThread.print(IMMORTAL_TO_IMMORTAL);
222                NoHeapRealtimeThread.print("\n\nNew objects: \n  in heap:    ");
223                NoHeapRealtimeThread.print(NEW_HEAP);
224                NoHeapRealtimeThread.print("\n  in scope:   ");
225                NoHeapRealtimeThread.print(NEW_SCOPE);
226                NoHeapRealtimeThread.print("\n  in immortal:");
227                NoHeapRealtimeThread.print(NEW_IMMORTAL);
228                NoHeapRealtimeThread.print("\n\nNew arrays: ");
229                NoHeapRealtimeThread.print("\n  in heap:    ");
230                NoHeapRealtimeThread.print(NEW_ARRAY_HEAP);
231                NoHeapRealtimeThread.print("\n  in scope:   ");
232                NoHeapRealtimeThread.print(NEW_ARRAY_SCOPE);
233                NoHeapRealtimeThread.print("\n  in immortal:");
234                NoHeapRealtimeThread.print(NEW_ARRAY_IMMORTAL);
235            }
236            if ((heapChecks!=0)||(heapRefs!=0)) {
237                touched = true;
238                NoHeapRealtimeThread.print("\n-------------------------------------");
239                NoHeapRealtimeThread.print("\nHeap checks: ");
240                NoHeapRealtimeThread.print(heapChecks);
241                NoHeapRealtimeThread.print(" refs: ");
242                NoHeapRealtimeThread.print(heapRefs);
243                NoHeapRealtimeThread.print("\n  Write checks: ");
244                NoHeapRealtimeThread.print(WRITE_CHECKS);
245                NoHeapRealtimeThread.print(" refs: ");
246                NoHeapRealtimeThread.print(WRITE_REFS);
247                NoHeapRealtimeThread.print("\n  Read checks: ");
248                NoHeapRealtimeThread.print(READ_CHECKS);
249                NoHeapRealtimeThread.print(" refs: ");
250                NoHeapRealtimeThread.print(READ_REFS);
251                NoHeapRealtimeThread.print("\n  NATIVECALL checks: ");
252                NoHeapRealtimeThread.print(NATIVECALL_CHECKS);
253                NoHeapRealtimeThread.print(" refs: ");
254                NoHeapRealtimeThread.print(NATIVECALL_REFS);
255                NoHeapRealtimeThread.print("\n  CALL checks: ");
256                NoHeapRealtimeThread.print(CALL_CHECKS);
257                NoHeapRealtimeThread.print(" refs: ");
258                NoHeapRealtimeThread.print(CALL_REFS);
259                NoHeapRealtimeThread.print("\n  METHOD checks: ");
260                NoHeapRealtimeThread.print(METHOD_CHECKS);
261                NoHeapRealtimeThread.print(" refs: ");
262                NoHeapRealtimeThread.print(METHOD_REFS);
263            }
264            if (touched) {
265                NoHeapRealtimeThread.print("\n-------------------------------------\n");
266                if ((HEAP_TO_HEAP+HEAP_TO_SCOPE+HEAP_TO_IMMORTAL+SCOPE_TO_HEAP+
267                     SCOPE_TO_SCOPE+SCOPE_TO_IMMORTAL+IMMORTAL_TO_HEAP+
268                     IMMORTAL_TO_SCOPE+IMMORTAL_TO_IMMORTAL)!=accessChecks) {
269                    NoHeapRealtimeThread.print("Access checks don't add up!\n");
270                }
271                if ((NEW_HEAP+NEW_SCOPE+NEW_IMMORTAL)!=newObjects) {
272                    NoHeapRealtimeThread.print("New object's don't add up!\n");
273                }
274                if ((NEW_ARRAY_HEAP+NEW_ARRAY_SCOPE+
275                     NEW_ARRAY_IMMORTAL)!=newArrayObjects) {
276                    NoHeapRealtimeThread.print("New array objects don't add up!\n");
277                }
278                if ((WRITE_CHECKS+READ_CHECKS+NATIVECALL_CHECKS+CALL_CHECKS+
279                     METHOD_CHECKS)!=heapChecks) {
280                    NoHeapRealtimeThread.print("Heap checks just don't add up!\n");
281                }
282                if ((WRITE_REFS+READ_REFS+NATIVECALL_REFS+CALL_REFS+
283                     METHOD_REFS)!=heapRefs) {
284                    NoHeapRealtimeThread.print("Heap refs just don't add up!\n");
285                }       
286            } else {
287                NoHeapRealtimeThread.print("Did you forget to compile with the STATS option?\n");
288            }
289        }
290    }