@@ -135,6 +135,44 @@ void et_pal_emit_log_message(
135135
136136namespace {
137137
138+ // Setup our own allocator that can show some extra stuff like used and free
139+ // memory info
140+ class ArmMemoryAllocator : public executorch ::runtime::MemoryAllocator {
141+ public:
142+ ArmMemoryAllocator (uint32_t size, uint8_t * base_address)
143+ : MemoryAllocator(size, base_address), used_(0 ) {}
144+
145+ void * allocate (size_t size, size_t alignment = kDefaultAlignment ) override {
146+ void * ret = executorch::runtime::MemoryAllocator::allocate (size, alignment);
147+ if (ret != nullptr ) {
148+ // Align with the same code as in MemoryAllocator::allocate() to keep
149+ // used_ "in sync" As alignment is expected to be power of 2 (checked by
150+ // MemoryAllocator::allocate()) we can check it the lower bits
151+ // (same as alignment - 1) is zero or not.
152+ if ((size & (alignment - 1 )) == 0 ) {
153+ // Already aligned.
154+ used_ += size;
155+ } else {
156+ used_ = (used_ | (alignment - 1 )) + 1 + size;
157+ }
158+ }
159+ return ret;
160+ }
161+
162+ // Returns the used size of the allocator's memory buffer.
163+ size_t used_size () const {
164+ return used_;
165+ }
166+
167+ // Returns the free size of the allocator's memory buffer.
168+ size_t free_size () const {
169+ return executorch::runtime::MemoryAllocator::size () - used_;
170+ }
171+
172+ private:
173+ size_t used_;
174+ };
175+
138176Result<BufferCleanup> prepare_input_tensors (
139177 Method& method,
140178 MemoryAllocator& allocator,
@@ -291,7 +329,7 @@ int main(int argc, const char* argv[]) {
291329
292330#ifdef SEMIHOSTING
293331 const char * output_basename = nullptr ;
294- MemoryAllocator input_file_allocator (
332+ ArmMemoryAllocator input_file_allocator (
295333 input_file_allocation_pool_size, input_file_allocation_pool);
296334
297335 /* parse input parameters */
@@ -354,13 +392,15 @@ int main(int argc, const char* argv[]) {
354392 (unsigned int )method_meta.error ());
355393 }
356394
357- MemoryAllocator method_allocator (
395+ ArmMemoryAllocator method_allocator (
358396 method_allocation_pool_size, method_allocation_pool);
359397
360398 std::vector<uint8_t *> planned_buffers; // Owns the memory
361399 std::vector<Span<uint8_t >> planned_spans; // Passed to the allocator
362400 size_t num_memory_planned_buffers = method_meta->num_memory_planned_buffers ();
363401
402+ size_t planned_buffer_membase = method_allocator.used_size ();
403+
364404 for (size_t id = 0 ; id < num_memory_planned_buffers; ++id) {
365405 size_t buffer_size =
366406 static_cast <size_t >(method_meta->memory_planned_buffer_size (id).get ());
@@ -373,15 +413,20 @@ int main(int argc, const char* argv[]) {
373413 planned_spans.push_back ({planned_buffers.back (), buffer_size});
374414 }
375415
416+ size_t planned_buffer_memsize =
417+ method_allocator.used_size () - planned_buffer_membase;
418+
376419 HierarchicalAllocator planned_memory (
377420 {planned_spans.data (), planned_spans.size ()});
378421
379- MemoryAllocator temp_allocator (
422+ ArmMemoryAllocator temp_allocator (
380423 temp_allocation_pool_size, temp_allocation_pool);
381424
382425 MemoryManager memory_manager (
383426 &method_allocator, &planned_memory, &temp_allocator);
384427
428+ size_t method_loaded_membase = method_allocator.used_size ();
429+
385430 Result<Method> method = program->load_method (method_name, &memory_manager);
386431 if (!method.ok ()) {
387432 ET_LOG (
@@ -390,9 +435,12 @@ int main(int argc, const char* argv[]) {
390435 method_name,
391436 method.error ());
392437 }
438+ size_t method_loaded_memsize =
439+ method_allocator.used_size () - method_loaded_membase;
393440 ET_LOG (Info, " Method loaded." );
394441
395442 ET_LOG (Info, " Preparing inputs..." );
443+ size_t input_membase = method_allocator.used_size ();
396444
397445 auto inputs =
398446 ::prepare_input_tensors (*method, method_allocator, input_buffers);
@@ -404,12 +452,52 @@ int main(int argc, const char* argv[]) {
404452 method_name,
405453 inputs.error ());
406454 }
455+ size_t input_memsize = method_allocator.used_size () - input_membase;
407456 ET_LOG (Info, " Input prepared." );
408457
409458 ET_LOG (Info, " Starting the model execution..." );
459+ size_t executor_membase = method_allocator.used_size ();
410460 StartMeasurements ();
411461 Error status = method->execute ();
412462 StopMeasurements ();
463+ size_t executor_memsize = method_allocator.used_size () - executor_membase;
464+
465+ ET_LOG (Info, " model_pte_loaded_size: %lu bytes." , pte_size);
466+ #ifdef SEMIHOSTING
467+ if (input_file_allocator.size () > 0 ) {
468+ ET_LOG (
469+ Info,
470+ " input_file_allocator_used: %zu / %zu free: %zu ( used: %zu %% ) " ,
471+ input_file_allocator.used_size (),
472+ input_file_allocator.size (),
473+ input_file_allocator.free_size (),
474+ 100 * input_file_allocator.used_size () / input_file_allocator.size ());
475+ }
476+ #endif
477+ if (method_allocator.size () != 0 ) {
478+ size_t method_allocator_used = method_allocator.used_size ();
479+ ET_LOG (
480+ Info,
481+ " method_allocator_used: %zu / %zu free: %zu ( used: %zu %% ) " ,
482+ method_allocator_used,
483+ method_allocator.size (),
484+ method_allocator.free_size (),
485+ 100 * method_allocator_used / method_allocator.size ());
486+ ET_LOG (
487+ Info, " method_allocator_planned: %zu bytes" , planned_buffer_memsize);
488+ ET_LOG (Info, " method_allocator_loaded: %zu bytes" , method_loaded_memsize);
489+ ET_LOG (Info, " method_allocator_input: %zu bytes" , input_memsize);
490+ ET_LOG (Info, " method_allocator_executor: %zu bytes" , executor_memsize);
491+ }
492+ if (temp_allocator.size () > 0 ) {
493+ ET_LOG (
494+ Info,
495+ " temp_allocator_used: %zu / %zu free: %zu ( used: %zu %% ) " ,
496+ temp_allocator.used_size (),
497+ temp_allocator.size (),
498+ temp_allocator.free_size (),
499+ 100 * temp_allocator.used_size () / temp_allocator.size ());
500+ }
413501
414502 if (status != Error::Ok) {
415503 ET_LOG (
0 commit comments