root/juggler/tags/1.0.7/Performance/vjPerfDataBuffer.cpp

Revision 8789, 7.9 kB (checked in by patrickh, 7 years ago)

Copyright update.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
2  *
3  * VR Juggler is (C) Copyright 1998, 1999, 2000, 2001, 2002
4  *   by Iowa State University
5  *
6  * Original Authors:
7  *   Allen Bierbaum, Christopher Just,
8  *   Patrick Hartling, Kevin Meinert,
9  *   Carolina Cruz-Neira, Albert Baker
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  *
26  * -----------------------------------------------------------------
27  * File:          $RCSfile$
28  * Date modified: $Date$
29  * Version:       $Revision$
30  * -----------------------------------------------------------------
31  *
32  *************** <auto-copyright.pl END do not edit this line> ***************/
33
34
35 #include <Performance/vjPerfDataBuffer.h>
36 #include <Kernel/vjDebug.h>
37
38
39 void vjPerfDataBuffer::init (const char* _name, int _numbufs,
40                                     int _nindex) {
41     name = strdup (_name);
42     numbufs = _numbufs;
43     buffer = new buf_entry[numbufs];
44     read_begin = 0;
45     write_pos = 1;
46     lost = 0;
47     active = 0;
48     nindex = _nindex;
49 }
50
51
52
53 //: destructor
54 //: POST: all memory & buffers have been freed.
55 vjPerfDataBuffer::~vjPerfDataBuffer () {
56     active = 0;
57     delete []buffer;
58     delete name;
59 }
60
61
62
63 //: activates the buffer
64 //! POST: once this call is made, the buffer will start
65 //+       storing data whenever a set() is made and
66 //+       writing available data when requested.
67 void vjPerfDataBuffer::activate() {
68     active = 1;
69     vjDEBUG(vjDBG_PERFORMANCE,1) << "Performance Buffer " << name <<
70         " activated.\n" << vjDEBUG_FLUSH;
71 }
72
73
74
75 //: deactivates the buffer
76 //! POST: once this call is made, the buffer will,
77 //+       essentially, do nothing.  set() will not store
78 //+       any information and the write calls won't
79 //+       write anything.
80 void vjPerfDataBuffer::deactivate() {
81     active = 0;
82     /* deactivate maybe should reset the buffer so it's reactivated
83      * with a clean slate, thusly:
84      */
85     read_begin = 0;
86     write_pos = 1;
87     lost = 0;
88     vjDEBUG(vjDBG_PERFORMANCE,1) << "Performance Buffer " << name <<
89         " deactivated.\n" << vjDEBUG_FLUSH;
90
91 }
92
93
94
95 bool vjPerfDataBuffer::isActive() {
96     return active;
97 }
98
99
100
101 //: writes a new time entry to the buffer
102 //! POST: if a buffer is available, it is stamped with
103 //+       the current time and _phase.  If not, the
104 //+       'lost' counter is incremented.
105 //! ARGS: _phase - an integer index used to differentiate
106 //+       between different stamping points in the process
107 //+       that calls set. e.g. 1 = point right before
108 //+       entering some big computation, and 2 = point
109 //+       right after.
110 void vjPerfDataBuffer::set(int _phase) {
111     int tw;
112
113     if (!active)
114         return;
115
116     if (write_pos == read_begin) {
117         if (lost_lock.acquire() != -1) {
118             lost++;
119             lost_lock.release();
120         }
121         else
122             vjDEBUG(vjDBG_ALL,2) << "vjPerfDataBuffer: lock acquire "
123                        << "failed\n" << vjDEBUG_FLUSH;
124         tw = (write_pos + numbufs - 1) % numbufs;
125         buffer[tw].phase = _phase;
126         buffer[tw].ts.set();
127     }
128     else {
129         buffer[write_pos].phase = _phase;
130         buffer[write_pos].ts.set();
131         write_pos = (write_pos+1)%numbufs;
132     }
133 }
134
135
136 void vjPerfDataBuffer::set (int _phase, vjTimeStamp& _value) {
137     int tw;
138
139     if (!active)
140         return;
141
142     if (write_pos == read_begin) {
143         lost_lock.acquire();
144         lost++;
145         lost_lock.release();
146
147         // overwrite last buffer pos with most recent
148         tw = (write_pos + numbufs - 1) % numbufs;
149         buffer[tw].phase = _phase;
150         buffer[tw].ts = _value;
151     }
152     else {
153         buffer[write_pos].phase = _phase;
154         buffer[write_pos].ts = _value;
155         write_pos = (write_pos+1)%numbufs;
156     }
157 }
158
159
160     // for below: need a version w/ max # buffers to write
161
162     //: writes buffer contents to an ostream
163     //! POST: As many buffers as available are written to
164     //+       the ostream out and released so they can be
165     //+       used again by the writer.
166     //! ARGS: out - an ostream to write contents to.
167     //! NOTE: The format for a buffer is 'ind timestamp\n',
168     //+       e.g.: (for four buffers, say we have 3 indices)
169     //+       <br>1 15
170     //+       <br>2 25
171     //+       <br>3 27
172     //+       <br>1 42
173 void vjPerfDataBuffer::write (std::ostream& out) {
174     // the only tricky part of this is that the region we
175     // want to print out might wrap back around to the
176     // beginning of the list.  That's what the 2nd big
177     // case is for.
178     int begin, end, i, tlost;
179     buf_entry* b;
180
181     //out.width(13);
182
183     if (!active)
184         return;
185
186     //out << "PerfData " << name << "\n";
187     begin = read_begin;
188     end = (write_pos - 1 + numbufs)%numbufs;
189     //cout << "begin/end are " << begin <<' '<< end << endl;
190     if (begin == end)
191         return;
192     out << "PerfData1 \"" << name << "\" " << nindex << std::endl;
193     if (begin < end) {
194         for (i = begin; i < end; i++) {
195             b = &(buffer[i]);
196             out << b->phase << ' '
197                 << std::setiosflags(std::ios::fixed) << b->ts << '\n';
198         }
199     }
200     else { /* wraparound */
201         for (i = begin; i < numbufs; i++) {
202             b = &(buffer[i]);
203             out << b->phase << ' ' << std::setiosflags(std::ios::fixed)
204                 << b->ts << '\n';
205         }
206         for (i = 0; i < end; i++) {
207             b = &(buffer[i]);
208             out << b->phase << ' ' << std::setiosflags(std::ios::fixed)
209                 << b->ts << '\n';
210         }
211     }
212        
213     lost_lock.acquire();
214     tlost = lost;
215     lost = 0;
216     lost_lock.release();
217     read_begin = end;
218
219     out << -1 << ' ' << tlost << std::endl;
220
221 }
222
223
224
225 // this probably isn't safe in a multitasking environment
226 void vjPerfDataBuffer::writeTotal(std::ostream& out, int preskip, int postskip, float discrep) {
227     int begin = read_begin;
228     int end = (write_pos - 1 + numbufs)%numbufs;
229     int last = (end + numbufs-1) %numbufs;
230     float retval;
231     int nump;
232     int i;
233     float diff, avg;
234
235     retval = buffer[(end-postskip)%numbufs].ts - buffer[(begin+preskip)%numbufs].ts;
236     /*
237     cout << "begin is " << begin
238          << "\nend is " << end
239          << "\nlast is " << last << endl;
240     */
241     if (last > begin)
242         nump = last - begin;
243     else
244         nump = last + (numbufs - begin);
245
246     avg = retval/(nump - preskip - postskip);
247
248     out << "Dumping buffer: " << nump << " samples, total: "
249         << retval << " us, avg: " << avg << "us\n";
250     if (discrep > 0) {
251         out << "Reporting Discrepencies:\n";
252     }
253     end = (end-postskip)%numbufs;
254     begin = (begin + preskip)%numbufs;
255
256         if (begin == end)
257             return;
258         else if (begin < end) {
259             for (i = begin+1; i < end; i++) {
260                 diff = buffer[i].ts - buffer[i-1].ts;
261                 if (fabsf(diff - avg) > avg * discrep) {
262                     out << "    " << diff << " us at time "
263                         << buffer[i-1].ts << " us\n";
264                 }
265             }
266         }
267         else { /* wraparound */
268             for (i = begin+1; i < numbufs; i++) {
269                 diff = buffer[i].ts - buffer[i-1].ts;
270                 if (fabsf(diff - avg) > avg * discrep) {
271                     out << "    " << diff << " us at time "
272                         << buffer[i-1].ts << " us\n";
273
274                 }
275             }
276             diff = buffer[0].ts - buffer[numbufs].ts;
277             if (fabsf(diff - avg) > avg * discrep) {
278                 out << "    " << diff << " us at time "
279                     << buffer[numbufs].ts << " us\n";
280             }
281             for (i = 1; i < end; i++) {
282                 diff = buffer[i].ts - buffer[i-1].ts;
283                 if (fabsf(diff - avg) > avg * discrep) {
284                     out << "    " << diff << " us at time "
285                         << buffer[i-1].ts << " us\n";
286                 }
287             }
288        
289         }
290
291
292     lost_lock.acquire();
293     lost = 0;
294     lost_lock.release();
295     read_begin = end;
296
297 }
298
299
300 void vjPerfDataBuffer::dumpData() {
301
302     lost_lock.acquire();
303     read_begin = 0;
304     write_pos = 1;
305     lost = 0;
306     lost_lock.release();
307
308 }
Note: See TracBrowser for help on using the browser.