Commit 51445c78 authored by Marc Gravell's avatar Marc Gravell

rename GetCommands() back to FinishProfiling() (akin to v1); add some obvious...

rename GetCommands() back to FinishProfiling() (akin to v1); add some obvious methods that avoid LINQ-to-Objects in a few cases, exploiting the fact that we can calculate the count as we reverse the list
parent 090cb210
...@@ -596,7 +596,7 @@ public void SimpleProfiling() ...@@ -596,7 +596,7 @@ public void SimpleProfiling()
var val = db.StringGet(key); var val = db.StringGet(key);
Assert.Equal("world", val); Assert.Equal("world", val);
var msgs = profiler.GetCommands(); var msgs = profiler.FinishProfiling();
Log("Checking GET..."); Log("Checking GET...");
Assert.Contains(msgs, m => m.Command == "GET"); Assert.Contains(msgs, m => m.Command == "GET");
Log("Checking SET..."); Log("Checking SET...");
......
...@@ -35,7 +35,7 @@ public void Simple() ...@@ -35,7 +35,7 @@ public void Simple()
var s = (string)db.Execute("ECHO", "fii"); var s = (string)db.Execute("ECHO", "fii");
Assert.Equal("fii", s); Assert.Equal("fii", s);
var cmds = session.GetCommands(); var cmds = session.FinishProfiling();
var i = 0; var i = 0;
foreach (var cmd in cmds) foreach (var cmd in cmds)
{ {
...@@ -121,7 +121,7 @@ public void ManyThreads() ...@@ -121,7 +121,7 @@ public void ManyThreads()
threads.ForEach(thread => thread.Start()); threads.ForEach(thread => thread.Start());
threads.ForEach(thread => thread.Join()); threads.ForEach(thread => thread.Join());
var allVals = session.GetCommands(); var allVals = session.FinishProfiling();
var relevant = allVals.Where(cmd => cmd.Db > 0).ToList(); var relevant = allVals.Where(cmd => cmd.Db > 0).ToList();
var kinds = relevant.Select(cmd => cmd.Command).Distinct().ToList(); var kinds = relevant.Select(cmd => cmd.Command).Distinct().ToList();
...@@ -178,7 +178,7 @@ public void ManyContexts() ...@@ -178,7 +178,7 @@ public void ManyContexts()
Task.WaitAll(allTasks.ToArray()); Task.WaitAll(allTasks.ToArray());
results[ix] = profiler.GetSession().GetCommands(); results[ix] = profiler.GetSession().FinishProfiling();
}); });
threads.Add(thread); threads.Add(thread);
...@@ -252,7 +252,7 @@ public void LowAllocationEnumerable() ...@@ -252,7 +252,7 @@ public void LowAllocationEnumerable()
conn.WaitAll(allTasks.ToArray()); conn.WaitAll(allTasks.ToArray());
var res = session.GetCommands(); var res = session.FinishProfiling();
Assert.True(res.GetType().IsValueType); Assert.True(res.GetType().IsValueType);
using (var e = res.GetEnumerator()) using (var e = res.GetEnumerator())
...@@ -312,7 +312,7 @@ public void ProfilingMD_Ex1() ...@@ -312,7 +312,7 @@ public void ProfilingMD_Ex1()
threads.ForEach(thread => thread.Start()); threads.ForEach(thread => thread.Start());
threads.ForEach(thread => thread.Join()); threads.ForEach(thread => thread.Join());
IEnumerable<IProfiledCommand> timings = session.GetCommands(); IEnumerable<IProfiledCommand> timings = session.FinishProfiling();
Assert.Equal(16000, timings.Count()); Assert.Equal(16000, timings.Count());
} }
...@@ -349,7 +349,7 @@ public void ProfilingMD_Ex2() ...@@ -349,7 +349,7 @@ public void ProfilingMD_Ex2()
Task.WaitAll(threadTasks.ToArray()); Task.WaitAll(threadTasks.ToArray());
perThreadTimings[Thread.CurrentThread] = profiler.GetSession().GetCommands().ToList(); perThreadTimings[Thread.CurrentThread] = profiler.GetSession().FinishProfiling().ToList();
}); });
threads.Add(thread); threads.Add(thread);
...@@ -388,7 +388,7 @@ public async Task ProfilingMD_Ex2_Async() ...@@ -388,7 +388,7 @@ public async Task ProfilingMD_Ex2_Async()
await db.StringSetAsync(prefix + j, "" + j); await db.StringSetAsync(prefix + j, "" + j);
} }
perThreadTimings.Add(profiler.GetSession().GetCommands().ToList()); perThreadTimings.Add(profiler.GetSession().FinishProfiling().ToList());
}); });
tasks.Add(task); tasks.Add(task);
......
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace StackExchange.Redis.Profiling namespace StackExchange.Redis.Profiling
{ {
...@@ -23,8 +26,7 @@ namespace StackExchange.Redis.Profiling ...@@ -23,8 +26,7 @@ namespace StackExchange.Redis.Profiling
/// </summary> /// </summary>
public struct Enumerator : IEnumerator<IProfiledCommand> public struct Enumerator : IEnumerator<IProfiledCommand>
{ {
private ProfiledCommand Head; private ProfiledCommand Head, CurrentBacker;
private ProfiledCommand CurrentBacker;
private bool IsEmpty => Head == null; private bool IsEmpty => Head == null;
private bool IsUnstartedOrFinished => CurrentBacker == null; private bool IsUnstartedOrFinished => CurrentBacker == null;
...@@ -65,26 +67,59 @@ public bool MoveNext() ...@@ -65,26 +67,59 @@ public bool MoveNext()
/// <summary> /// <summary>
/// Resets the enumeration. /// Resets the enumeration.
/// </summary> /// </summary>
public void Reset() public void Reset() => CurrentBacker = null;
{
CurrentBacker = null;
}
/// <summary> /// <summary>
/// Disposes the enumeration. /// Disposes the enumeration.
/// subsequent attempts to enumerate results in undefined behavior. /// subsequent attempts to enumerate results in undefined behavior.
/// </summary> /// </summary>
public void Dispose() public void Dispose() => CurrentBacker = Head = null;
}
private readonly ProfiledCommand _head;
private readonly int _count;
/// <summary>
/// Returns the number of commands captured in this snapshot
/// </summary>
public int Count() => _count;
/// <summary>
/// Returns the captured commands as an array
/// </summary>
public IProfiledCommand[] ToArray()
{ // exploit the fact that we know the length
if (_count == 0) return Array.Empty<IProfiledCommand>();
var arr = new IProfiledCommand[_count];
var cur = _head;
for(int i = 0; i < _count; i++)
{ {
CurrentBacker = Head = null; arr[i] = cur;
cur = cur.NextElement;
} }
return arr;
} }
private readonly ProfiledCommand Head; /// <summary>
/// Returns the captured commands as a list
internal ProfiledCommandEnumerable(ProfiledCommand head) /// </summary>
public List<IProfiledCommand> ToList()
{ // exploit the fact that we know the length
var list = new List<IProfiledCommand>(_count);
var cur = _head;
while (cur != null)
{ {
Head = head; list.Add(cur);
cur = cur.NextElement;
}
return list;
}
internal ProfiledCommandEnumerable(int count, ProfiledCommand head)
{
_count = count;
_head = head;
Debug.Assert(_count == Enumerable.Count(this));
} }
/// <summary> /// <summary>
...@@ -94,7 +129,7 @@ internal ProfiledCommandEnumerable(ProfiledCommand head) ...@@ -94,7 +129,7 @@ internal ProfiledCommandEnumerable(ProfiledCommand head)
/// </para> /// </para>
/// <para>`foreach` will automatically use this method.</para> /// <para>`foreach` will automatically use this method.</para>
/// </summary> /// </summary>
public Enumerator GetEnumerator() => new Enumerator(Head); public Enumerator GetEnumerator() => new Enumerator(_head);
IEnumerator<IProfiledCommand> IEnumerable<IProfiledCommand>.GetEnumerator() => GetEnumerator(); IEnumerator<IProfiledCommand> IEnumerable<IProfiledCommand>.GetEnumerator() => GetEnumerator();
......
...@@ -33,13 +33,15 @@ internal void Add(ProfiledCommand command) ...@@ -33,13 +33,15 @@ internal void Add(ProfiledCommand command)
} }
/// <summary> /// <summary>
/// Yield the commands that were captured as part of this session, resetting the session /// Reset the session and yield the commands that were captured for enumeration; if additional commands
/// are added, they can be retrieved via additional calls to FinishProfiling
/// </summary> /// </summary>
public ProfiledCommandEnumerable GetCommands() public ProfiledCommandEnumerable FinishProfiling()
{ {
var head = (ProfiledCommand)Interlocked.Exchange(ref _untypedHead, null); var head = (ProfiledCommand)Interlocked.Exchange(ref _untypedHead, null);
// reverse the list so everything is ordered the way the consumer expected them // reverse the list so everything is ordered the way the consumer expected them
int count = 0;
ProfiledCommand previous = null, current = head, next; ProfiledCommand previous = null, current = head, next;
while(current != null) while(current != null)
{ {
...@@ -47,9 +49,10 @@ public ProfiledCommandEnumerable GetCommands() ...@@ -47,9 +49,10 @@ public ProfiledCommandEnumerable GetCommands()
current.NextElement = previous; current.NextElement = previous;
previous = current; previous = current;
current = next; current = next;
count++;
} }
return new ProfiledCommandEnumerable(previous); return new ProfiledCommandEnumerable(count, previous);
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment