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()
var val = db.StringGet(key);
Assert.Equal("world", val);
var msgs = profiler.GetCommands();
var msgs = profiler.FinishProfiling();
Log("Checking GET...");
Assert.Contains(msgs, m => m.Command == "GET");
Log("Checking SET...");
......
......@@ -35,7 +35,7 @@ public void Simple()
var s = (string)db.Execute("ECHO", "fii");
Assert.Equal("fii", s);
var cmds = session.GetCommands();
var cmds = session.FinishProfiling();
var i = 0;
foreach (var cmd in cmds)
{
......@@ -121,7 +121,7 @@ public void ManyThreads()
threads.ForEach(thread => thread.Start());
threads.ForEach(thread => thread.Join());
var allVals = session.GetCommands();
var allVals = session.FinishProfiling();
var relevant = allVals.Where(cmd => cmd.Db > 0).ToList();
var kinds = relevant.Select(cmd => cmd.Command).Distinct().ToList();
......@@ -178,7 +178,7 @@ public void ManyContexts()
Task.WaitAll(allTasks.ToArray());
results[ix] = profiler.GetSession().GetCommands();
results[ix] = profiler.GetSession().FinishProfiling();
});
threads.Add(thread);
......@@ -252,7 +252,7 @@ public void LowAllocationEnumerable()
conn.WaitAll(allTasks.ToArray());
var res = session.GetCommands();
var res = session.FinishProfiling();
Assert.True(res.GetType().IsValueType);
using (var e = res.GetEnumerator())
......@@ -312,7 +312,7 @@ public void ProfilingMD_Ex1()
threads.ForEach(thread => thread.Start());
threads.ForEach(thread => thread.Join());
IEnumerable<IProfiledCommand> timings = session.GetCommands();
IEnumerable<IProfiledCommand> timings = session.FinishProfiling();
Assert.Equal(16000, timings.Count());
}
......@@ -349,7 +349,7 @@ public void ProfilingMD_Ex2()
Task.WaitAll(threadTasks.ToArray());
perThreadTimings[Thread.CurrentThread] = profiler.GetSession().GetCommands().ToList();
perThreadTimings[Thread.CurrentThread] = profiler.GetSession().FinishProfiling().ToList();
});
threads.Add(thread);
......@@ -388,7 +388,7 @@ public async Task ProfilingMD_Ex2_Async()
await db.StringSetAsync(prefix + j, "" + j);
}
perThreadTimings.Add(profiler.GetSession().GetCommands().ToList());
perThreadTimings.Add(profiler.GetSession().FinishProfiling().ToList());
});
tasks.Add(task);
......
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace StackExchange.Redis.Profiling
{
......@@ -23,8 +26,7 @@ namespace StackExchange.Redis.Profiling
/// </summary>
public struct Enumerator : IEnumerator<IProfiledCommand>
{
private ProfiledCommand Head;
private ProfiledCommand CurrentBacker;
private ProfiledCommand Head, CurrentBacker;
private bool IsEmpty => Head == null;
private bool IsUnstartedOrFinished => CurrentBacker == null;
......@@ -65,26 +67,59 @@ public bool MoveNext()
/// <summary>
/// Resets the enumeration.
/// </summary>
public void Reset()
{
CurrentBacker = null;
}
public void Reset() => CurrentBacker = null;
/// <summary>
/// Disposes the enumeration.
/// subsequent attempts to enumerate results in undefined behavior.
/// </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;
internal ProfiledCommandEnumerable(ProfiledCommand head)
/// <summary>
/// Returns the captured commands as a list
/// </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)
{
list.Add(cur);
cur = cur.NextElement;
}
return list;
}
internal ProfiledCommandEnumerable(int count, ProfiledCommand head)
{
Head = head;
_count = count;
_head = head;
Debug.Assert(_count == Enumerable.Count(this));
}
/// <summary>
......@@ -94,7 +129,7 @@ internal ProfiledCommandEnumerable(ProfiledCommand head)
/// </para>
/// <para>`foreach` will automatically use this method.</para>
/// </summary>
public Enumerator GetEnumerator() => new Enumerator(Head);
public Enumerator GetEnumerator() => new Enumerator(_head);
IEnumerator<IProfiledCommand> IEnumerable<IProfiledCommand>.GetEnumerator() => GetEnumerator();
......
......@@ -33,13 +33,15 @@ internal void Add(ProfiledCommand command)
}
/// <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>
public ProfiledCommandEnumerable GetCommands()
public ProfiledCommandEnumerable FinishProfiling()
{
var head = (ProfiledCommand)Interlocked.Exchange(ref _untypedHead, null);
// reverse the list so everything is ordered the way the consumer expected them
int count = 0;
ProfiledCommand previous = null, current = head, next;
while(current != null)
{
......@@ -47,9 +49,10 @@ public ProfiledCommandEnumerable GetCommands()
current.NextElement = previous;
previous = current;
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