/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// From the kernel rapl_scale() function: // // > users must then scale back: count * 1/(1e9*2^32) to get Joules #define PERF_EVENT_SCALE_NANOJOULES 2.3283064365386962890625e-1 #define SCALE_NANOJOULES_TO_PICOWATTHOUR 3.6 #define SYSFS_PERF_POWER_TYPE_PATH "/sys/bus/event_source/devices/power/type"
constexpr RaplDomain kSupportedRaplDomains[] = {
{RaplEventType::RAPL_ENERGY_CORES, "Power: CPU cores", "Consumption of all physical cores"},
{
RaplEventType::RAPL_ENERGY_PKG, "Power: CPU package", "Consumption of the whole processor package",
},
{
RaplEventType::RAPL_ENERGY_DRAM, "Power: DRAM", "Consumption of the dram domain",
},
{
RaplEventType::RAPL_ENERGY_GPU, "Power: iGPU", "Consumption of the builtin-gpu domain",
},
{
RaplEventType::RAPL_ENERGY_PSYS, "Power: System", "Consumption of the builtin-psys domain",
}};
static std::string GetSysfsFileID(RaplEventType aEventType) { switch (aEventType) { case RaplEventType::RAPL_ENERGY_CORES: return"cores"; case RaplEventType::RAPL_ENERGY_PKG: return"pkg"; case RaplEventType::RAPL_ENERGY_DRAM: return"ram"; case RaplEventType::RAPL_ENERGY_GPU: return"gpu"; case RaplEventType::RAPL_ENERGY_PSYS: return"psys";
}
if (sysfsFile >> std::hex >> config) {
RAPL_LOG("Read config from %s: 0x%" PRIx64, sysfsFileName.c_str(), config); return config;
}
returnstatic_cast<uint64_t>(aEventType);
}
class RaplProfilerCount final : public BaseProfilerCount { public: explicit RaplProfilerCount(int aPerfEventType, const RaplEventType& aPerfEventConfig, constchar* aLabel, constchar* aDescription)
: BaseProfilerCount(aLabel, "power", aDescription),
mLastResult(0),
mPerfEventFd(-1) {
RAPL_LOG("Creating RAPL Event for type: %s", mLabel);
// Optimize for ease of use and do not set an excludes value. This // ensures we do not require PERF_PMU_CAP_NO_EXCLUDE. struct perf_event_attr attr = {0};
memset(&attr, 0, sizeof(attr));
attr.type = aPerfEventType;
attr.size = sizeof(struct perf_event_attr);
attr.config = GetRaplPerfEventConfig(aPerfEventConfig);
attr.sample_period = 0;
attr.sample_type = PERF_SAMPLE_IDENTIFIER;
attr.inherit = 1;
RAPL_LOG("Config for event %s: 0x%llx", mLabel, attr.config);
mEventScale = GetRaplPerfEventScale(aPerfEventConfig);
RAPL_LOG("Scale for event %s: %.22e", mLabel, mEventScale);
long fd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, 0); if (fd < 0) {
RAPL_LOG("Event descriptor creation failed for event: %s", mLabel);
mPerfEventFd = -1; return;
}
RAPL_LOG("Created descriptor for event: %s", mLabel)
mPerfEventFd = static_cast<int>(fd);
}
if (raplEventResult.isNothing()) { return result;
}
// We need to return picowatthour to be consistent with the Windows // EMI API. As a result, the scale calculation should: // // - Convert the returned value to nanojoules // - Convert nanojoules to picowatthour double nanojoules = static_cast<double>(raplEventResult.value()) * mEventScale; double picowatthours = nanojoules / SCALE_NANOJOULES_TO_PICOWATTHOUR;
RAPL_LOG("Sample %s { count: %lu, last-result: %lu } = %lfJ", mLabel,
raplEventResult.value(), mLastResult, nanojoules * 1e-9);
// If the tick count is the same as the returned value or if this is the // first sample, treat this sample as a duplicate.
result.isSampleNew =
(mLastResult != 0 && mLastResult != raplEventResult.value() &&
result.count >= 0);
mLastResult = raplEventResult.value();
uint64_t mLastResult; int mPerfEventFd; double mEventScale;
};
staticint GetRaplPerfEventType() {
FILE* fp = fopen(SYSFS_PERF_POWER_TYPE_PATH, "r"); if (!fp) {
RAPL_LOG("Open of " SYSFS_PERF_POWER_TYPE_PATH " failed"); return -1;
}
int readTypeValue = -1; if (fscanf(fp, "%d", &readTypeValue) != 1) {
RAPL_LOG("Read of " SYSFS_PERF_POWER_TYPE_PATH " failed");
}
fclose(fp);
return readTypeValue;
}
PowerCounters::PowerCounters() { if (!XRE_IsParentProcess()) { // Energy meters are global, so only sample them on the parent. return;
}
// Get the value perf_event_attr.type should be set to for RAPL // perf events. int perfEventType = GetRaplPerfEventType(); if (perfEventType < 0) {
RAPL_LOG("Failed to find the event type for RAPL perf events."); return;
}
for (constauto& raplEventDomain : kSupportedRaplDomains) {
RaplProfilerCount* raplEvent = new RaplProfilerCount(
perfEventType, raplEventDomain.mRaplEventType, raplEventDomain.mLabel,
raplEventDomain.mDescription); if (!raplEvent->ValidPerfEventFd() || !mCounters.emplaceBack(raplEvent)) { delete raplEvent;
}
}
}
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.