<document definer="Amiga" type="readme">
<head>
  <domain layer=0>AmigaDE
  <domain layer=1>Utilities
  <domain layer=2>Memory Profiling
  <version>0:2
</head>
<version_log>
  <entry>
    <resource>fleecy moss
    <timestamp format="yyyy-mm-dd">2001-08-25
    <description>first release
  </entry>
</version_log>
<index>
  <section ref=1>Introduction
  <section ref=2>Installation
  <section ref=3>Usage
  <section ref=4>Known Issues
</index>
;===============================================================================
<body>

<section ref=1>
  <p>
    The Amiga memory system allows for a sophisticated monitoring of memory usage which
    helps to reduce memory leaks and optimise memory management.
  </p>
  <p>
    The key elements of the content service are;
    <ul>
      <li>the memory macros
      <li>the profile report
    </ul>
  </p>
  <p>
    Version 0:2 supports transient memory allocation and deallocation. It does not support 
    persistent memory allocation as of yet because it is much harder to track memory as
    it is passed between processes and threads. A set of macros is provided which allows the user
    to get and free memory, and which provides the profiling information necessary for the profiler.
    A simple switch can turn this off and on to reduce the overhead.
  </p>
  <p>
    The profile report picks up the memory usage information and then provides a list of all
    memory that was allocated but not deallocated or vice versa. Whilst not an exact document it
    provides a huge improvement over what currently exists.
  </p>
</section ref=1>

<section ref=2>
  <p>
    This distribution has been developed and tested on 1.1rc only, and is currently coded only to
    work with applications developed using VP itself.
  </p>
  <p>
    <ol>
      <li>/ami/sys/inc/mem_management.inc - the macros
      <li>/ami/sys/utils/mem/report_1.00 - the profile report
    </ol>
    All source files have been compiled with asm -gvO2 <tool>
  </p>
</section ref=2>

<section ref=3>
  <p>
    It first needs to be understood that the memory profiler only works if it is used as the only
    memory model for an application. It works by recording all memory gets and frees and then
    analysing them for anomalies. If it is only half used, it will only provide information about
    what it knows.
  </p>
  <p>
    All transient memory allocations should be made and released using the two macros, ami_get_tmem
    and ami_free_mem. They provide a simple 1 statement method for managing memory resources. Thus
    /ami/sys/inc/mem_management must be included in the source files. They should
    be used as follows; <BR>
    <ul>
      <li>ami_get_tmem size,pointer,flag where <br>
      <ul>
        <li>size - number of bytes required. This can be a constant or variable or indirect
	  pointer. 
        <li>pointer - pointer to the memory. Make sure this is never set to null, as can happen for
	  instance if using lib/strtok or lib/fgets, otherwise it will show up as an anomaly in the profile
	  report.
        <li>flag - ([0 - set memory to nulls],[1 - don't do anything to it])
      </ul>
      <li>ami_free_mem pointer where <br>
      <ul>
        <li>pointer - the pointer of the memory. If a null pointer, this will be reported by the memory
	  profiler
      </ul>
    </ul>
  </p>
  <p>
    To use the profiler properly, points of reference are required in the code. This is achieved via
    the use of an ftrace log. This log provides a set of notifications as execution passes through
    the application. The application developer should make generous usage of the following throughout
    their code as it will be used to work out exactly where a memory get or free has occurred. <br>
    <ol>
      <li>.ifdebug
      <li>  tracef "some text\n"
      <li>.endif
    </ol>
    At the very minimum it is recommended that these are placed at the tops of all
    subroutines and code blocks. 'help tracef' typed at the shell can reveal how to insert run time
    variables into the traces. Do not worry about code bloat. For development, the application should
    always be assembled using 'asm -gvO2 tool.asm'. The -g options is what activates the .ifdebug. To
    remove all the debug information simple assemble using 'asm -vO2 tool.asm'. Checking the binary
    size will lay your mind to rest.
  </p>
  <p>
    When ready to run or test an application, the following process should occur from the shell.<br>
    <ol>
      <li>rm (log file name e.g. /ami/debug/log)
      <li>ftrace (log file name)
      <li>./<main_tool>
    </ol>
  </p>
  <p>
    When the application finishes, the developer can get a full log of the run by typing the following
    at the command line; <br>
    <ul>
      <li>less (log file name)
    </ul>
    As well as all the developers debugs, there will also be lines with <MACRO> in them. These have
    been inserted by the memory profiler. By checking the log against the tool source, it should be
    easy for the developer to see where memory was allocated and freed.
  </p>
  <p>
    To run the memory profiler, the following should be typed at the command line;<br>
    <ol>
      <li>rm (memory profile report file name e.g. /ami/debug/memprof)
      <li>ftrace (memory profile report file name)
      <li>./ami/sys/utils/mem/report_1 (log file name e.g. /ami/debug/log)
      <li>less /ami/debug/memprof
    </ol>
  </p>
  <p>
    The memory profile report provides a list of the number of recorded gets and frees, to see
    if they balance, and then it provides a detailed list of the number of gets and frees made 
    against a single address. It is important to realise that a single address may have many
    gets and frees made against it as the memory is reused. Each memory address usage history
    takes the form of a single line; <br>
    <ul>
      <li>...ADDR=nnnnnnnn (Get gn, Free fn)
    </ul>
    If gn is the same number as fn, then all the memory that was allocated has been freed.
  <p>
    Any mismatches between the number of gets and frees, which could indicate a memory leak
    or pointer error are highlighted in the memory usage section. These can be seen when gn and
    fn are different, and the legend <b>*** MISMATCH ***</b> appears next to the line in
    question.
  </p>
  <p>
    If a mismatch line has (Get 1, Free 0), then discovery is simple. Open up the log file name
    by typing; <br>
    <ul>
      <li>less (log file name)
    </ol>
    and then type '/' followed by the address from the mismatch line (ADDR=nnnnnnnn).  This will cause
    the log to jump to the first occurrence of that address, which will be highlighted. If the developer
    has put good log tracefs into the application, then it will be easy to determine the cause of the memory
    leak.
  </p>
  <p>
    It is more complicated when gn and fn are multiples, for instance (Get 8, Free 7), since this means that there
    were 3 successful get/free pairs and one rogue get. To locate this leak requires the same process being
    undertaken as above, but then press n after the /nnnnnnnn to move to each successive occurrence of the 
    address. The developer will have to ascertain for themselves which of the gets and frees are successful pairs,
    allowing them to narrow down to a single rogue get.
  </p>
  <p>
    Elate does provide a very limited execution tool that provides summary usage which can also be useful;
    To use it, type the following at the command line;<br>
    <ul>
      run -I -m1M (full pathname of the tool)
    </ul>
  </p>
</section ref=3>

<section ref=4>
  <ol>
    <li>When usings the macro ami_get_tmem, beware of using (i_size1+i_size2) and (i_size+5) type expressions
      for the size parameter. I  have successfully used constants, single variables and pointers to sizes
      but the arithmetic expressions seem to cause some issues.
  </ol>
</section ref=4>

</body>

</document>

