зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1743176 - Collect the GPU time used in the parent process through Glean, r=chutten,jrmuizel.
Differential Revision: https://phabricator.services.mozilla.com/D132265
This commit is contained in:
Родитель
464abfcf25
Коммит
15f070e21c
|
@ -19,8 +19,9 @@ typedef struct _D3DKMTQS_COUNTER {
|
|||
|
||||
typedef struct _D3DKMTQS_ADAPTER_INFO {
|
||||
ULONG NbSegments;
|
||||
ULONG NodeCount;
|
||||
|
||||
ULONG Filler[4];
|
||||
ULONG Filler[3];
|
||||
ULONGLONG Filler2[2]; // Assumed sizeof(LONGLONG) = sizeof(ULONGLONG)
|
||||
struct {
|
||||
ULONG Filler[14];
|
||||
|
@ -121,11 +122,20 @@ typedef struct _D3DKMTQS_PROCESS_SEGMENT_INFO {
|
|||
ULONG64 Reserved[8];
|
||||
} D3DKMTQS_PROCESS_SEGMENT_INFO;
|
||||
|
||||
typedef struct _D3DKMTQS_PROCESS_NODE_INFO {
|
||||
LARGE_INTEGER RunningTime; // 100ns
|
||||
ULONG ContextSwitch;
|
||||
ULONG PreemptionStatistics[16];
|
||||
ULONG PacketStatistics[32];
|
||||
ULONG64 Reserved[8];
|
||||
} D3DKMTQS_PROCESS_NODE_INFO;
|
||||
|
||||
typedef enum _D3DKMTQS_TYPE {
|
||||
D3DKMTQS_ADAPTER = 0,
|
||||
D3DKMTQS_PROCESS = 1,
|
||||
D3DKMTQS_SEGMENT = 3,
|
||||
D3DKMTQS_PROCESS_SEGMENT = 4,
|
||||
D3DKMTQS_PROCESS_NODE = 6,
|
||||
} D3DKMTQS_TYPE;
|
||||
|
||||
typedef union _D3DKMTQS_RESULT {
|
||||
|
@ -134,12 +144,17 @@ typedef union _D3DKMTQS_RESULT {
|
|||
D3DKMTQS_SEGMENT_INFO_WIN8 SegmentInfoWin8;
|
||||
D3DKMTQS_PROCESS_INFO ProcessInfo;
|
||||
D3DKMTQS_PROCESS_SEGMENT_INFO ProcessSegmentInfo;
|
||||
D3DKMTQS_PROCESS_NODE_INFO ProcessNodeInformation;
|
||||
} D3DKMTQS_RESULT;
|
||||
|
||||
typedef struct _D3DKMTQS_QUERY_SEGMENT {
|
||||
ULONG SegmentId;
|
||||
} D3DKMTQS_QUERY_SEGMENT;
|
||||
|
||||
typedef struct _D3DKMTQS_QUERY_NODE {
|
||||
ULONG NodeId;
|
||||
} D3DKMTQS_QUERY_NODE;
|
||||
|
||||
typedef struct _D3DKMTQS {
|
||||
D3DKMTQS_TYPE Type;
|
||||
LUID AdapterLuid;
|
||||
|
@ -149,6 +164,7 @@ typedef struct _D3DKMTQS {
|
|||
union {
|
||||
D3DKMTQS_QUERY_SEGMENT QuerySegment;
|
||||
D3DKMTQS_QUERY_SEGMENT QueryProcessSegment;
|
||||
D3DKMTQS_QUERY_NODE QueryProcessNode;
|
||||
};
|
||||
} D3DKMTQS;
|
||||
|
||||
|
|
|
@ -313,6 +313,69 @@ void gfxWindowsPlatform::InitMemoryReportersForGPUProcess() {
|
|||
RegisterStrongMemoryReporter(new D3DSharedTexturesReporter());
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult gfxWindowsPlatform::GetGpuTimeSinceProcessStartInMs(
|
||||
uint64_t* aResult) {
|
||||
RefPtr<ID3D11Device> d3d11Device;
|
||||
if (!(d3d11Device = mozilla::gfx::Factory::GetDirect3D11Device())) {
|
||||
// If we don't have a D3DDevice, we likely didn't use any GPU time.
|
||||
*aResult = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsModuleHandle module(LoadLibrary(L"gdi32.dll"));
|
||||
if (!module) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
PFND3DKMTQS queryD3DKMTStatistics =
|
||||
(PFND3DKMTQS)GetProcAddress(module, "D3DKMTQueryStatistics");
|
||||
if (!queryD3DKMTStatistics) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIDevice> dxgiDevice;
|
||||
if (d3d11Device->QueryInterface(__uuidof(IDXGIDevice),
|
||||
getter_AddRefs(dxgiDevice)) != S_OK) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
IDXGIAdapter* DXGIAdapter;
|
||||
if (dxgiDevice->GetAdapter(&DXGIAdapter) != S_OK) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
DXGI_ADAPTER_DESC adapterDesc;
|
||||
DXGIAdapter->GetDesc(&adapterDesc);
|
||||
DXGIAdapter->Release();
|
||||
|
||||
D3DKMTQS queryStatistics;
|
||||
memset(&queryStatistics, 0, sizeof(D3DKMTQS));
|
||||
queryStatistics.Type = D3DKMTQS_ADAPTER;
|
||||
queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
|
||||
if (!NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint64_t result = 0;
|
||||
ULONG nodeCount = queryStatistics.QueryResult.AdapterInfo.NodeCount;
|
||||
for (ULONG i = 0; i < nodeCount; ++i) {
|
||||
memset(&queryStatistics, 0, sizeof(D3DKMTQS));
|
||||
queryStatistics.Type = D3DKMTQS_PROCESS_NODE;
|
||||
queryStatistics.AdapterLuid = adapterDesc.AdapterLuid;
|
||||
queryStatistics.hProcess = GetCurrentProcess();
|
||||
queryStatistics.QueryProcessNode.NodeId = i;
|
||||
if (NT_SUCCESS(queryD3DKMTStatistics(&queryStatistics))) {
|
||||
result += queryStatistics.QueryResult.ProcessNodeInformation.RunningTime
|
||||
.QuadPart *
|
||||
100 / PR_NSEC_PER_MSEC;
|
||||
}
|
||||
}
|
||||
|
||||
*aResult = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void UpdateANGLEConfig() {
|
||||
if (!gfxConfig::IsEnabled(Feature::D3D11_COMPOSITING)) {
|
||||
gfxConfig::Disable(Feature::D3D11_HW_ANGLE, FeatureStatus::Disabled,
|
||||
|
|
|
@ -6,12 +6,6 @@
|
|||
#ifndef GFX_WINDOWS_PLATFORM_H
|
||||
#define GFX_WINDOWS_PLATFORM_H
|
||||
|
||||
/**
|
||||
* XXX to get CAIRO_HAS_DWRITE_FONT
|
||||
* and cairo_win32_scaled_font_select_font
|
||||
*/
|
||||
#include "cairo-win32.h"
|
||||
|
||||
#include "gfxCrashReporterUtils.h"
|
||||
#include "gfxFontUtils.h"
|
||||
#include "gfxWindowsSurface.h"
|
||||
|
@ -177,6 +171,8 @@ class gfxWindowsPlatform final : public gfxPlatform {
|
|||
}
|
||||
|
||||
public:
|
||||
static nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult);
|
||||
|
||||
bool DwmCompositionEnabled();
|
||||
|
||||
mozilla::layers::ReadbackManagerD3D11* GetReadbackManager();
|
||||
|
|
|
@ -21,8 +21,8 @@ using FlushFOGDataPromise = mozilla::dom::ContentParent::FlushFOGDataPromise;
|
|||
namespace mozilla {
|
||||
namespace glean {
|
||||
|
||||
static void RecordCpuTime() {
|
||||
static uint64_t previousCpuTime = 0;
|
||||
static void RecordPowerMetrics() {
|
||||
static uint64_t previousCpuTime = 0, previousGpuTime = 0;
|
||||
|
||||
uint64_t cpuTime;
|
||||
if (NS_FAILED(GetCpuTimeSinceProcessStartInMs(&cpuTime))) {
|
||||
|
@ -38,6 +38,16 @@ static void RecordCpuTime() {
|
|||
// This should be fine for now, but may overflow in the future.
|
||||
power::total_cpu_time_ms.Add(int32_t(newCpuTime));
|
||||
}
|
||||
|
||||
uint64_t gpuTime;
|
||||
if (NS_SUCCEEDED(GetGpuTimeSinceProcessStartInMs(&gpuTime))) {
|
||||
uint64_t newGpuTime = gpuTime - previousGpuTime;
|
||||
previousGpuTime += newGpuTime;
|
||||
|
||||
if (newGpuTime) {
|
||||
power::total_gpu_time_ms.Add(int32_t(newGpuTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -48,8 +58,8 @@ static void RecordCpuTime() {
|
|||
* serialized payload that the Rust impl hands you.
|
||||
*/
|
||||
void FlushFOGData(std::function<void(ipc::ByteBuf&&)>&& aResolver) {
|
||||
// Record the CPU time right before data is sent to the parent.
|
||||
RecordCpuTime();
|
||||
// Record power metrics right before data is sent to the parent.
|
||||
RecordPowerMetrics();
|
||||
|
||||
ByteBuf buf;
|
||||
uint32_t ipcBufferSize = impl::fog_serialize_ipc_buf();
|
||||
|
@ -130,8 +140,9 @@ void SendFOGData(ipc::ByteBuf&& buf) {
|
|||
* sending it all down into Rust to be used.
|
||||
*/
|
||||
RefPtr<GenericPromise> FlushAndUseFOGData() {
|
||||
// Record CPU time on the parent before sending requests to child processes.
|
||||
RecordCpuTime();
|
||||
// Record power metrics on the parent before sending requests to child
|
||||
// processes.
|
||||
RecordPowerMetrics();
|
||||
|
||||
RefPtr<GenericPromise::Private> ret = new GenericPromise::Private(__func__);
|
||||
std::function<void(nsTArray<ByteBuf> &&)> resolver =
|
||||
|
|
|
@ -27,6 +27,13 @@ class GeckoChildProcessHost;
|
|||
*/
|
||||
nsresult GetCpuTimeSinceProcessStartInMs(uint64_t* aResult);
|
||||
|
||||
/**
|
||||
* Return the number of milliseconds of GPU time used since process start.
|
||||
*
|
||||
* @return NS_OK on success.
|
||||
*/
|
||||
nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult);
|
||||
|
||||
// Process types. When updating this enum, please make sure to update
|
||||
// WebIDLProcType, ChromeUtils::RequestProcInfo and ProcTypeToWebIDL to
|
||||
// mirror the changes.
|
||||
|
|
|
@ -31,6 +31,19 @@ nsresult GetCpuTimeSinceProcessStartInMs(uint64_t* aResult) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult) {
|
||||
task_power_info_v2_data_t task_power_info;
|
||||
mach_msg_type_number_t count = TASK_POWER_INFO_V2_COUNT;
|
||||
kern_return_t kr =
|
||||
task_info(mach_task_self(), TASK_POWER_INFO_V2, (task_info_t)&task_power_info, &count);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
*aResult = task_power_info.gpu_energy.task_gpu_utilisation / PR_NSEC_PER_MSEC;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests) {
|
||||
auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
|
||||
RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
|
||||
|
|
|
@ -196,6 +196,10 @@ nsresult GetCpuTimeSinceProcessStartInMs(uint64_t* aResult) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests) {
|
||||
auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
|
||||
RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "mozilla/ProcInfo.h"
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/SSE.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "nsMemoryReporterManager.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
|
@ -85,6 +86,10 @@ nsresult GetCpuTimeSinceProcessStartInMs(uint64_t* aResult) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetGpuTimeSinceProcessStartInMs(uint64_t* aResult) {
|
||||
return gfxWindowsPlatform::GetGpuTimeSinceProcessStartInMs(aResult);
|
||||
}
|
||||
|
||||
RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests) {
|
||||
auto holder = MakeUnique<MozPromiseHolder<ProcInfoPromise>>();
|
||||
RefPtr<ProcInfoPromise> promise = holder->Ensure(__func__);
|
||||
|
|
|
@ -26,3 +26,19 @@ power:
|
|||
notification_emails:
|
||||
- florian@mozilla.com
|
||||
expires: never
|
||||
|
||||
total_gpu_time_ms:
|
||||
type: counter
|
||||
description: >
|
||||
Total GPU time used by all processes in ms.
|
||||
bugs:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1743176
|
||||
data_reviews:
|
||||
- https://bugzilla.mozilla.org/show_bug.cgi?id=1743176
|
||||
data_sensitivity:
|
||||
- technical
|
||||
notification_emails:
|
||||
- florian@mozilla.com
|
||||
expires: never
|
||||
no_lint:
|
||||
- COMMON_PREFIX
|
||||
|
|
Загрузка…
Ссылка в новой задаче