Advertisement
klassekatze

Profiler.cs

Oct 6th, 2023 (edited)
1,260
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 6.47 KB | None | 0 0
  1. using Sandbox.ModAPI.Ingame;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7.  
  8. namespace IngameScript
  9. {
  10.     public partial class Program : MyGridProgram
  11.     {
  12. static void bapp(StringBuilder b, params object[] args)
  13.         {
  14.             foreach(object a in args)
  15.             {
  16.                 b.Append(a.ToString());
  17.             }
  18.         }
  19.  
  20.         public class Profiler
  21.         {
  22.  
  23.  
  24.             static bool PROFILING_ENABLED = true;
  25.             static List<Profiler> profilers = new List<Profiler>();
  26.             const int mstracklen = 60;
  27.             double[] mstrack = new double[mstracklen];
  28.             double msdiv = 1.0d / mstracklen;
  29.             int mscursor = 0;
  30.             DateTime start_time = DateTime.MinValue;
  31.             string Name = "";
  32.             string pre = "";
  33.             string post = "";
  34.             int _ticks_between_calls = 1;
  35.             int ltick = int.MinValue;
  36.             //..int callspertick = 1;
  37.  
  38.             static int base_sort_position_c = 0;
  39.             int base_sort_position = 0;
  40.  
  41.             bool nevercalled = true;
  42.             //bool closed = true;
  43.             public int getSortPosition()
  44.             {
  45.                 if (nevercalled) return int.MaxValue;
  46.                 int mult = (int)Math.Pow(10, 8 - (depth * 2));
  47.                 if (parent != null) return parent.getSortPosition() + (base_sort_position * mult);
  48.                 return base_sort_position * mult;
  49.             }
  50.             static int basep = (int)Math.Pow(10, 5);
  51.             public Profiler(string name)
  52.             {
  53.                 if (PROFILING_ENABLED)
  54.                 {
  55.                     Name = name;
  56.                     profilers.Add(this);
  57.                     for(var i =0; i < mstracklen; i++)mstrack[i] = 0;
  58.                     base_sort_position = base_sort_position_c;
  59.                     base_sort_position_c += 1;
  60.                 }
  61.             }
  62.             public void s()
  63.             {
  64.                 start();
  65.             }
  66.             public void e()
  67.             {
  68.                 stop();
  69.             }
  70.             static List<Profiler> stack = new List<Profiler>();
  71.             Profiler parent = null;
  72.             int depth = 0;
  73.             bool adding = false;
  74.             public void start()
  75.             {
  76.                 if (PROFILING_ENABLED)
  77.                 {
  78.                     //closed = false;
  79.                     nevercalled = false;
  80.                     if (tick != ltick)
  81.                     {
  82.                         if (_ticks_between_calls == 1 && ltick != int.MinValue)
  83.                         {
  84.                             _ticks_between_calls = tick - ltick;
  85.                         }else
  86.                         {
  87.                             var tbc = tick - ltick;
  88.                             if (tbc != _ticks_between_calls)
  89.                             {
  90.                                 _ticks_between_calls = 1;
  91.                                 for (var i = 0; i < mstracklen; i++) mstrack[i] = 0;
  92.                             }
  93.                         }
  94.  
  95.                         ltick = tick;
  96.                         //callspertick = 1;
  97.                         adding = false;
  98.                     }
  99.                     else
  100.                     {
  101.                         adding = true;
  102.                     }
  103.                     if (depth == 0) depth = stack.Count;
  104.                     if (depth > 11) depth = 11;
  105.                     if (stack.Count > 0 && parent == null) parent = stack[stack.Count - 1];
  106.                     stack.Add(this);
  107.                     start_time = DateTime.Now;
  108.                 }
  109.             }
  110.             double lastms = 0;
  111.             double average = 0;
  112.  
  113.  
  114.             /// <summary>
  115.             /// records a fake ms consumption for this timeframe - for tests or demo
  116.             /// </summary>
  117.             public double FAKE_stop(double fakems)
  118.             {
  119.                 return stop(fakems);
  120.             }
  121.             /// <summary>
  122.             /// adds the elapsed time since start() to the records
  123.             /// </summary>
  124.             public double stop()
  125.             {
  126.                 double time = 0;
  127.                 if (PROFILING_ENABLED)
  128.                 {
  129.                     //closed = true;
  130.                     time = (DateTime.Now - start_time).TotalMilliseconds;
  131.                 }
  132.                 return stop(time);
  133.             }
  134.  
  135.             private double stop(double _ms)
  136.             {
  137.                 double time = 0;
  138.                 if (PROFILING_ENABLED)
  139.                 {
  140.                     time = _ms;
  141.  
  142.                     stack.Pop();
  143.                     if (parent != null)
  144.                     {
  145.                         depth = parent.depth + 1;
  146.                     }
  147.  
  148.                     //if(!adding)mscursor = (mscursor + 1) % mstracklen;
  149.  
  150.  
  151.                     if (!adding) mstrack[mscursor] = 0;
  152.                     mstrack[mscursor] += time;
  153.                     if (!adding) mscursor = (mscursor + 1) % mstracklen;
  154.  
  155.                     average = 0d;
  156.                     foreach (double ms in mstrack) average += ms;
  157.                     average *= msdiv;
  158.                     average /= _ticks_between_calls;
  159.                     lastms = time;
  160.                 }
  161.                 return time;
  162.             }
  163.             /// <summary>
  164.             /// generates a monospaced report text. If called every tick, every 120 ticks it will recalculate treeview data.
  165.             /// </summary>
  166.             //the treeview can be initially inaccurate as some profilers might not be called every tick, depending on program architecture
  167.             public string getReport(StringBuilder bu)
  168.             {
  169.                 if (PROFILING_ENABLED)
  170.                 {
  171.                     if (tick % 120 == 25)//recalculate hacky treeview data, delayed by 25 ticks from program start
  172.                     {
  173.                         try
  174.                         {
  175.                             profilers.Sort(delegate (Profiler x, Profiler y)
  176.                             {
  177.                                 return x.getSortPosition().CompareTo(y.getSortPosition());
  178.                             });
  179.                         }
  180.                         catch (Exception) { }
  181.  
  182.                         for (int i = 0; i < profilers.Count; i++)
  183.                         {
  184.                             Profiler p = profilers[i];
  185.  
  186.                             p.pre = "";
  187.                             if (p.depth > 0 && p.parent != null)
  188.                             {
  189.                                 bool parent_has_future_siblings = false;
  190.                                 bool has_future_siblings_under_parent = false;
  191.                                 for (int b = i + 1; b < profilers.Count; b++)
  192.                                 {
  193.                                     if (profilers[b].depth == p.parent.depth) parent_has_future_siblings = true;
  194.                                     if (profilers[b].depth == p.depth) has_future_siblings_under_parent = true;
  195.                                     if (profilers[b].depth < p.depth) break;
  196.  
  197.                                 }
  198.                                 while (p.pre.Length < p.parent.depth)
  199.                                 {
  200.                                     if (parent_has_future_siblings) p.pre += "│";
  201.                                     else p.pre += " ";
  202.                                 }
  203.                                 bool last = false;
  204.  
  205.                                 if (!has_future_siblings_under_parent)
  206.                                 {
  207.                                     if (i < profilers.Count - 1)
  208.                                     {
  209.                                         if (profilers[i + 1].depth != p.depth) last = true;
  210.                                     }
  211.                                     else last = true;
  212.                                 }
  213.                                 if (last) p.pre += "└";
  214.                                 else p.pre += "├";
  215.                                 while (p.pre.Length < p.depth) p.pre += "─";
  216.                             }
  217.                         }
  218.                         int mlen = 0;
  219.                         foreach (Profiler p in profilers) if (p.pre.Length + p.Name.Length > mlen) mlen = p.pre.Length + p.Name.Length;
  220.                         foreach (Profiler p in profilers)
  221.                         {
  222.                             p.post = "";
  223.                             int l = p.pre.Length + p.Name.Length + p.post.Length;
  224.                             if (l < mlen) p.post = new string('_', mlen - l);
  225.                         }
  226.                     }
  227.                     if (nevercalled) bapp(bu, "!!!!", Name , "!!!!: NEVER CALLED!");
  228.                     else bapp(bu, pre, Name, post, ": " , lastms.ToString("0.00") , ";", average.ToString("0.00"));
  229.                 }
  230.                 return "";
  231.             }
  232.             static public string getAllReports()
  233.             {
  234.                 StringBuilder b = new StringBuilder();
  235.                 //string r = "";
  236.                 if (PROFILING_ENABLED)
  237.                 {
  238.                     foreach (Profiler watch in profilers)
  239.                     {
  240.                         watch.getReport(b);
  241.                         b.Append("\n");
  242.                     }
  243.                 }
  244.                 if (stack.Count > 0)
  245.                 {
  246.                     bapp(b,"profile stack error:\n", stack.Count, "\n");
  247.                     foreach (var s in stack)
  248.                     {
  249.                         bapp(b, s.Name, ",");
  250.                     }
  251.                 }
  252.                 return b.ToString();
  253.             }
  254.         }
  255.     }
  256. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement