Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: $'
7
 *     '$Date: 2009-06-13 15:28:13 +0300  $'
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 */
23
package edu.ucsb.nceas.metacat;
24

    
25
import java.io.File;
26
import java.io.FileWriter;
27
import java.io.IOException;
28
import java.util.Date;
29
import java.util.Enumeration;
30
import java.util.Hashtable;
31
import java.util.Vector;
32

    
33
/**
34
 * @author berkley
35
 *  Singleton to track metacat profile stats and print them to a CSV file
36
 */
37
public class MetacatProfiler
38
{
39
    private static MetacatProfiler profiler = null;
40
    
41
    private Hashtable<String,Profile> profiles;
42
    private String log = "";
43
    private int callOrderCount = 0;
44
    private boolean aggregateMethodCalls = true;
45
    
46
    /**
47
     * private constructor
48
     */
49
    private MetacatProfiler()
50
    {
51
        profiles = new Hashtable<String,Profile>();
52
    }
53
    
54
    /**
55
     * get a singleton instance
56
     * @return
57
     */
58
    public static MetacatProfiler getInstance()
59
    {
60
        if(profiler == null)
61
        {
62
            profiler = new MetacatProfiler();
63
        }
64
        
65
        return profiler;
66
    }
67
    
68
    /**
69
     * return a hashtable of the profiles
70
     * @return
71
     */
72
    public Hashtable<String, Profile> getProfiles()
73
    {
74
        return profiles;
75
    }
76
    
77
    /**
78
     * reset all times in the singleton 
79
     */
80
    public void reset()
81
    {
82
        profiles = new Hashtable<String, Profile>();
83
        log = "";
84
    }
85
    
86
    /**
87
     * print a message to the log in real-time
88
     * @param msg
89
     */
90
    public void printLogMsg(String msg)
91
    {
92
        log += "//" + new Date().toString() + ":" + msg + "\n";
93
    }
94
    
95
    /**
96
     * start the timing on a profile
97
     * @param profileName
98
     */
99
    public void startTime(String profileName)
100
    {
101
        long start = new Date().getTime();
102
        
103
        Profile p = profiles.get(profileName);
104
        if(!aggregateMethodCalls || p == null)
105
        {
106
            p = new Profile();
107
            p.name = profileName;    
108
            p.start = start;
109
            p.methodcalls = 0;
110
            p.total = 0;
111
            p.callorder = callOrderCount;
112
            callOrderCount++;
113
            profiles.put(profileName, p);
114
        }
115
        else
116
        {
117
            p.start = start;
118
            profiles.put(profileName, p);
119
        }
120
    }
121
    
122
    /**
123
     * stop the timing on a profile
124
     * @param profileName
125
     */
126
    public void stopTime(String profileName)
127
    {
128
        //System.out.println("\n==================stop==================");
129
        long stop = new Date().getTime();
130
        boolean found = false;
131
        Profile p = profiles.get(profileName);
132
        
133
        if(p == null)
134
        {
135
            System.out.println("WARNING: profile " + profileName + " not registered with MetacatProfiler");
136
        }
137
        else
138
        {
139
            p.stop = stop;
140
        }
141
        
142
        if(!aggregateMethodCalls)
143
        {
144
            log += p.toString();
145
        }
146
        else
147
        {
148
            if(p != null)
149
            {
150
                //System.out.println("p: " + p.toString());
151
                p.total += p.stop - p.start;
152
                p.methodcalls = p.methodcalls + 1;
153
                //System.out.println("newp: " + p.toString());
154
                profiles.put(profileName, p);
155
            }
156
            else
157
            {
158
                p = new Profile();
159
                p.methodcalls = 1;
160
                profiles.put(profileName, p);
161
            }
162
        }
163
    }
164
    
165
    /**
166
     * sort the profiles by "callorder", "callcount" or "total"
167
     * @param sortKey
168
     * @return
169
     */
170
    public Profile[] sortProfiles(String sortKey)
171
    {
172
       Vector<Profile> v = new Vector<Profile>();
173
       Enumeration keys = profiles.keys();
174
       Profile[] pArr = new Profile[profiles.size()];
175
       int i = 0;
176
       while(keys.hasMoreElements())
177
       {
178
           String key = (String)keys.nextElement();
179
           pArr[i] = profiles.get(key);
180
           i++;
181
       }
182
       
183
       int n = profiles.size();
184
       for (int pass=1; pass < n; pass++) {  // count how many times
185
           // This next loop becomes shorter and shorter
186
           for (i=0; i < n-pass; i++) {
187
               long x = 0;
188
               long y = 0;
189
               if(sortKey.equals("callorder"))
190
               {
191
                   x = pArr[i].callorder;
192
                   y = pArr[i+1].callorder;
193
               }
194
               else if(sortKey.equals("callcount"))
195
               {
196
                   x = pArr[i].methodcalls;
197
                   y = pArr[i+1].methodcalls;
198
               }
199
               else
200
               { //default by total
201
                   x = pArr[i].total;
202
                   y = pArr[i+1].total;
203
               }
204
               
205
               if (x < y) {
206
                   // exchange elements
207
                   Profile temp = pArr[i];  
208
                   pArr[i] = pArr[i+1];  
209
                   pArr[i+1] = temp;
210
               }
211
           }
212
       }
213

    
214
       return pArr;
215
    }
216
    
217
    /**
218
     * print a sorted CSV file.  The sortKey can be "callorder", "callcount" or "total"
219
     * @param f
220
     * @param sortKey
221
     * @throws IOException
222
     */
223
    public void printSortedCSV(File f, String sortKey) throws IOException
224
    {
225
        Profile[] p = sortProfiles(sortKey);
226
        String log2 = "";
227
        log2 = "\n" + log + "\n" + "=======profile entries sorted by " + sortKey + "========\n";
228
        for(int i=0; i<p.length; i++)
229
        {
230
            log2 += p[i].toString() + "\n";
231
        }
232
        log2 += "=======end profile entries========";
233
        System.out.println(log2);
234
        if(f != null)
235
        {
236
            FileWriter fw = new FileWriter(f, true);
237
            fw.write(log2);
238
            fw.flush();
239
            fw.close();
240
        }
241
    }
242
    
243
    /**
244
     * print the CSV file with no sorting
245
     * @param f
246
     * @throws IOException
247
     */
248
    public void printCSV(File f) throws IOException
249
    {
250
        if(aggregateMethodCalls)
251
        {
252
            Enumeration keys = profiles.keys();
253
            while(keys.hasMoreElements())
254
            {
255
                String key = (String)keys.nextElement();
256
                Profile p = profiles.get(key);
257
                log += p.toString();
258
            }
259
        }
260
        
261
        FileWriter fw = new FileWriter(f, true);
262
        fw.write(log);
263
        fw.flush();
264
        fw.close();
265
    }
266
    
267
    /**
268
     * container class for profile information
269
     * @author berkley
270
     *
271
     */
272
    public class Profile
273
    {
274
        public long start;
275
        public long stop;
276
        public long total = -1;
277
        public long methodcalls;
278
        public long callorder;
279
        public String name;
280
        
281
        public String toString()
282
        {
283
            if(total == -1)
284
            {
285
                total = stop - start;
286
            }
287
            return "name: " + name + ", calls: " + methodcalls + ", totaltime: " + total;
288
        }
289
    }
290
}
(43-43/63)