rentzsch/mach_star — Issue #30: Performance is slow on Lion 64-bit
Author: krblock
Created: 2012-01-30 18:26:41+00:00
State: open

I recently tried using mach_override.c on Lion 64-bit and the performance was a lot slower than in previous OS versions on 32-bit. Based on some performance measurements I determine that the performance problem was due to a large number of calls to vm_allocate in the following snippet of code from allocateBrandIsland. In previous versions vm_allocate was only called once, but on Lion 64-bit is was called around 64K times.

while( !err && !allocated && page != last ) {

err = vm_allocate( task_self, &page, pageSize, 0 );
if( err == err_none )
allocated = 1;
else if( err == KERN_NO_SPACE ) {
#if defined(__x86_64__)
page -= pageSize;
#else
page += pageSize;
#endif
err = err_none;
}
}

Not sure what the idea solution would be, however, I made two changes that greatly improved performance for me:

1. I cached the last call, if the same "first" address is used, I started at the next available page based on the last call.

2. When not using a cached call, make larger jumps through memory to find an available page quicker.

The changes where the following where COVERITY macro enables the change:

--- 1.15/build/capture/mach-override.c 2012-01-28 12:54:07 -08:00
+++ 1.16/build/capture/mach-override.c 2012-01-28 13:50:08 -08:00
@@ -361,6 +361,11 @@ mach_override_ptr(

************************************************************************
***/

+#if COVERITY
+static vm_address_t lastFunctionAddr = 0;
+static vm_address_t cacheAddrFirst = 0;
+#endif
+
mach_error_t
allocateBranchIsland(
BranchIsland **island,
@@ -389,7 +394,26 @@ allocateBranchIsland(
vm_address_t last = 0xfffe0000;
#endif

+#if COVERITY
+ /* If we are starting from the same address again, skip ahead to where we
+ found the address last time. */
+ int using_cache = FALSE;
+ vm_address_t page;
+ if (lastFunctionAddr == first) {
+ using_cache = TRUE;
+#if defined(__x86_64__)
+ page = cacheAddrFirst - pageSize;
+#else
+ page = cacheAddrFirst + pageSize;
+#endif
+ }
+ else {
+ page = first;
+ }
+#else
vm_address_t page = first;
+#endif
+
int allocated = 0;
vm_map_t task_self = mach_task_self();

@@ -400,15 +424,30 @@ allocateBranchIsland(
allocated = 1;
else if( err == KERN_NO_SPACE ) {
#if defined(__x86_64__)
+#if COVERITY
+ /* If we are not using a cached value, the memory we want could be fa
r away.
+ Take bigger jumps */
+ page -= (using_cache ? pageSize : pageSi
ze*64);
+#else
page -= pageSize;
+#endif
#else
page += pageSize;
#endif
err = err_none;
}
}
+

+#if COVERITY
+ if( allocated ) {
+ lastFunctionAddr = first;
+ cacheAddrFirst = page;
+ *island = (BranchIsland*) page;
+ }
+#else
if( allocated )
*island = (BranchIsland*) page;
+#endif