Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Por padrão, o TraceProcessor acessa os dados carregando-os na memória à medida que o rastreamento é processado. Essa abordagem de buffer é fácil de usar, mas pode ser cara em termos de uso de memória.
O TraceProcessor também fornece a função trace.UseStreaming(), que dá suporte ao acesso a vários tipos de dados de rastreamento de forma streaming (processando dados conforme são lidos do arquivo de rastreamento, em vez de armazená-los em memória bufferizada). Por exemplo, um rastreamento de chamadas de sistema pode ser bastante grande, e bufferizar toda a lista dessas chamadas em um rastreamento pode ser bastante caro.
Acessando dados em buffer
O código a seguir mostra o acesso aos dados de syscall de forma normal e em modo buffer por meio da função trace.UseSyscalls():
using Microsoft.Windows.EventTracing;
using Microsoft.Windows.EventTracing.Processes;
using Microsoft.Windows.EventTracing.Syscalls;
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.Error.WriteLine("Usage: <trace.etl>");
return;
}
using (ITraceProcessor trace = TraceProcessor.Create(args[0]))
{
IPendingResult<ISyscallDataSource> pendingSyscallData = trace.UseSyscalls();
trace.Process();
ISyscallDataSource syscallData = pendingSyscallData.Result;
Dictionary<IProcess, int> syscallsPerCommandLine = new Dictionary<IProcess, int>();
foreach (ISyscall syscall in syscallData.Syscalls)
{
IProcess process = syscall.Thread?.Process;
if (process == null)
{
continue;
}
if (!syscallsPerCommandLine.ContainsKey(process))
{
syscallsPerCommandLine.Add(process, 0);
}
++syscallsPerCommandLine[process];
}
Console.WriteLine("Process Command Line: Syscalls Count");
foreach (IProcess process in syscallsPerCommandLine.Keys)
{
Console.WriteLine($"{process.CommandLine}: {syscallsPerCommandLine[process]}");
}
}
}
}
Acessando dados de streaming
Com um rastreamento de syscalls grande, a tentativa de armazenar em buffer os dados de syscall na memória pode ser muito custosa ou pode até não ser viável. O código a seguir mostra como acessar os mesmos dados de syscall de forma contínua, substituindo trace.UseSyscalls() por trace.UseStreaming().UseSyscalls():
using Microsoft.Windows.EventTracing;
using Microsoft.Windows.EventTracing.Processes;
using Microsoft.Windows.EventTracing.Syscalls;
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
if (args.Length != 1)
{
Console.Error.WriteLine("Usage: <trace.etl>");
return;
}
using (ITraceProcessor trace = TraceProcessor.Create(args[0]))
{
IPendingResult<IThreadDataSource> pendingThreadData = trace.UseThreads();
Dictionary<IProcess, int> syscallsPerCommandLine = new Dictionary<IProcess, int>();
trace.UseStreaming().UseSyscalls(ConsumerSchedule.SecondPass, context =>
{
Syscall syscall = context.Data;
IProcess process = syscall.GetThread(pendingThreadData.Result)?.Process;
if (process == null)
{
return;
}
if (!syscallsPerCommandLine.ContainsKey(process))
{
syscallsPerCommandLine.Add(process, 0);
}
++syscallsPerCommandLine[process];
});
trace.Process();
Console.WriteLine("Process Command Line: Syscalls Count");
foreach (IProcess process in syscallsPerCommandLine.Keys)
{
Console.WriteLine($"{process.CommandLine}: {syscallsPerCommandLine[process]}");
}
}
}
}
Como o streaming funciona
Por padrão, todos os dados de streaming são fornecidos durante a primeira passagem pelo rastreamento e os dados armazenados em buffer de outras fontes não estão disponíveis. O exemplo acima mostra como combinar streaming com buffer – os dados de thread são armazenados em buffer antes que os dados de syscall sejam transmitidos. Como resultado, o rastreamento deve ser lido duas vezes – uma vez para obter dados de thread em buffer e uma segunda vez para acessar dados de syscall de streaming com os dados de thread em buffer agora disponíveis. Para combinar streaming e bufferização dessa maneira, o exemplo passa ConsumerSchedule.SecondPass para trace.UseStreaming().UseSyscalls(), o que faz com que o processamento de syscall aconteça em uma segunda passagem pelo trace. Ao ser executado em uma segunda passagem, o callback de syscall pode acessar o resultado pendente da função trace.UseThreads() ao processar cada chamada de syscall. Sem esse argumento opcional, o streaming de syscall teria sido executado na primeira passagem pelo rastreamento (havendo apenas uma única passagem), e o resultado pendente de trace.UseThreads() ainda não estaria disponível. Nesse caso, o retorno de chamada ainda teria acesso ao ThreadId a partir do syscall, mas não teria acesso ao processo para o thread (porque o thread para processar dados de vinculação é fornecido por meio de outros eventos que podem ainda não ter sido processados).
Algumas diferenças importantes no uso entre buffer e streaming:
- O buffer retorna um IPendingResult<T>e o resultado que ele mantém está disponível somente antes que o rastreamento seja processado. Depois que o rastreamento for processado, os resultados poderão ser enumerados usando técnicas como foreach e LINQ.
- O streaming não retorna nada e, em vez disso, usa um argumento de retorno de chamada. Ele chama a função de retorno cada vez que cada item se torna disponível. Como os dados não são armazenados em buffer, nunca há uma lista de resultados a serem enumerados com foreach ou LINQ – o retorno de chamada de streaming precisa armazenar em buffer qualquer parte dos dados que deseja salvar para uso após a conclusão do processamento.
- O código para o processamento de dados em buffer aparece após a chamada da função trace.Process(), quando os resultados pendentes estão disponíveis.
- O código para o processamento de dados de streaming aparece antes da chamada para trace.Process(), como um callback para o método trace.UseStreaming.Use...().
- Um consumidor de streaming pode decidir processar apenas parte do fluxo e cancelar retornos de chamada futuros chamando context.Cancel(). Um consumidor de buffer sempre recebe uma lista em buffer completa.
Dados de streaming correlacionados
Às vezes, os dados de rastreamento vêm em uma sequência de eventos – por exemplo, as chamadas são registradas por meio de eventos de entrada e saída separados, mas os dados combinados de ambos os eventos podem ser mais úteis. O método trace.UseStreaming().UseSyscalls() correlaciona os dados de ambos os eventos e os oferece conforme o par fica disponível. Alguns tipos de dados correlacionados estão disponíveis por meio de trace.UseStreaming():
| Código | Descrição |
|---|---|
| traço. UseStreaming(). UseContextSwitchData() | Transmite dados de troca de contexto correlacionados (de eventos compactos e não compactos, com SwitchInThreadIds mais precisos do que os de eventos não compactos brutos). |
| traço. UseStreaming(). UseScheduledTasks() | Transmite dados correlacionados de tarefas agendadas. |
| traço. UseStreaming(). UseSyscalls() | Transmite dados de chamada do sistema correlacionados. |
| traço. UseStreaming(). UseWindowInFocus() | Transmite dados de janela em foco correlacionados. |
Eventos de streaming autônomos
Além disso, trace.UseStreaming() fornece eventos analisados para vários tipos diferentes de eventos autônomos:
| Código | Descrição |
|---|---|
| traço. UseStreaming(). UseLastBranchRecordEvents() | Transmite eventos de LBR (último registro de branch) analisados. |
| traço. UseStreaming(). UseReadyThreadEvents() | Transmite eventos de threads prontos e analisados. |
| traço. UseStreaming(). UseThreadCreateEvents() | Fluxos de eventos de criação de thread analisados. |
| traço. UseStreaming(). UseThreadExitEvents() | Transmite eventos de saída de thread analisados. |
| Trace. UseStreaming(). UseThreadRundownStartEvents() | Transmite eventos de início de rundown de thread analisados. |
| traço. UseStreaming(). UseThreadRundownStopEvents() | Transmite eventos de parada de rundown de thread analisados. |
| traço. UseStreaming(). UseThreadSetNameEvents() | Transmite eventos de nome do conjunto de threads analisados. |
Eventos de streaming subjacentes para dados correlacionados
Por fim, a funcionalidade trace.UseStreaming() também disponibiliza os eventos subjacentes usados para correlacionar os dados na lista acima. Esses eventos subjacentes são:
| Código | Descrição | Incluído em |
|---|---|---|
| traço. UseStreaming(). UseCompactContextSwitchEvents() | Fluxos analisados de eventos compactos de troca de contexto. | traço. UseStreaming(). UseContextSwitchData() |
| traço. UseStreaming(). UseContextSwitchEvents() | Transmite eventos de comutação de contexto analisados. SwitchInThreadIds pode não ser preciso em alguns casos. | traço. UseStreaming(). UseContextSwitchData() |
| traço. UseStreaming(). UseFocusChangeEvents() | Transmite eventos analisados de alteração de foco de janela. | traço. UseStreaming(). UseWindowInFocus() |
| traço. UseStreaming(). UseScheduledTaskStartEvents() | Transmite eventos de início da tarefa agendada analisados. | traço. UseStreaming(). UseScheduledTasks() |
| traço. UseStreaming(). UseScheduledTaskStopEvents() | Transmite eventos de parada de tarefa agendada analisados. | traço. UseStreaming(). UseScheduledTasks() |
| traço. UseStreaming(). UseScheduledTaskTriggerEvents() | Transmite eventos de gatilho de tarefa agendada analisados. | traço. UseStreaming(). UseScheduledTasks() |
| traço. UseStreaming(). UseSessionLayerSetActiveWindowEvents() | Fluxos analisados definem eventos de janela ativa na camada de sessão. | traço. UseStreaming(). UseWindowInFocus() |
| traço. UseStreaming(). UseSyscallEnterEvents() | Fluxos analisados de eventos de entrada de chamadas de sistema. | traço. UseStreaming(). UseSyscalls() |
| traço. UseStreaming(). UseSyscallExitEvents() | Transmite eventos de saída de syscall analisados. | traço. UseStreaming(). UseSyscalls() |
Próximas etapas
Neste tutorial, você aprendeu a usar o streaming para acessar dados de rastreamento imediatamente e usando menos memória.
A próxima etapa é procurar acessar os dados desejados em seus rastreamentos. Veja os exemplos para algumas ideias. Observe que nem todos os rastreamentos incluem todos os tipos de dados com suporte.
Windows developer