PageRenderTime 236ms CodeModel.GetById 18ms RepoModel.GetById 0ms 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
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception, CPL-1.0, CC-BY-SA-3.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1, Apache-2.0
  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. using System;
  16. using System.Collections.Generic;
  17. using System.Diagnostics;
  18. using System.Runtime.CompilerServices;
  19. using System.Threading;
  20. using Microsoft.Scripting.Math;
  21. using IronRuby.Builtins;
  22. using IronRuby.Compiler.Generation;
  23. using IronRuby.Runtime;
  24. namespace IronRuby.Compiler.Generation {
  25. public sealed class Profiler {
  26. public struct MethodCounter {
  27. public readonly string/*!*/ Name;
  28. public readonly string/*!*/ File;
  29. public readonly int Line;
  30. public readonly long Ticks;
  31. public MethodCounter(string/*!*/ name, string/*!*/ file, int line, long ticks) {
  32. Name = name;
  33. File = file;
  34. Line = line;
  35. Ticks = ticks;
  36. }
  37. public string/*!*/ Id {
  38. get {
  39. return String.Format("{0};{1};{2}", Name, File, Line);
  40. }
  41. }
  42. }
  43. public static readonly Profiler/*!*/ Instance = new Profiler();
  44. internal static long[] _ProfileTicks = new long[100];
  45. private readonly Dictionary<string/*!*/, int>/*!*/ _counters;
  46. private readonly List<long[]>/*!*/ _profiles;
  47. private static int _Index;
  48. private Profiler() {
  49. _counters = new Dictionary<string, int>();
  50. _profiles = new List<long[]>();
  51. }
  52. public int GetTickIndex(string/*!*/ name) {
  53. int index;
  54. lock (_counters) {
  55. if (!_counters.TryGetValue(name, out index)) {
  56. index = _Index++;
  57. _counters.Add(name, index);
  58. }
  59. if (index >= _ProfileTicks.Length) {
  60. long[] newProfile = new long[index * 2];
  61. _profiles.Add(Interlocked.Exchange(ref _ProfileTicks, newProfile));
  62. }
  63. }
  64. return index;
  65. }
  66. public List<MethodCounter/*!*/>/*!*/ GetProfile() {
  67. var result = new List<MethodCounter>();
  68. lock (_counters) {
  69. // capture the current profile:
  70. long[] newProfile = new long[_ProfileTicks.Length];
  71. long[] total = Interlocked.Exchange(ref _ProfileTicks, newProfile);
  72. for (int i = 0; i < _profiles.Count; i++) {
  73. for (int j = 0; j < total.Length; j++) {
  74. if (j < _profiles[i].Length) {
  75. total[j] += _profiles[i][j];
  76. }
  77. }
  78. }
  79. foreach (var counter in _counters) {
  80. string methodName = counter.Key;
  81. string fileName = null;
  82. int line = 0;
  83. if (RubyStackTraceBuilder.TryParseRubyMethodName(ref methodName, ref fileName, ref line)) {
  84. result.Add(new MethodCounter(methodName, fileName, line, total[counter.Value]));
  85. }
  86. }
  87. }
  88. return result;
  89. }
  90. }
  91. }
  92. namespace IronRuby.Runtime {
  93. public static partial class RubyOps {
  94. [Emitted]
  95. public static void UpdateProfileTicks(int index, long entryStamp) {
  96. Interlocked.Add(ref Profiler._ProfileTicks[index], Stopwatch.GetTimestamp() - entryStamp);
  97. }
  98. }
  99. }