forked from OSchip/llvm-project
[llvm-mca] Move the logic that prints scheduler statistics from BackendStatistics to its own view.
Added flag -scheduler-stats to print scheduler related statistics. llvm-svn: 329792
This commit is contained in:
parent
d928201ac5
commit
1cc29c045e
|
@ -139,8 +139,7 @@ option specifies "``-``", then the output will also be sent to standard output.
|
|||
.. option:: -verbose
|
||||
|
||||
Enable verbose output. In particular, this flag enables a number of extra
|
||||
statistics and performance counters for the dispatch logic, the reorder
|
||||
buffer, the retire control unit and the register file.
|
||||
statistics and performance counters for the retire control unit.
|
||||
|
||||
.. option:: -timeline
|
||||
|
||||
|
@ -170,6 +169,11 @@ option specifies "``-``", then the output will also be sent to standard output.
|
|||
dispatch events, as well as static/dynamic dispatch stall events. This view
|
||||
is disabled by default.
|
||||
|
||||
.. option:: -scheduler-stats
|
||||
|
||||
Enable extra scheduler statistics. This view collects and analyzes instruction
|
||||
issue events. This view is disabled by default.
|
||||
|
||||
.. option:: -instruction-info
|
||||
|
||||
Enable the instruction info view. This is enabled by default.
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
# RUN: llvm-mca -march=aarch64 -mcpu=exynos-m3 -iterations=1 -verbose -resource-pressure=false -instruction-info=false < %s | FileCheck %s -check-prefix=ALL
|
||||
# RUN: llvm-mca -march=aarch64 -mcpu=exynos-m1 -iterations=1 -verbose -resource-pressure=false -instruction-info=false < %s | FileCheck %s -check-prefix=ALL
|
||||
# RUN: llvm-mca -march=aarch64 -mcpu=exynos-m3 -iterations=1 -scheduler-stats -resource-pressure=false -instruction-info=false < %s | FileCheck %s -check-prefix=ALL
|
||||
# RUN: llvm-mca -march=aarch64 -mcpu=exynos-m1 -iterations=1 -scheduler-stats -resource-pressure=false -instruction-info=false < %s | FileCheck %s -check-prefix=ALL
|
||||
|
||||
b t
|
||||
b t
|
||||
|
||||
# ALL: Schedulers - number of cycles where we saw N instructions issued:
|
||||
# ALL-NEXT: [# issued], [# cycles]
|
||||
# ALL-NEXT: 0, 1 (50.0%)
|
||||
# ALL-NEXT: 1, 1 (50.0%)
|
||||
|
||||
# ALL: Scheduler's queue usage:
|
||||
# ALL-NEXT: No scheduler resources used.
|
||||
|
||||
|
|
|
@ -1,8 +1,31 @@
|
|||
# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=1 -verbose < %s | FileCheck %s
|
||||
# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=1 -scheduler-stats < %s | FileCheck %s
|
||||
|
||||
vmulps (%rsi), %xmm0, %xmm0
|
||||
add %rsi, %rsi
|
||||
|
||||
# CHECK: Iterations: 1
|
||||
# CHECK-NEXT: Instructions: 2
|
||||
# CHECK-NEXT: Total Cycles: 10
|
||||
# CHECK-NEXT: Dispatch Width: 2
|
||||
# CHECK-NEXT: IPC: 0.20
|
||||
|
||||
# CHECK: Instruction Info:
|
||||
# CHECK-NEXT: [1]: #uOps
|
||||
# CHECK-NEXT: [2]: Latency
|
||||
# CHECK-NEXT: [3]: RThroughput
|
||||
# CHECK-NEXT: [4]: MayLoad
|
||||
# CHECK-NEXT: [5]: MayStore
|
||||
# CHECK-NEXT: [6]: HasSideEffects
|
||||
|
||||
# CHECK: [1] [2] [3] [4] [5] [6] Instructions:
|
||||
# CHECK-NEXT: 1 7 1.00 * vmulps (%rsi), %xmm0, %xmm0
|
||||
# CHECK-NEXT: 1 1 0.50 addq %rsi, %rsi
|
||||
|
||||
# CHECK: Schedulers - number of cycles where we saw N instructions issued:
|
||||
# CHECK-NEXT: [# issued], [# cycles]
|
||||
# CHECK-NEXT: 0, 9 (90.0%)
|
||||
# CHECK-NEXT: 2, 1 (10.0%)
|
||||
|
||||
# CHECK: Scheduler's queue usage:
|
||||
# CHECK-NEXT: JALU01, 1/20
|
||||
# CHECK-NEXT: JFPU01, 1/18
|
||||
|
@ -26,9 +49,10 @@ add %rsi, %rsi
|
|||
|
||||
# CHECK: Resource pressure per iteration:
|
||||
# CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]
|
||||
# CHECK-NEXT: - 1.00 - - 1.00 - 1.00 1.00 - - - - - -
|
||||
# CHECK-NEXT: - 1.00 - - 1.00 - 1.00 1.00 - - - - - -
|
||||
|
||||
# CHECK: Resource pressure by instruction:
|
||||
# CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] Instructions:
|
||||
# CHECK-NEXT: - - - - 1.00 - 1.00 1.00 - - - - - - vmulps (%rsi), %xmm0, %xmm0
|
||||
# CHECK-NEXT: - 1.00 - - - - - - - - - - - - addq %rsi, %rsi
|
||||
|
||||
|
|
|
@ -21,42 +21,11 @@ using namespace llvm;
|
|||
namespace mca {
|
||||
|
||||
void BackendStatistics::onInstructionEvent(const HWInstructionEvent &Event) {
|
||||
switch (Event.Type) {
|
||||
default:
|
||||
break;
|
||||
case HWInstructionEvent::Retired: {
|
||||
if (Event.Type == HWInstructionEvent::Retired)
|
||||
++NumRetired;
|
||||
break;
|
||||
}
|
||||
case HWInstructionEvent::Issued:
|
||||
++NumIssued;
|
||||
}
|
||||
}
|
||||
|
||||
void BackendStatistics::onReservedBuffers(ArrayRef<unsigned> Buffers) {
|
||||
for (const unsigned Buffer : Buffers) {
|
||||
if (BufferedResources.find(Buffer) != BufferedResources.end()) {
|
||||
BufferUsage &BU = BufferedResources[Buffer];
|
||||
BU.SlotsInUse++;
|
||||
BU.MaxUsedSlots = std::max(BU.MaxUsedSlots, BU.SlotsInUse);
|
||||
continue;
|
||||
}
|
||||
|
||||
BufferedResources.insert(
|
||||
std::pair<unsigned, BufferUsage>(Buffer, {1U, 1U}));
|
||||
}
|
||||
}
|
||||
|
||||
void BackendStatistics::onReleasedBuffers(ArrayRef<unsigned> Buffers) {
|
||||
for (const unsigned Buffer : Buffers) {
|
||||
assert(BufferedResources.find(Buffer) != BufferedResources.end() &&
|
||||
"Buffered resource not in map?");
|
||||
BufferUsage &BU = BufferedResources[Buffer];
|
||||
BU.SlotsInUse--;
|
||||
}
|
||||
}
|
||||
|
||||
void BackendStatistics::printRetireUnitStatistics(llvm::raw_ostream &OS) const {
|
||||
void BackendStatistics::printView(llvm::raw_ostream &OS) const {
|
||||
std::string Buffer;
|
||||
raw_string_ostream TempStream(Buffer);
|
||||
TempStream << "\n\nRetire Control Unit - "
|
||||
|
@ -78,46 +47,4 @@ void BackendStatistics::printRetireUnitStatistics(llvm::raw_ostream &OS) const {
|
|||
OS << Buffer;
|
||||
}
|
||||
|
||||
void BackendStatistics::printSchedulerStatistics(llvm::raw_ostream &OS) const {
|
||||
std::string Buffer;
|
||||
raw_string_ostream TempStream(Buffer);
|
||||
TempStream << "\n\nSchedulers - number of cycles where we saw N instructions "
|
||||
"issued:\n";
|
||||
TempStream << "[# issued], [# cycles]\n";
|
||||
for (const std::pair<unsigned, unsigned> &Entry : IssuedPerCycle) {
|
||||
TempStream << " " << Entry.first << ", " << Entry.second << " ("
|
||||
<< format("%.1f", ((double)Entry.second / NumCycles) * 100)
|
||||
<< "%)\n";
|
||||
}
|
||||
|
||||
TempStream.flush();
|
||||
OS << Buffer;
|
||||
}
|
||||
|
||||
void BackendStatistics::printSchedulerUsage(raw_ostream &OS,
|
||||
const MCSchedModel &SM) const {
|
||||
std::string Buffer;
|
||||
raw_string_ostream TempStream(Buffer);
|
||||
TempStream << "\n\nScheduler's queue usage:\n";
|
||||
// Early exit if no buffered resources were consumed.
|
||||
if (BufferedResources.empty()) {
|
||||
TempStream << "No scheduler resources used.\n";
|
||||
TempStream.flush();
|
||||
OS << Buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
|
||||
const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
|
||||
if (ProcResource.BufferSize <= 0)
|
||||
continue;
|
||||
|
||||
const BufferUsage &BU = BufferedResources.lookup(I);
|
||||
TempStream << ProcResource.Name << ", " << BU.MaxUsedSlots << '/'
|
||||
<< ProcResource.BufferSize << '\n';
|
||||
}
|
||||
|
||||
TempStream.flush();
|
||||
OS << Buffer;
|
||||
}
|
||||
} // namespace mca
|
||||
|
|
|
@ -8,18 +8,12 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
///
|
||||
/// This file implements a printer class for printing generic Backend
|
||||
/// statistics related to the scheduler and retire unit.
|
||||
/// This file implements a View named BackendStatistics that knows how to
|
||||
/// collect and print a few statistics related to the retire unit.
|
||||
///
|
||||
/// Example:
|
||||
/// ========
|
||||
///
|
||||
/// Schedulers - number of cycles where we saw N instructions issued:
|
||||
/// [# issued], [# cycles]
|
||||
/// 0, 7 (5.4%)
|
||||
/// 1, 4 (3.1%)
|
||||
/// 2, 8 (6.2%)
|
||||
///
|
||||
/// Retire Control Unit - number of cycles where we saw N instructions retired:
|
||||
/// [# retired], [# cycles]
|
||||
/// 0, 9 (6.9%)
|
||||
|
@ -27,11 +21,6 @@
|
|||
/// 2, 1 (0.8%)
|
||||
/// 4, 3 (2.3%)
|
||||
///
|
||||
/// Scheduler's queue usage:
|
||||
/// JALU01, 0/20
|
||||
/// JFPU01, 18/18
|
||||
/// JLSAGU, 0/12
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_MCA_BACKENDSTATISTICS_H
|
||||
|
@ -49,43 +38,21 @@ class BackendStatistics : public View {
|
|||
|
||||
using Histogram = llvm::DenseMap<unsigned, unsigned>;
|
||||
Histogram RetiredPerCycle;
|
||||
Histogram IssuedPerCycle;
|
||||
|
||||
unsigned NumIssued;
|
||||
unsigned NumRetired;
|
||||
unsigned NumCycles;
|
||||
|
||||
// Tracks the usage of a scheduler's queue.
|
||||
struct BufferUsage {
|
||||
unsigned SlotsInUse;
|
||||
unsigned MaxUsedSlots;
|
||||
};
|
||||
|
||||
// There is a map entry for each buffered resource in the scheduling model.
|
||||
// Every time a buffer is consumed/freed, this view updates the corresponding
|
||||
// entry.
|
||||
llvm::DenseMap<unsigned, BufferUsage> BufferedResources;
|
||||
|
||||
void updateHistograms() {
|
||||
IssuedPerCycle[NumIssued]++;
|
||||
RetiredPerCycle[NumRetired]++;
|
||||
NumIssued = 0;
|
||||
NumRetired = 0;
|
||||
}
|
||||
|
||||
void printRetireUnitStatistics(llvm::raw_ostream &OS) const;
|
||||
void printSchedulerStatistics(llvm::raw_ostream &OS) const;
|
||||
|
||||
void printRCUStatistics(llvm::raw_ostream &OS, const Histogram &Histogram,
|
||||
unsigned Cycles) const;
|
||||
void printIssuePerCycle(const Histogram &IssuePerCycle,
|
||||
unsigned TotalCycles) const;
|
||||
void printSchedulerUsage(llvm::raw_ostream &OS,
|
||||
const llvm::MCSchedModel &SM) const;
|
||||
|
||||
public:
|
||||
BackendStatistics(const llvm::MCSubtargetInfo &sti)
|
||||
: STI(sti), NumIssued(0), NumRetired(0), NumCycles(0) { }
|
||||
: STI(sti), NumRetired(0), NumCycles(0) {}
|
||||
|
||||
void onInstructionEvent(const HWInstructionEvent &Event) override;
|
||||
|
||||
|
@ -93,19 +60,7 @@ public:
|
|||
|
||||
void onCycleEnd(unsigned Cycle) override { updateHistograms(); }
|
||||
|
||||
// Increases the number of used scheduler queue slots of every buffered
|
||||
// resource in the Buffers set.
|
||||
void onReservedBuffers(llvm::ArrayRef<unsigned> Buffers) override;
|
||||
|
||||
// Decreases by one the number of used scheduler queue slots of every
|
||||
// buffered resource in the Buffers set.
|
||||
void onReleasedBuffers(llvm::ArrayRef<unsigned> Buffers) override;
|
||||
|
||||
void printView(llvm::raw_ostream &OS) const override {
|
||||
printSchedulerStatistics(OS);
|
||||
printRetireUnitStatistics(OS);
|
||||
printSchedulerUsage(OS, STI.getSchedModel());
|
||||
}
|
||||
void printView(llvm::raw_ostream &OS) const override;
|
||||
};
|
||||
} // namespace mca
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ add_llvm_tool(llvm-mca
|
|||
RegisterFileStatistics.cpp
|
||||
ResourcePressureView.cpp
|
||||
Scheduler.cpp
|
||||
SchedulerStatistics.cpp
|
||||
Support.cpp
|
||||
SummaryView.cpp
|
||||
TimelineView.cpp
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
//===--------------------- SchedulerStatistics.cpp --------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
///
|
||||
/// This file implements the SchedulerStatistics interface.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "SchedulerStatistics.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace mca {
|
||||
|
||||
void SchedulerStatistics::onInstructionEvent(const HWInstructionEvent &Event) {
|
||||
if (Event.Type == HWInstructionEvent::Issued)
|
||||
++NumIssued;
|
||||
}
|
||||
|
||||
void SchedulerStatistics::onReservedBuffers(ArrayRef<unsigned> Buffers) {
|
||||
for (const unsigned Buffer : Buffers) {
|
||||
if (BufferedResources.find(Buffer) != BufferedResources.end()) {
|
||||
BufferUsage &BU = BufferedResources[Buffer];
|
||||
BU.SlotsInUse++;
|
||||
BU.MaxUsedSlots = std::max(BU.MaxUsedSlots, BU.SlotsInUse);
|
||||
continue;
|
||||
}
|
||||
|
||||
BufferedResources.insert(
|
||||
std::pair<unsigned, BufferUsage>(Buffer, {1U, 1U}));
|
||||
}
|
||||
}
|
||||
|
||||
void SchedulerStatistics::onReleasedBuffers(ArrayRef<unsigned> Buffers) {
|
||||
for (const unsigned Buffer : Buffers) {
|
||||
assert(BufferedResources.find(Buffer) != BufferedResources.end() &&
|
||||
"Buffered resource not in map?");
|
||||
BufferUsage &BU = BufferedResources[Buffer];
|
||||
BU.SlotsInUse--;
|
||||
}
|
||||
}
|
||||
|
||||
void SchedulerStatistics::printSchedulerStatistics(llvm::raw_ostream &OS) const {
|
||||
std::string Buffer;
|
||||
raw_string_ostream TempStream(Buffer);
|
||||
TempStream << "\n\nSchedulers - number of cycles where we saw N instructions "
|
||||
"issued:\n";
|
||||
TempStream << "[# issued], [# cycles]\n";
|
||||
for (const std::pair<unsigned, unsigned> &Entry : IssuedPerCycle) {
|
||||
TempStream << " " << Entry.first << ", " << Entry.second << " ("
|
||||
<< format("%.1f", ((double)Entry.second / NumCycles) * 100)
|
||||
<< "%)\n";
|
||||
}
|
||||
|
||||
TempStream.flush();
|
||||
OS << Buffer;
|
||||
}
|
||||
|
||||
void SchedulerStatistics::printSchedulerUsage(raw_ostream &OS,
|
||||
const MCSchedModel &SM) const {
|
||||
std::string Buffer;
|
||||
raw_string_ostream TempStream(Buffer);
|
||||
TempStream << "\n\nScheduler's queue usage:\n";
|
||||
// Early exit if no buffered resources were consumed.
|
||||
if (BufferedResources.empty()) {
|
||||
TempStream << "No scheduler resources used.\n";
|
||||
TempStream.flush();
|
||||
OS << Buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
|
||||
const MCProcResourceDesc &ProcResource = *SM.getProcResource(I);
|
||||
if (ProcResource.BufferSize <= 0)
|
||||
continue;
|
||||
|
||||
const BufferUsage &BU = BufferedResources.lookup(I);
|
||||
TempStream << ProcResource.Name << ", " << BU.MaxUsedSlots << '/'
|
||||
<< ProcResource.BufferSize << '\n';
|
||||
}
|
||||
|
||||
TempStream.flush();
|
||||
OS << Buffer;
|
||||
}
|
||||
} // namespace mca
|
|
@ -0,0 +1,95 @@
|
|||
//===--------------------- SchedulerStatistics.h ----------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// \file
|
||||
///
|
||||
/// This file defines class SchedulerStatistics. Class SchedulerStatistics is a
|
||||
/// View that listens to instruction issue events in order to print general
|
||||
/// statistics related to the hardware schedulers.
|
||||
///
|
||||
/// Example:
|
||||
/// ========
|
||||
///
|
||||
/// Schedulers - number of cycles where we saw N instructions issued:
|
||||
/// [# issued], [# cycles]
|
||||
/// 0, 7 (5.4%)
|
||||
/// 1, 4 (3.1%)
|
||||
/// 2, 8 (6.2%)
|
||||
///
|
||||
/// Scheduler's queue usage:
|
||||
/// JALU01, 0/20
|
||||
/// JFPU01, 18/18
|
||||
/// JLSAGU, 0/12
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TOOLS_LLVM_MCA_SCHEDULERSTATISTICS_H
|
||||
#define LLVM_TOOLS_LLVM_MCA_SCHEDULERSTATISTICS_H
|
||||
|
||||
#include "View.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
|
||||
namespace mca {
|
||||
|
||||
class SchedulerStatistics : public View {
|
||||
const llvm::MCSubtargetInfo &STI;
|
||||
|
||||
using Histogram = llvm::DenseMap<unsigned, unsigned>;
|
||||
Histogram IssuedPerCycle;
|
||||
|
||||
unsigned NumIssued;
|
||||
unsigned NumCycles;
|
||||
|
||||
// Tracks the usage of a scheduler's queue.
|
||||
struct BufferUsage {
|
||||
unsigned SlotsInUse;
|
||||
unsigned MaxUsedSlots;
|
||||
};
|
||||
|
||||
llvm::DenseMap<unsigned, BufferUsage> BufferedResources;
|
||||
|
||||
void updateHistograms() {
|
||||
IssuedPerCycle[NumIssued]++;
|
||||
NumIssued = 0;
|
||||
}
|
||||
|
||||
void printSchedulerStatistics(llvm::raw_ostream &OS) const;
|
||||
|
||||
void printIssuePerCycle(const Histogram &IssuePerCycle,
|
||||
unsigned TotalCycles) const;
|
||||
void printSchedulerUsage(llvm::raw_ostream &OS,
|
||||
const llvm::MCSchedModel &SM) const;
|
||||
|
||||
public:
|
||||
SchedulerStatistics(const llvm::MCSubtargetInfo &sti)
|
||||
: STI(sti), NumIssued(0), NumCycles(0) { }
|
||||
|
||||
void onInstructionEvent(const HWInstructionEvent &Event) override;
|
||||
|
||||
void onCycleBegin(unsigned Cycle) override { NumCycles++; }
|
||||
|
||||
void onCycleEnd(unsigned Cycle) override { updateHistograms(); }
|
||||
|
||||
// Increases the number of used scheduler queue slots of every buffered
|
||||
// resource in the Buffers set.
|
||||
void onReservedBuffers(llvm::ArrayRef<unsigned> Buffers) override;
|
||||
|
||||
// Decreases by one the number of used scheduler queue slots of every
|
||||
// buffered resource in the Buffers set.
|
||||
void onReleasedBuffers(llvm::ArrayRef<unsigned> Buffers) override;
|
||||
|
||||
void printView(llvm::raw_ostream &OS) const override {
|
||||
printSchedulerStatistics(OS);
|
||||
printSchedulerUsage(OS, STI.getSchedModel());
|
||||
}
|
||||
};
|
||||
} // namespace mca
|
||||
|
||||
#endif
|
|
@ -29,6 +29,7 @@
|
|||
#include "InstructionTables.h"
|
||||
#include "RegisterFileStatistics.h"
|
||||
#include "ResourcePressureView.h"
|
||||
#include "SchedulerStatistics.h"
|
||||
#include "SummaryView.h"
|
||||
#include "TimelineView.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
|
@ -99,6 +100,11 @@ static cl::opt<bool>
|
|||
cl::desc("Print dispatch statistics"),
|
||||
cl::init(false));
|
||||
|
||||
static cl::opt<bool>
|
||||
PrintiSchedulerStats("scheduler-stats",
|
||||
cl::desc("Print scheduler statistics"),
|
||||
cl::init(false));
|
||||
|
||||
static cl::opt<bool>
|
||||
PrintResourcePressureView("resource-pressure",
|
||||
cl::desc("Print the resource pressure view"),
|
||||
|
@ -432,6 +438,9 @@ int main(int argc, char **argv) {
|
|||
if (PrintDispatchStats)
|
||||
Printer.addView(llvm::make_unique<mca::DispatchStatistics>(*STI));
|
||||
|
||||
if (PrintiSchedulerStats)
|
||||
Printer.addView(llvm::make_unique<mca::SchedulerStatistics>(*STI));
|
||||
|
||||
if (PrintModeVerbose)
|
||||
Printer.addView(llvm::make_unique<mca::BackendStatistics>(*STI));
|
||||
|
||||
|
|
Loading…
Reference in New Issue