事件查看器

在性能探查器中,可以在应用仍在运行时收集诊断信息,然后在应用停止后检查收集的信息(如事后分析)。

通用事件查看器通过一系列事件(如模块加载、线程启动和系统配置)显示应用活动。 此视图有助于在 Visual Studio 探查器中更好地诊断应用的运行情况。

安装

  1. 在 Visual Studio 中,按 Alt+F2 打开性能探查器。

  2. 选中“事件查看器”复选框。

    已选中“事件查看器”复选框

  3. 选择“开始”按钮,以运行此工具。

  4. 在此工具开始运行后,在应用中完成要探查的方案。 然后,选择“停止收集”或关闭应用,以查看数据。

    显示“停止收集”的窗口

若要详细了解如何提高此工具的效率,请参阅优化分析设置

了解数据

事件查看器跟踪

列名称 描述
提供商名称 事件源
事件名称 由其提供程序指定的事件
Text 事件的提供程序、事件名称和 ID 的说明
时间戳(毫秒) 事件发生的时间
提供程序 GUID 事件提供程序的 ID
事件 ID 事件的 ID
进程 ID 发生事件所在的进程(如果已知)
进程名 当前正在运行的进程的名称
线程 ID 发生事件所在的线程的 ID(如果已知)

如果默认情况下缺少任何列,请右键单击现有列标题之一,然后选择要添加的列。

向事件查看器添加列

选择事件后,就会看到“其他属性”窗口。 “通用属性”列出了将会为所有事件显示的属性。 “有效负载属性”显示了特定于事件的属性。 对于某些事件,还可以查看“堆栈”。

显示堆栈的事件查看器

整理数据

除了“文本”列以外的其他所有列都是可排序的。

事件查看器跟踪

事件查看器一次最多可显示 20,000 个事件。 若要专注于相关事件,可以通过选择事件筛选器来筛选显示的事件。 还可以查看每个提供程序发生的事件总数所占的百分比,此信息为你提供时间分配的明细。 如果将鼠标悬停在一个事件筛选器上,就能看到显示以下内容的工具提示:

  • 事件名称
  • 提供程序
  • GUID
  • 事件总数所占的百分比
  • 事件计数

事件查看器事件筛选器

提供程序筛选器显示了每个提供程序发生的事件总数所占的百分比。 如果将鼠标悬停在一个提供程序上,可以看到显示提供程序名称、事件总数所占百分比和事件计数的类似工具提示。

事件查看器提供程序筛选器

启用自定义 ETW 事件

可以使用自定义 ETW 事件检测代码,并允许它们显示在事件查看器中。 若要启用自定义事件:

  1. 生成自定义事件代码。

    本部分末尾提供了 C++ 自定义事件代码的示例。

  2. 打开性能探查器 (Alt + F2),启用事件查看器,然后选择 其旁边的“设置”图标(齿轮图标)。

    事件查看器设置图标的屏幕截图。

  3. 在对话框中,在“其他提供程序”下启用第一行,然后执行以下操作之一:

    • 对于本机自定义事件代码,请根据自定义事件代码的 GUID 设置 提供程序 GUID,并将提供程序名称值留空或使用其默认值。

    • 对于 C# 自定义事件代码,请设置声明事件代码时使用的相同提供程序名称值。 此名称在后台转换为 GUID,因此请将 提供程序 GUID 留空。

      对于本机自定义事件,该行应类似于下图。

      事件查看器设置的屏幕截图。

  4. 选择“确定”

    收集诊断跟踪并打开自定义事件时,自定义事件将显示在事件查看器中。 下图显示了事件查看器中的自定义事件,其中筛选设置为仅显示自定义事件。

    显示自定义事件的事件查看器屏幕截图。

下面是 C++ 的自定义事件代码示例。

#include <Windows.h>
#include <evntprov.h>
#include <iostream>
#include <thread>

// This GUID must be regenerated so it is unique for your provider
// {7369B7AC-64EB-4618-B6B6-C8442B12E8F2}
GUID customEventProvider = { 0x7369b7ac, 0x64eb, 0x4618, { 0xb6, 0xb6, 0xc8, 0x44, 0x2b, 0x12, 0xe8, 0xf2 } };
REGHANDLE _customEventProviderRegHandle = 0;

// Id, Version, Channel, Level, OpCode, Task, Keyword
const EVENT_DESCRIPTOR CustomEventDescriptor = { 1, 0, 0, 0, 0, 0, 1 };

int main()
{
    // Register the provider
    ULONG res = ::EventRegister(&customEventProvider, nullptr, nullptr, &_customEventProviderRegHandle);
    if (res != ERROR_SUCCESS)
    {
        return res;
    }

    byte data[] = { 0xFF, 0xFF, 0xFF, 0xFF };
    EVENT_DATA_DESCRIPTOR eventData[1];
    ::EventDataDescCreate(&(eventData[0]), &data, sizeof(data));

    for (int i = 0; i < 10; ++i)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        ::EventWrite(_customEventProviderRegHandle, &CustomEventDescriptor, _countof(eventData), eventData);
        std::cout << "Wrote event\n";
    }

    res = ::EventUnregister(_customEventProviderRegHandle);
    if (res != ERROR_SUCCESS)
    {
        return res;
    }

    return 0;
}