PageRenderTime 17ms CodeModel.GetById 11ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/IronPython_Main/Languages/Ruby/Ruby/Compiler/Generation/Profiler.cs

#
C# | 112 lines | 84 code | 13 blank | 15 comment | 6 complexity | db84ddfbf65e778211db912236696efc 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 * ironruby@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
 16using System;
 17using System.Collections.Generic;
 18using System.Diagnostics;
 19using System.Runtime.CompilerServices;
 20using System.Threading;
 21using Microsoft.Scripting.Math;
 22using IronRuby.Builtins;
 23using IronRuby.Compiler.Generation;
 24using IronRuby.Runtime;
 25
 26namespace IronRuby.Compiler.Generation {
 27    public sealed class Profiler {
 28        public struct MethodCounter {
 29            public readonly string/*!*/ Name;
 30            public readonly string/*!*/ File;
 31            public readonly int Line;
 32            public readonly long Ticks;
 33
 34            public MethodCounter(string/*!*/ name, string/*!*/ file, int line, long ticks) {
 35                Name = name;
 36                File = file;
 37                Line = line;
 38                Ticks = ticks;
 39	        }
 40
 41            public string/*!*/ Id {
 42                get {
 43                    return String.Format("{0};{1};{2}", Name, File, Line);
 44                }
 45            }
 46        }
 47
 48        public static readonly Profiler/*!*/ Instance = new Profiler();
 49        internal static long[] _ProfileTicks = new long[100];
 50        
 51        private readonly Dictionary<string/*!*/, int>/*!*/ _counters;
 52        private readonly List<long[]>/*!*/ _profiles;
 53        private static int _Index;
 54
 55        private Profiler() {
 56            _counters = new Dictionary<string, int>();
 57            _profiles = new List<long[]>();
 58        }
 59
 60        public int GetTickIndex(string/*!*/ name) {
 61            int index;
 62            lock (_counters) {
 63                if (!_counters.TryGetValue(name, out index)) {
 64                    index = _Index++;
 65                    _counters.Add(name, index);
 66                }
 67                if (index >= _ProfileTicks.Length) {
 68                    long[] newProfile = new long[index * 2];
 69                    _profiles.Add(Interlocked.Exchange(ref _ProfileTicks, newProfile));
 70                }
 71            }
 72            return index;
 73        }
 74
 75        public List<MethodCounter/*!*/>/*!*/ GetProfile() {
 76            var result = new List<MethodCounter>();
 77            lock (_counters) {
 78                // capture the current profile:
 79                long[] newProfile = new long[_ProfileTicks.Length];
 80                long[] total = Interlocked.Exchange(ref _ProfileTicks, newProfile);
 81
 82                for (int i = 0; i < _profiles.Count; i++) {
 83                    for (int j = 0; j < total.Length; j++) {
 84                        if (j < _profiles[i].Length) {
 85                            total[j] += _profiles[i][j];
 86                        }
 87                    }
 88                }
 89
 90                foreach (var counter in _counters) {
 91                    string methodName = counter.Key;
 92                    string fileName = null;
 93                    int line = 0;
 94                    if (RubyStackTraceBuilder.TryParseRubyMethodName(ref methodName, ref fileName, ref line)) {
 95                        result.Add(new MethodCounter(methodName, fileName, line, total[counter.Value]));
 96                    }
 97                }
 98            }
 99
100            return result;
101        }
102    }
103}
104
105namespace IronRuby.Runtime {
106    public static partial class RubyOps {
107        [Emitted]
108        public static void UpdateProfileTicks(int index, long entryStamp) {
109            Interlocked.Add(ref Profiler._ProfileTicks[index], Stopwatch.GetTimestamp() - entryStamp);
110        }
111    }
112}