/// <summary> /// Create a profile for a grid. /// </summary> /// <param name="grid">grid to profile</param> private GridShapeProfiler(IMyCubeGrid grid) { this.myCubeGrid = grid; myLogger = new Logger("GridShapeProfiler", () => myCubeGrid.DisplayName); this.SlimBlocks = new ListSnapshots <IMySlimBlock>(); // instead of iterating over blocks, test cells of grid for contents (no need to lock grid) ReadOnlyList <IMySlimBlock> mutable = SlimBlocks.mutable(); myCubeGrid.Min.ForEachVector(myCubeGrid.Max, (cell) => { IMySlimBlock slim = myCubeGrid.GetCubeBlock(cell); if (slim != null) { mutable.Add(slim); } return(false); }); myCubeGrid.OnBlockAdded += Grid_OnBlockAdded; myCubeGrid.OnBlockRemoved += Grid_OnBlockRemoved; myCubeGrid.OnClose += Grid_OnClose; using (lock_registry.AcquireExclusiveUsing()) registry.Add(this.myCubeGrid, this); }
/// <summary> /// Create Results from a List of execution times. /// </summary> /// <param name="executionTimes">Execution times. Results does not create a copy, so the list should not be changed.</param> internal Results(ListSnapshots<MyTimeSpan> executionTimes) { UnsortedResults = executionTimes.immutable(); Count = UnsortedResults.Count; Lazy_SortedResults = new Lazy<ReadOnlyList<MyTimeSpan>>(() => { executionTimes.mutable().Sort((MyTimeSpan first, MyTimeSpan second) => { return Math.Sign((first - second).Ticks); }); return new ReadOnlyList<MyTimeSpan>(executionTimes.immutable()); }); Lazy_Total = new Lazy<MyTimeSpan>(() => { MyTimeSpan sum = new MyTimeSpan(0); foreach (MyTimeSpan result in UnsortedResults) sum += result; return sum; }); Lazy_Mean = new Lazy<MyTimeSpan>(() => { return new MyTimeSpan(Total.Ticks / Count); }); Lazy_Median = new Lazy<MyTimeSpan>(() => SortedResults_Interpolate((decimal)Count / 2 - 0.5m)); Lazy_FirstQuartile = new Lazy<MyTimeSpan>(() => SortedResults_Interpolate((decimal)Count / 4 - 0.5m)); Lazy_ThirdQuartile = new Lazy<MyTimeSpan>(() => SortedResults_Interpolate((decimal)Count * 3 / 4 - 0.5m)); }
/// <summary> /// Time an Action /// </summary> /// <param name="action">Action to perform</param> /// <param name="iterations">Number of iterations of action</param> /// <param name="ignoreFirst">Perform an extra invokation first, that will not be timed.</param> /// <returns>Results of timing</returns> /// <exception cref="ArgumentNullException">If action == null</exception> /// <exception cref="ArgumentOutOfRangeException">If iterarions < 1</exception> public static Results Time(Action action, int iterations = 1, bool extraFirst = false) { VRage.Exceptions.ThrowIf<ArgumentNullException>(action == null, "action"); VRage.Exceptions.ThrowIf<ArgumentOutOfRangeException>(iterations < 1, "iterations < 1"); if (extraFirst) action.Invoke(); ListSnapshots<MyTimeSpan> unsortedResults = new ListSnapshots<MyTimeSpan>(iterations); ReadOnlyList<MyTimeSpan> mutable = unsortedResults.mutable(); for (int i = 0; i < iterations; i++) { MyGameTimer actionTimer = new MyGameTimer(); action.Invoke(); mutable.Add(actionTimer.Elapsed); } return new Results(unsortedResults); }
/// <summary> /// Add a block to the profile. /// </summary> private void Grid_OnBlockAdded(IMySlimBlock slim) { using (lock_SlimBlocks.AcquireExclusiveUsing()) SlimBlocks.mutable().Add(slim); }