OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
EventHistogram.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 using System;
29 using System.Collections.Generic;
30 using System.Linq;
31 using System.Text;
32 
33 using OpenMetaverse.StructuredData;
34 
35 namespace OpenSim.Framework.Monitoring
36 {
37 // Create a time histogram of events. The histogram is built in a wrap-around
38 // array of equally distributed buckets.
39 // For instance, a minute long histogram of second sized buckets would be:
40 // new EventHistogram(60, 1000)
41 public class EventHistogram
42 {
43  private int m_timeBase;
44  private int m_numBuckets;
45  private int m_bucketMilliseconds;
46  private int m_lastBucket;
47  private int m_totalHistogramMilliseconds;
48  private long[] m_histogram;
49  private object histoLock = new object();
50 
51  public EventHistogram(int numberOfBuckets, int millisecondsPerBucket)
52  {
53  m_numBuckets = numberOfBuckets;
54  m_bucketMilliseconds = millisecondsPerBucket;
55  m_totalHistogramMilliseconds = m_numBuckets * m_bucketMilliseconds;
56 
57  m_histogram = new long[m_numBuckets];
58  Zero();
59  m_lastBucket = 0;
60  m_timeBase = Util.EnvironmentTickCount();
61  }
62 
63  public void Event()
64  {
65  this.Event(1);
66  }
67 
68  // Record an event at time 'now' in the histogram.
69  public void Event(int cnt)
70  {
71  lock (histoLock)
72  {
73  // The time as displaced from the base of the histogram
74  int bucketTime = Util.EnvironmentTickCountSubtract(m_timeBase);
75 
76  // If more than the total time of the histogram, we just start over
77  if (bucketTime > m_totalHistogramMilliseconds)
78  {
79  Zero();
80  m_lastBucket = 0;
81  m_timeBase = Util.EnvironmentTickCount();
82  }
83  else
84  {
85  // To which bucket should we add this event?
86  int bucket = bucketTime / m_bucketMilliseconds;
87 
88  // Advance m_lastBucket to the new bucket. Zero any buckets skipped over.
89  while (bucket != m_lastBucket)
90  {
91  // Zero from just after the last bucket to the new bucket or the end
92  for (int jj = m_lastBucket + 1; jj <= Math.Min(bucket, m_numBuckets - 1); jj++)
93  {
94  m_histogram[jj] = 0;
95  }
96  m_lastBucket = bucket;
97  // If the new bucket is off the end, wrap around to the beginning
98  if (bucket > m_numBuckets)
99  {
100  bucket -= m_numBuckets;
101  m_lastBucket = 0;
102  m_histogram[m_lastBucket] = 0;
103  m_timeBase += m_totalHistogramMilliseconds;
104  }
105  }
106  }
107  m_histogram[m_lastBucket] += cnt;
108  }
109  }
110 
111  // Get a copy of the current histogram
112  public long[] GetHistogram()
113  {
114  long[] ret = new long[m_numBuckets];
115  lock (histoLock)
116  {
117  int indx = m_lastBucket + 1;
118  for (int ii = 0; ii < m_numBuckets; ii++, indx++)
119  {
120  if (indx >= m_numBuckets)
121  indx = 0;
122  ret[ii] = m_histogram[indx];
123  }
124  }
125  return ret;
126  }
127 
129  {
130  OSDMap ret = new OSDMap();
131 
132  ret.Add("Buckets", OSD.FromInteger(m_numBuckets));
133  ret.Add("BucketMilliseconds", OSD.FromInteger(m_bucketMilliseconds));
134  ret.Add("TotalMilliseconds", OSD.FromInteger(m_totalHistogramMilliseconds));
135 
136  // Compute a number for the first bucket in the histogram.
137  // This will allow readers to know how this histogram relates to any previously read histogram.
138  int baseBucketNum = (m_timeBase / m_bucketMilliseconds) + m_lastBucket + 1;
139  ret.Add("BaseNumber", OSD.FromInteger(baseBucketNum));
140 
141  ret.Add("Values", GetHistogramAsOSDArray());
142 
143  return ret;
144  }
145  // Get a copy of the current histogram
147  {
148  OSDArray ret = new OSDArray(m_numBuckets);
149  lock (histoLock)
150  {
151  int indx = m_lastBucket + 1;
152  for (int ii = 0; ii < m_numBuckets; ii++, indx++)
153  {
154  if (indx >= m_numBuckets)
155  indx = 0;
156  ret[ii] = OSD.FromLong(m_histogram[indx]);
157  }
158  }
159  return ret;
160  }
161 
162  // Zero out the histogram
163  public void Zero()
164  {
165  lock (histoLock)
166  {
167  for (int ii = 0; ii < m_numBuckets; ii++)
168  m_histogram[ii] = 0;
169  }
170  }
171 }
172 
173 }
OpenMetaverse.StructuredData.OSDArray OSDArray
OpenMetaverse.StructuredData.OSDMap OSDMap
EventHistogram(int numberOfBuckets, int millisecondsPerBucket)