StackExchange.Redis
Perfilado
Buscar..
Observaciones
Las características de creación de perfiles de StackExchange.Redis están compuestas por la interfaz IProfiler
y ConnectionMultiplexer.RegisterProfiler(IProfiler)
, ConnectionMultiplexer.BeginProfiling(object)
, ConnectionMultiplexer.FinishProfiling(object)
.
Comenzar y finalizar el perfilado toma un object
contexto para que los comandos relacionados puedan agruparse.
Esta agrupación funciona mediante la consulta de su interfaz de IProfiler
para un objeto de contexto al inicio de un comando, antes de que ocurra cualquier chanchullo de subprocesos, y asociando ese comando con cualquier otro comando que tenga el mismo objeto de contexto. Se debe llamar a Begin con el mismo objeto de contexto, por lo que StackExchange.Redis sabe que debe comenzar a perfilar los comandos con ese objeto de contexto, y se llama a Finish para detener el perfilado y devolver los resultados.
Agrupa todos los comandos de un conjunto de hilos juntos
class ToyProfiler : IProfiler
{
public ConcurrentDictionary<Thread, object> Contexts = new ConcurrentDictionary<Thread, object>();
public object GetContext()
{
object ctx;
if(!Contexts.TryGetValue(Thread.CurrentThread, out ctx)) ctx = null;
return ctx;
}
}
// ...
ConnectionMultiplexer conn = /* initialization */;
var profiler = new ToyProfiler();
var thisGroupContext = new object();
conn.RegisterProfiler(profiler);
var threads = new List<Thread>();
for (var i = 0; i < 16; i++)
{
var db = conn.GetDatabase(i);
var thread =
new Thread(
delegate()
{
var threadTasks = new List<Task>();
for (var j = 0; j < 1000; j++)
{
var task = db.StringSetAsync("" + j, "" + j);
threadTasks.Add(task);
}
Task.WaitAll(threadTasks.ToArray());
}
);
profiler.Contexts[thread] = thisGroupContext;
threads.Add(thread);
}
conn.BeginProfiling(thisGroupContext);
threads.ForEach(thread => thread.Start());
threads.ForEach(thread => thread.Join());
IEnumerable<IProfiledCommand> timings = conn.FinishProfiling(thisGroupContext);
Al final, los tiempos contendrán 16,000 objetos IProfiledCommand, uno para cada comando emitido para redisponer.
Agrupar comandos basados en hilo de emisión
ConnectionMultiplexer conn = /* initialization */;
var profiler = new ToyProfiler();
conn.RegisterProfiler(profiler);
var threads = new List<Thread>();
var perThreadTimings = new ConcurrentDictionary<Thread, List<IProfiledCommand>>();
for (var i = 0; i < 16; i++)
{
var db = conn.GetDatabase(i);
var thread =
new Thread(
delegate()
{
var threadTasks = new List<Task>();
conn.BeginProfiling(Thread.CurrentThread);
for (var j = 0; j < 1000; j++)
{
var task = db.StringSetAsync("" + j, "" + j);
threadTasks.Add(task);
}
Task.WaitAll(threadTasks.ToArray());
perThreadTimings[Thread.CurrentThread] = conn.FinishProfiling(Thread.CurrentThread).ToList();
}
);
profiler.Contexts[thread] = thread;
threads.Add(thread);
}
threads.ForEach(thread => thread.Start());
threads.ForEach(thread => thread.Join());
perThreadTimings
termina con 16 entradas de 1,000 IProfilingCommands, codificadas por el hilo que las emitió.