PageRenderTime 31ms CodeModel.GetById 8ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_Main/Runtime/Tests/SiteTest/SiteLog.cs

#
C# | 334 lines | 160 code | 31 blank | 143 comment | 13 complexity | fae0eed5a5dabfb239eb34208553edb9 MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
  6 * copy of the license can be found in the License.html file at the root of this distribution. If 
  7 * you cannot locate the  Apache License, Version 2.0, please send an email to 
  8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
  9 * by the terms of the Apache License, Version 2.0.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15
 16#if !CLR2
 17using System.Linq.Expressions;
 18#else
 19using Microsoft.Scripting.Ast;
 20#endif
 21
 22using System;
 23using System.Collections.Generic;
 24using System.Diagnostics;
 25using System.Text;
 26using System.Threading;
 27
 28namespace SiteTest {
 29    /// <summary>
 30    /// SiteLog logs the various events of a dyn site scenario.
 31    /// 
 32    /// This class is still being designed.  It should be thread-safe.
 33    /// Need to better handle performance metrics
 34    /// </summary>
 35    public class SiteLog {
 36        public delegate void Func();
 37        List<Event> _log = new List<Event>();
 38        Stopwatch logtimer = new Stopwatch();
 39
 40        Stopwatch scenarioTimer = new Stopwatch();
 41        string scenarioDescription = null;
 42
 43        public SiteLog() {
 44            logtimer.Start();
 45        }
 46
 47        /// <summary>
 48        /// Removes all recorded events from the log
 49        /// and resets the timer to 0.  This invalidates
 50        /// all pre-existing event ids.
 51        /// </summary>
 52        public void Reset() {
 53            lock (_log) {
 54                _log.Clear();
 55                logtimer.Reset();
 56                logtimer.Start();
 57            }
 58        }
 59
 60        /// <summary>
 61        /// Retrieves the log event matching
 62        /// the given event id.
 63        /// </summary>
 64        /// <param name="index"></param>
 65        /// <returns></returns>
 66        public Event this[int index] {
 67            get {
 68                return _log[index];
 69            }
 70        }
 71
 72        /// <summary>
 73        /// Returns the number of entries currently in the log.
 74        /// </summary>
 75        public int Length {
 76            get {
 77                return _log.Count;
 78            }
 79        }
 80
 81        /// <summary>
 82        /// Delegate to be used by sites to Target the Log call
 83        /// </summary>
 84        /// <param name="site"></param>
 85        /// <param name="eType"></param>
 86        /// <param name="text"></param>
 87        /// <returns></returns>
 88        public delegate int LogDel(System.Runtime.CompilerServices.CallSite site, EventType eType, string text);
 89
 90        /// <summary>
 91        /// Adds a new event to the log with the given
 92        /// description using the current time and thread
 93        /// information.
 94        /// </summary>
 95        /// <param name="eType">The type of this event</param>
 96        /// <param name="text">Description of the new event</param>
 97        /// <returns></returns>
 98        public int Log(EventType eType, string text) {
 99            Event ev = new Event();
100            ev.Time = logtimer.ElapsedMilliseconds;
101            ev.EType = eType;
102            ev.ThreadId = Thread.CurrentThread.ManagedThreadId;
103            ev.Description = text;
104            lock (_log) {
105                _log.Add(ev);
106                return _log.Count - 1 ;
107            }
108        }
109
110        /// <summary>
111        /// Adds a new event with the given type and
112        /// an empty description.
113        /// </summary>
114        /// <param name="eType">The type of this event</param>
115        /// <returns></returns>
116        public int Log(EventType eType) {
117            return Log(eType, null);
118        }
119
120        /// <summary>
121        /// Logs a ScenarioBegin event, invokes f,
122        /// logs a ScenarioEnd event and returns
123        /// the elapsed time in milliseconds.
124        /// </summary>
125        /// <param name="text">Description of the event</param>
126        /// <param name="f"></param>
127        /// <returns></returns>
128        public long TimeScenario(string text, Func f) {
129            StartTimer(text);
130            f();
131            return StopTimer();
132        }
133
134        /// <summary>
135        /// Logs a ScenarioBegin event, invokes f,
136        /// logs a ScenarioEnd event and returns
137        /// the elapsed time in milliseconds.
138        /// </summary>
139        /// <param name="f"></param>
140        /// <returns></returns>
141        public long TimeScenario(Func f) {
142            return TimeScenario(null, f);
143        }
144
145        /// <summary>
146        /// Logs a ScenarioBegin event and starts
147        /// a separate stopwatch timer.  The given
148        /// text is used as the event's long description.
149        /// </summary>
150        /// <param name="text"></param>
151        public void StartTimer(string text) {
152            if(scenarioTimer.IsRunning)
153                throw new ApplicationException("The scenario timer is already running");
154
155            scenarioDescription = text;
156            scenarioTimer.Reset();
157            Log(EventType.ScenarioBegin, text);
158            scenarioTimer.Start();
159        }
160
161        /// <summary>
162        /// Logs a ScenarioBegin event and starts
163        /// a separate stopwatch timer.
164        /// </summary>
165        public void StartTimer() {
166            StartTimer(null);
167        }
168
169        /// <summary>
170        /// Stops a running scenario stopwatch timer
171        /// logs an event and returns the number of
172        /// milliseconds elapsed since the timer was
173        /// started.
174        /// </summary>
175        /// <returns>Elapsed time in milliseconds</returns>
176        public long StopTimer() {
177            if (!scenarioTimer.IsRunning)
178                throw new ApplicationException("The scenario timer is not running");
179            Log(EventType.ScenarioEnd, scenarioDescription);
180            scenarioTimer.Stop();
181            scenarioDescription = null;
182            return scenarioTimer.ElapsedMilliseconds;
183        }
184
185        /// <summary>
186        /// Returns a pretty-printable view of the log contents
187        /// 
188        /// Don't want to override ToString because it impacts how
189        /// -X:ShowRules works.
190        /// </summary>
191        /// <returns></returns>
192        public string ToPrintableString() {
193            lock (_log) {
194                return ToPrintableString(_log.ToArray());
195            }
196        }
197
198        /// <summary>
199        /// Returns a pretty-printable view of a given list of events
200        /// </summary>
201        /// <param name="events"></param>
202        /// <returns></returns>
203        private string ToPrintableString(Event[] events) {
204            StringBuilder repr = new StringBuilder();
205            repr.AppendLine("TID\tTime\tEvent Type\t\tDescription");
206            foreach (Event e in events) {
207                repr.AppendLine(e.ToString());
208            }
209            return repr.ToString();
210        }
211
212        /// <summary>
213        /// Generates an Expression tree that, when invoked,
214        /// will append a new event to this log with the
215        /// given description and the current (at invocation time)
216        /// time and thread information.
217        /// </summary>
218        /// <param name="textExp">An Expression that returns a string that describes the new event</param>
219        /// <param name="eType"></param>
220        /// <returns></returns>
221        public Expression GenLog(EventType eType, Expression textExp) {
222            return GenLog(Expression.Constant(eType), textExp);
223        }
224
225        /// <summary>
226        /// Generates an Expression tree that, when invoked,
227        /// will append a new event to this log with the
228        /// given description and the current (at invocation time)
229        /// time and thread information.
230        /// </summary>
231        /// <param name="text">Description of the new event</param>
232        /// <param name="eType"></param>
233        /// <returns></returns>
234        public Expression GenLog(EventType eType, string text) {
235            return GenLog(eType, Expression.Constant(text, typeof(string)));
236        }
237
238        /// <summary>
239        /// Generates an Expression tree that, when invoked,
240        /// will append a new event to this log with the
241        /// given description and the current (at invocation time)
242        /// time and thread information.
243        /// </summary>
244        /// <param name="eTypeExp"></param>
245        /// <param name="textExp"></param>
246        /// <returns></returns>
247        public Expression GenLog(Expression eTypeExp, Expression textExp) {
248            return Expression.Call(Expression.Constant(this),
249                typeof(SiteLog).GetMethod("Log", new Type[] { typeof(EventType), typeof(string) }),
250                eTypeExp,
251                textExp);
252        }
253
254        /// <summary>
255        /// Compares the current log against the given
256        /// sequence of events, ignoring all extended information
257        /// (long description, threadid, timings).
258        /// </summary>
259        /// <param name="args"></param>
260        /// <returns></returns>
261        public bool MatchesEventSequence(params Event[] args) {
262            bool result = true;
263            lock (_log) {
264                if (args.Length != _log.Count)
265                    result = false;
266                else {
267                    for (int i = 0; i < _log.Count; i++) {
268                        if (args[i].EType != _log[i].EType) {
269                            result = false;
270                            break;
271                        }
272
273                        //If the baseline sequence didn't give an event description then don't compare
274                        if (args[i].Description != null) {
275                            if (args[i].Description != _log[i].Description) {
276                                result = false;
277                                break;
278                            }
279                        }
280                    }
281                }
282
283                if (!result) {
284                    Console.WriteLine("Expected:\n{0}", ToPrintableString(args));
285                    Console.WriteLine("Actual:\n{0}", ToPrintableString());
286                }
287
288                return result;
289            }
290        }
291
292        public Event CreateEvent(EventType eType) {
293            return CreateEvent(eType, null);
294        }
295
296        public Event CreateEvent(EventType eType, string descr) {
297            Event e = new Event();
298            e.EType = eType;
299            e.Description = descr;
300            return e;
301        }
302
303        /// <summary>
304        /// Represents a single log event
305        /// </summary>
306        public struct Event {
307            public int ThreadId;
308            public long Time;
309            public string Description;
310            public EventType EType;
311
312            public override string ToString() {
313                return String.Format("{0}\t{1}\t{2}\t\t{3}", ThreadId, Time, EType, Description);
314            }
315        }
316
317        /// <summary>
318        /// Enumeration of the different types of dyn site
319        /// events we care to track.  This makes it easier
320        /// to compare against an expected baseline.
321        /// </summary>
322        public enum EventType {
323            MakeRule,
324            ValidatorInvocation,
325            TestInvocation,
326            TargetInvocation,
327            CachePrune_L2,
328            CacheOverflow_L1,
329            ScenarioBegin,
330            ScenarioEnd,
331            //@TODO - Add any others...
332        }
333    }
334}