<br><br><div class="gmail_quote">On Tue, Apr 14, 2009 at 10:04 AM, John M McIntosh <span dir="ltr">&lt;<a href="mailto:johnmci@smalltalkconsulting.com">johnmci@smalltalkconsulting.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Yes, so WikiServer  ( <a href="http://www.mobilewikiserver.com" target="_blank">http://www.mobilewikiserver.com</a> ) is an image file of 10.5 MB.<br>
<br>
As startup only 4.5 MB of OOPS memory is faulted in, and about 700K of memory is altered, which reduces initial memory use by 6MB and reduces the startup time by 3+ seconds.<br>
Given the slow speed of the iPhone, and the fact I&#39;ve a 64MB limit, 6MB is a lot, and 3 seconds is welcome. Unfortunately a full GC will fault all that 10.5 MB in, however by doing some GC tuning one<br>
can avoid a full GC until things are quite stressed.<br>
<br>
I note on os-x desktop machines the entire 10.5MB is read in and the pages marked as non-referenced, but obviously the rules for the virtual memory subsystem are different.<br>
<br>
<br>
First let me suggest we change<br>
<br>
writeImageFileIO<br>
<br>
<br>
        /* header size in bytes; do not change! */<br>
<br>
        headerSize = 64;<br>
        f = sqImageFileOpen(imageName, &quot;wb&quot;);<br>
<br>
<br>
from 64 bytes to 4096 bytes, if possible.<br>
<br>
Now let&#39;s explore why, and what is going on.<br>
<br>
on unix if you decide to use mmap versus malloc to allocate storage for oops space it does<br>
<br>
#define MAP_PROT        (PROT_READ | PROT_WRITE)<br>
#define MAP_FLAGS       (MAP_ANON | MAP_PRIVATE)<br>
 mmap(0, heapLimit, MAP_PROT, MAP_FLAGS, devZero, 0)<br>
<br>
<br>
where heapLimit is usually 1GB, start location zero.<br>
<br>
This returns a start location somewhere in memory, never zero, and generally we have to swizzle all the object pointer. On a save and restart of the squeak app the address<br>
you get back *maybe* the same address, if it is the same we don&#39;t need to swizzle pointers, however OpenBSD based systems likely will always give a different location for security reasons.<br>
<br>
I had then set a start location of 128MB, but found on os-x as the number of apps goes up you don&#39;t get 128MB, so I settled on 500MB which<br>
seems ok. 8GB pro macs running 52 applications fail at 500MB, but the failure is it chooses it&#39;s own address, so we don&#39;t care...<br>
<br>
Well yes that limits your squeak image to 3.5GB but it&#39;s doubtful that a 32bit system will let you allocate a contiguous chunk of memory &gt; 2 GB anyway.<br>
<br>
Now the next issue was the original memory allocation logic would give you the 1GB, and you would read the entire image into that memory area.<br>
<br>
In thinking about this I thought why can&#39;t you mmap to the image file for the size of the file rounded up to the page size, then mmap after that memory<br>
to anonymous memory upto the desired heapsize.<br>
<br>
So two mmaps, one for the file, followed by another for young space.<br>
<br>
I implemented this for the os-x vm and the iPhone VM.<br>
<br>
In testing with a 500 Mhz powerpc laptop, I found the startup time was reduced by 30% because it would fault in say a 20MB page by page as it did the<br>
needless flush primitive calls logic, versus reading the 20mb into memory, the virtual memory pager was just more efficient at pullling in the data either by better<br>
I/O processing, or faster logic in finding the free pages.<br>
<br>
Problems:<br>
<br>
It turns out there is a flaw in the OS-X BSD mmap logic when you mmap files on NFS drives, it hangs, and some people with I think overstressed systems reported issues with the first mmap failing.<br>
Because of this I reverted back to the old logic by default, and put a flag in the info.plist SqueakUseFileMappedMMAP to enable the new logic.<br>
Obviously for Linux you have to decide if this flaw exists and has not been fixed?<br>
<br>
Now the problem with headerSize<br>
<br>
In the file mmap case the entire file is mapped into memory at 500MB, but the oops space starts at 64 bytes, so memory is at 500MB+64<br>
In the anonymous mmap case memory starts at 500MB, but the oops space starts at 0, so memory is at 500MB.</blockquote><div><br></div><div>John, I think this is a non-issue.  There is no reason to worry about the unused 64 bytes at the beginning of the image file.  Simply map it at 500Mb and have the heap start at 500Mb + 64.  So the header is mapped into memory.  This should make snapshot a little easier because one simply updates the header in place in memory.</div>
<div><br></div><div>In any case you&#39;re never going to find an ideal header size.  Some systems have very large page sizes and it would be silly to choose a header as large as, say, 1Mb.  Better to keep it on the small side and map it into memory where it won&#39;t be a problem.</div>
<div><br></div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">If the headersize was 4096 we could mmap the file at 500MB-4096,<br>
Or alter the anonymous case we could allocate at 500MB but stick the oops space at 500MB +64 (header size).<br>
<br>
However by using a headerSize of 4096 we can then get the oops space to start on a page boundary, which may or may not have implications.</blockquote><div><br></div><div>Nah.  64 bytes beyond a page boundary for the first few objects won&#39;t make any difference.   Don&#39;t sweat it.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>
Anyway it would be good to resolve this bit of tricky logic.<br>
<br>
I stuck the following code into ioRelinquishProcessorForMicroseconds() since ioRelinquishProcessorForMicroseconds will only get triggered once the<br>
image finishes all it&#39;s startup logic and becomes *idle*. So that I could determine how each page was viewed by the virtual memory subsystem.<br>
<br>
<br>
xtern unsigned char *memory;<br>
        extern usqInt   sqGetAvailableMemory();<br>
        extern size_t fileRoundedUpToPageSize;<br>
        size_t pageSize= getpagesize();<br>
        size_t vmpagesize=sqGetAvailableMemory()/pageSize + 1;<br>
        char *what = malloc(vmpagesize);<br>
        int err = mincore(memory, sqGetAvailableMemory(), what);<br>
        int countRef=0, countMod=0,countZero=0, countOne=0, i;<br>
        for (i=0;i&lt;fileRoundedUpToPageSize/pageSize;i++) {<br>
                if(what[i] == 0) countZero++;<br>
                if(what[i] == 1) countOne++;<br>
                if(what[i] == 3) countRef++;<br>
                if(what[i] == 7) countMod++;<br>
                {break for debugging here}<br>
        }<br>
                                                <br>
        free(what);<div><div></div><div class="h5"><br>
<br>
<br>
<br>
<br>
On 14-Apr-09, at 1:58 AM, Bert Freudenberg wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
On 14.04.2009, at 07:26, John M McIntosh wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I created a pharo entry to track the problem the VM &amp; image has in wanting to visit every smalltalk object multiple times at startup time.<br>
Athought this behavior is masked by Gigaherz processors, it&#39;s very evident as a problem on the iPhone. Fixing it results in reducing<br>
MB of RAM memory usage and saves actual &quot;seconds* of clock time at startup.<br>
<br>
<a href="http://code.google.com/p/pharo/issues/detail?id=737&amp;colspec=ID%20Type%20Status%20Summary%20Milestone&amp;start=200" target="_blank">http://code.google.com/p/pharo/issues/detail?id=737&amp;colspec=ID%20Type%20Status%20Summary%20Milestone&amp;start=200</a><br>

</blockquote>
<br>
Very nice. We experimented in that direction for OLPC which also is comparatively slow CPU wise, and even slower loading the whole image from the flash disk (which involves decompressing). Mmapping only the pages needed should give a considerable boost.<br>

<br>
Do we have evidence that an mmap base address of 500 MB works across platforms?<br>
<br>
- Bert -<br>
<br>
</blockquote>
<br></div></div><div><div></div><div class="h5">
--<br>
===========================================================================<br>
John M. McIntosh &lt;<a href="mailto:johnmci@smalltalkconsulting.com" target="_blank">johnmci@smalltalkconsulting.com</a>&gt;<br>
Corporate Smalltalk Consulting Ltd.  <a href="http://www.smalltalkconsulting.com" target="_blank">http://www.smalltalkconsulting.com</a><br>
===========================================================================<br>
<br>
<br>
<br>
<br>
</div></div></blockquote></div><br>