mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Print memory stats
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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_);
|
||||
|
||||
@@ -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_{};
|
||||
|
||||
Reference in New Issue
Block a user