Print memory stats

This commit is contained in:
momo5502
2025-07-12 13:47:52 +02:00
parent 90c087786c
commit 08995a4205
8 changed files with 196 additions and 54 deletions

View File

@@ -1,6 +1,6 @@
import { EmulationStatus } from "@/emulator";
import { TextTooltip } from "./text-tooltip";
import { BarChartSteps, CpuFill } from "react-bootstrap-icons";
import { BarChartSteps, CpuFill, FloppyFill } from "react-bootstrap-icons";
import "./emulation-summary.css";
@@ -8,6 +8,20 @@ export interface EmulationSummaryProps {
status?: EmulationStatus;
}
function formatMemory(value: BigInt): string {
const abbr = ["B", "KB", "MB", "GB", "PB"];
let num = Number(value);
let index = 0;
while (num >= 1024 && index < abbr.length - 1) {
num /= 1024;
index++;
}
return num.toFixed(2) + " " + abbr[index];
}
export function EmulationSummary(props: EmulationSummaryProps) {
if (!props.status) {
return <></>;
@@ -20,6 +34,11 @@ export function EmulationSummary(props: EmulationSummaryProps) {
<BarChartSteps className="inline ml-3" />
</TextTooltip>
<br />
<TextTooltip tooltip={"Application memory"}>
{formatMemory(props.status.committedMemory)}
<FloppyFill className="inline ml-3" />
</TextTooltip>
<br />
<TextTooltip tooltip={"Executed instructions"}>
{props.status.executedInstructions.toLocaleString()}
<CpuFill className="inline ml-3" />

View File

@@ -14,14 +14,18 @@ export enum EmulationState {
}
export interface EmulationStatus {
executedInstructions: BigInt;
activeThreads: number;
reservedMemory: BigInt;
committedMemory: BigInt;
executedInstructions: BigInt;
}
function createDefaultEmulationStatus(): EmulationStatus {
return {
executedInstructions: BigInt(0),
activeThreads: 0,
reservedMemory: BigInt(0),
committedMemory: BigInt(0),
};
}
@@ -239,6 +243,8 @@ export class Emulator {
this.stautsUpdateHandler({
activeThreads: info.activeThreads,
executedInstructions: info.executedInstructions,
reservedMemory: info.reservedMemory,
committedMemory: info.committedMemory,
});
}

View File

@@ -24,29 +24,13 @@ static getSizePrefixedRootAsEmulationStatus(bb:flatbuffers.ByteBuffer, obj?:Emul
return (obj || new EmulationStatus()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
}
executedInstructions():bigint {
const offset = this.bb!.__offset(this.bb_pos, 4);
return offset ? this.bb!.readUint64(this.bb_pos + offset) : BigInt('0');
}
mutate_executed_instructions(value:bigint):boolean {
const offset = this.bb!.__offset(this.bb_pos, 4);
if (offset === 0) {
return false;
}
this.bb!.writeUint64(this.bb_pos + offset, value);
return true;
}
activeThreads():number {
const offset = this.bb!.__offset(this.bb_pos, 6);
const offset = this.bb!.__offset(this.bb_pos, 4);
return offset ? this.bb!.readUint32(this.bb_pos + offset) : 0;
}
mutate_active_threads(value:number):boolean {
const offset = this.bb!.__offset(this.bb_pos, 6);
const offset = this.bb!.__offset(this.bb_pos, 4);
if (offset === 0) {
return false;
@@ -56,16 +40,72 @@ mutate_active_threads(value:number):boolean {
return true;
}
static startEmulationStatus(builder:flatbuffers.Builder) {
builder.startObject(2);
reservedMemory():bigint {
const offset = this.bb!.__offset(this.bb_pos, 6);
return offset ? this.bb!.readUint64(this.bb_pos + offset) : BigInt('0');
}
static addExecutedInstructions(builder:flatbuffers.Builder, executedInstructions:bigint) {
builder.addFieldInt64(0, executedInstructions, BigInt('0'));
mutate_reserved_memory(value:bigint):boolean {
const offset = this.bb!.__offset(this.bb_pos, 6);
if (offset === 0) {
return false;
}
this.bb!.writeUint64(this.bb_pos + offset, value);
return true;
}
committedMemory():bigint {
const offset = this.bb!.__offset(this.bb_pos, 8);
return offset ? this.bb!.readUint64(this.bb_pos + offset) : BigInt('0');
}
mutate_committed_memory(value:bigint):boolean {
const offset = this.bb!.__offset(this.bb_pos, 8);
if (offset === 0) {
return false;
}
this.bb!.writeUint64(this.bb_pos + offset, value);
return true;
}
executedInstructions():bigint {
const offset = this.bb!.__offset(this.bb_pos, 10);
return offset ? this.bb!.readUint64(this.bb_pos + offset) : BigInt('0');
}
mutate_executed_instructions(value:bigint):boolean {
const offset = this.bb!.__offset(this.bb_pos, 10);
if (offset === 0) {
return false;
}
this.bb!.writeUint64(this.bb_pos + offset, value);
return true;
}
static startEmulationStatus(builder:flatbuffers.Builder) {
builder.startObject(4);
}
static addActiveThreads(builder:flatbuffers.Builder, activeThreads:number) {
builder.addFieldInt32(1, activeThreads, 0);
builder.addFieldInt32(0, activeThreads, 0);
}
static addReservedMemory(builder:flatbuffers.Builder, reservedMemory:bigint) {
builder.addFieldInt64(1, reservedMemory, BigInt('0'));
}
static addCommittedMemory(builder:flatbuffers.Builder, committedMemory:bigint) {
builder.addFieldInt64(2, committedMemory, BigInt('0'));
}
static addExecutedInstructions(builder:flatbuffers.Builder, executedInstructions:bigint) {
builder.addFieldInt64(3, executedInstructions, BigInt('0'));
}
static endEmulationStatus(builder:flatbuffers.Builder):flatbuffers.Offset {
@@ -73,38 +113,48 @@ static endEmulationStatus(builder:flatbuffers.Builder):flatbuffers.Offset {
return offset;
}
static createEmulationStatus(builder:flatbuffers.Builder, executedInstructions:bigint, activeThreads:number):flatbuffers.Offset {
static createEmulationStatus(builder:flatbuffers.Builder, activeThreads:number, reservedMemory:bigint, committedMemory:bigint, executedInstructions:bigint):flatbuffers.Offset {
EmulationStatus.startEmulationStatus(builder);
EmulationStatus.addExecutedInstructions(builder, executedInstructions);
EmulationStatus.addActiveThreads(builder, activeThreads);
EmulationStatus.addReservedMemory(builder, reservedMemory);
EmulationStatus.addCommittedMemory(builder, committedMemory);
EmulationStatus.addExecutedInstructions(builder, executedInstructions);
return EmulationStatus.endEmulationStatus(builder);
}
unpack(): EmulationStatusT {
return new EmulationStatusT(
this.executedInstructions(),
this.activeThreads()
this.activeThreads(),
this.reservedMemory(),
this.committedMemory(),
this.executedInstructions()
);
}
unpackTo(_o: EmulationStatusT): void {
_o.executedInstructions = this.executedInstructions();
_o.activeThreads = this.activeThreads();
_o.reservedMemory = this.reservedMemory();
_o.committedMemory = this.committedMemory();
_o.executedInstructions = this.executedInstructions();
}
}
export class EmulationStatusT implements flatbuffers.IGeneratedObject {
constructor(
public executedInstructions: bigint = BigInt('0'),
public activeThreads: number = 0
public activeThreads: number = 0,
public reservedMemory: bigint = BigInt('0'),
public committedMemory: bigint = BigInt('0'),
public executedInstructions: bigint = BigInt('0')
){}
pack(builder:flatbuffers.Builder): flatbuffers.Offset {
return EmulationStatus.createEmulationStatus(builder,
this.executedInstructions,
this.activeThreads
this.activeThreads,
this.reservedMemory,
this.committedMemory,
this.executedInstructions
);
}
}

View File

@@ -236,7 +236,11 @@ namespace debugger
void update_emulation_status(const windows_emulator& win_emu)
{
const auto memory_status = win_emu.memory.compute_memory_stats();
Debugger::EmulationStatusT status{};
status.reserved_memory = memory_status.reserved_memory;
status.committed_memory = memory_status.committed_memory;
status.executed_instructions = win_emu.get_executed_instructions();
status.active_threads = static_cast<uint32_t>(win_emu.process.threads.size());
send_event(status);

View File

@@ -64,8 +64,10 @@ table ApplicationExit {
}
table EmulationStatus {
executed_instructions: uint64;
active_threads: uint32;
reserved_memory: uint64;
committed_memory: uint64;
executed_instructions: uint64;
}
union Event {

View File

@@ -1303,33 +1303,51 @@ inline ::flatbuffers::Offset<ApplicationExit> CreateApplicationExit(
struct EmulationStatusT : public ::flatbuffers::NativeTable {
typedef EmulationStatus TableType;
uint64_t executed_instructions = 0;
uint32_t active_threads = 0;
uint64_t reserved_memory = 0;
uint64_t committed_memory = 0;
uint64_t executed_instructions = 0;
};
struct EmulationStatus FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
typedef EmulationStatusT NativeTableType;
typedef EmulationStatusBuilder Builder;
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_EXECUTED_INSTRUCTIONS = 4,
VT_ACTIVE_THREADS = 6
VT_ACTIVE_THREADS = 4,
VT_RESERVED_MEMORY = 6,
VT_COMMITTED_MEMORY = 8,
VT_EXECUTED_INSTRUCTIONS = 10
};
uint64_t executed_instructions() const {
return GetField<uint64_t>(VT_EXECUTED_INSTRUCTIONS, 0);
}
bool mutate_executed_instructions(uint64_t _executed_instructions = 0) {
return SetField<uint64_t>(VT_EXECUTED_INSTRUCTIONS, _executed_instructions, 0);
}
uint32_t active_threads() const {
return GetField<uint32_t>(VT_ACTIVE_THREADS, 0);
}
bool mutate_active_threads(uint32_t _active_threads = 0) {
return SetField<uint32_t>(VT_ACTIVE_THREADS, _active_threads, 0);
}
uint64_t reserved_memory() const {
return GetField<uint64_t>(VT_RESERVED_MEMORY, 0);
}
bool mutate_reserved_memory(uint64_t _reserved_memory = 0) {
return SetField<uint64_t>(VT_RESERVED_MEMORY, _reserved_memory, 0);
}
uint64_t committed_memory() const {
return GetField<uint64_t>(VT_COMMITTED_MEMORY, 0);
}
bool mutate_committed_memory(uint64_t _committed_memory = 0) {
return SetField<uint64_t>(VT_COMMITTED_MEMORY, _committed_memory, 0);
}
uint64_t executed_instructions() const {
return GetField<uint64_t>(VT_EXECUTED_INSTRUCTIONS, 0);
}
bool mutate_executed_instructions(uint64_t _executed_instructions = 0) {
return SetField<uint64_t>(VT_EXECUTED_INSTRUCTIONS, _executed_instructions, 0);
}
bool Verify(::flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<uint64_t>(verifier, VT_EXECUTED_INSTRUCTIONS, 8) &&
VerifyField<uint32_t>(verifier, VT_ACTIVE_THREADS, 4) &&
VerifyField<uint64_t>(verifier, VT_RESERVED_MEMORY, 8) &&
VerifyField<uint64_t>(verifier, VT_COMMITTED_MEMORY, 8) &&
VerifyField<uint64_t>(verifier, VT_EXECUTED_INSTRUCTIONS, 8) &&
verifier.EndTable();
}
EmulationStatusT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
@@ -1341,12 +1359,18 @@ struct EmulationStatusBuilder {
typedef EmulationStatus Table;
::flatbuffers::FlatBufferBuilder &fbb_;
::flatbuffers::uoffset_t start_;
void add_executed_instructions(uint64_t executed_instructions) {
fbb_.AddElement<uint64_t>(EmulationStatus::VT_EXECUTED_INSTRUCTIONS, executed_instructions, 0);
}
void add_active_threads(uint32_t active_threads) {
fbb_.AddElement<uint32_t>(EmulationStatus::VT_ACTIVE_THREADS, active_threads, 0);
}
void add_reserved_memory(uint64_t reserved_memory) {
fbb_.AddElement<uint64_t>(EmulationStatus::VT_RESERVED_MEMORY, reserved_memory, 0);
}
void add_committed_memory(uint64_t committed_memory) {
fbb_.AddElement<uint64_t>(EmulationStatus::VT_COMMITTED_MEMORY, committed_memory, 0);
}
void add_executed_instructions(uint64_t executed_instructions) {
fbb_.AddElement<uint64_t>(EmulationStatus::VT_EXECUTED_INSTRUCTIONS, executed_instructions, 0);
}
explicit EmulationStatusBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
@@ -1360,10 +1384,14 @@ struct EmulationStatusBuilder {
inline ::flatbuffers::Offset<EmulationStatus> CreateEmulationStatus(
::flatbuffers::FlatBufferBuilder &_fbb,
uint64_t executed_instructions = 0,
uint32_t active_threads = 0) {
uint32_t active_threads = 0,
uint64_t reserved_memory = 0,
uint64_t committed_memory = 0,
uint64_t executed_instructions = 0) {
EmulationStatusBuilder builder_(_fbb);
builder_.add_executed_instructions(executed_instructions);
builder_.add_committed_memory(committed_memory);
builder_.add_reserved_memory(reserved_memory);
builder_.add_active_threads(active_threads);
return builder_.Finish();
}
@@ -1903,8 +1931,10 @@ inline EmulationStatusT *EmulationStatus::UnPack(const ::flatbuffers::resolver_f
inline void EmulationStatus::UnPackTo(EmulationStatusT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
(void)_o;
(void)_resolver;
{ auto _e = executed_instructions(); _o->executed_instructions = _e; }
{ auto _e = active_threads(); _o->active_threads = _e; }
{ auto _e = reserved_memory(); _o->reserved_memory = _e; }
{ auto _e = committed_memory(); _o->committed_memory = _e; }
{ auto _e = executed_instructions(); _o->executed_instructions = _e; }
}
inline ::flatbuffers::Offset<EmulationStatus> EmulationStatus::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const EmulationStatusT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
@@ -1915,12 +1945,16 @@ inline ::flatbuffers::Offset<EmulationStatus> CreateEmulationStatus(::flatbuffer
(void)_rehasher;
(void)_o;
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const EmulationStatusT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
auto _executed_instructions = _o->executed_instructions;
auto _active_threads = _o->active_threads;
auto _reserved_memory = _o->reserved_memory;
auto _committed_memory = _o->committed_memory;
auto _executed_instructions = _o->executed_instructions;
return Debugger::CreateEmulationStatus(
_fbb,
_executed_instructions,
_active_threads);
_active_threads,
_reserved_memory,
_committed_memory,
_executed_instructions);
}
inline DebugEventT *DebugEvent::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {

View File

@@ -100,6 +100,25 @@ void memory_manager::update_layout_version()
#endif
}
memory_stats memory_manager::compute_memory_stats() const
{
memory_stats stats{};
stats.reserved_memory = 0;
stats.committed_memory = 0;
for (const auto& reserved_region : this->reserved_regions_ | std::views::values)
{
stats.reserved_memory += reserved_region.length;
for (const auto& committed_region : reserved_region.committed_regions | std::views::values)
{
stats.committed_memory += committed_region.length;
}
}
return stats;
}
void memory_manager::serialize_memory_state(utils::buffer_serializer& buffer, const bool is_snapshot) const
{
buffer.write_atomic(this->layout_version_);

View File

@@ -24,6 +24,12 @@ struct region_info : basic_memory_region
using mmio_read_callback = std::function<void(uint64_t addr, void* data, size_t size)>;
using mmio_write_callback = std::function<void(uint64_t addr, const void* data, size_t size)>;
struct memory_stats
{
uint64_t reserved_memory = 0;
uint64_t committed_memory = 0;
};
class memory_manager : public memory_interface
{
public:
@@ -90,6 +96,8 @@ class memory_manager : public memory_interface
void serialize_memory_state(utils::buffer_serializer& buffer, bool is_snapshot) const;
void deserialize_memory_state(utils::buffer_deserializer& buffer, bool is_snapshot);
memory_stats compute_memory_stats() const;
private:
memory_interface* memory_{};
reserved_region_map reserved_regions_{};