X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=OSX%2FXScreenSaverView.m;h=7173d86d21700531e430bf370448cf25cf8ee017;hb=50be9bb40dc60130c99ffa568e6677779904ff70;hp=d483c8885ce70cd5de654ca2d7abd98143aea8c4;hpb=3243731044b944673630b55e16674c191b026f84;p=xscreensaver diff --git a/OSX/XScreenSaverView.m b/OSX/XScreenSaverView.m index d483c888..7173d86d 100644 --- a/OSX/XScreenSaverView.m +++ b/OSX/XScreenSaverView.m @@ -1,4 +1,4 @@ -/* xscreensaver, Copyright (c) 2006-2009 Jamie Zawinski +/* xscreensaver, Copyright (c) 2006-2010 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -21,6 +21,17 @@ #import "xlockmoreI.h" #import "jwxyz-timers.h" +/* Garbage collection only exists if we are being compiled against the + 10.6 SDK or newer, not if we are building against the 10.4 SDK. + */ +#ifndef MAC_OS_X_VERSION_10_6 +# define MAC_OS_X_VERSION_10_6 1060 /* undefined in 10.4 SDK, grr */ +#endif +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 /* 10.6 SDK */ +# import +# define DO_GC_HACKERY +#endif + extern struct xscreensaver_function_table *xscreensaver_function_table; /* Global variables used by the screen savers @@ -53,6 +64,7 @@ int mono_p = 0; void *addr = CFBundleGetDataPointerForName (cfb, (CFStringRef) table_name); NSAssert2 (addr, @"no symbol \"%@\" in bundle %@", table_name, path); + CFRelease (cfb); // NSLog (@"%@ = 0x%08X", table_name, (unsigned long) addr); return (struct xscreensaver_function_table *) addr; @@ -133,6 +145,7 @@ add_default_options (const XrmOptionDescRec *opts, }; static const char *default_defaults [] = { ".doFPS: False", + ".doubleBuffer: True", // for most OpenGL hacks ".textMode: date", // ".textLiteral: ", // ".textFile: ", @@ -430,6 +443,37 @@ screenhack_do_fps (Display *dpy, Window w, fps_state *fpst, void *closure) gettimeofday (&tv, 0); now = tv.tv_sec + (tv.tv_usec / 1000000.0); next_frame_time = now + (delay / 1000000.0); + + +# ifdef DO_GC_HACKERY + /* Current theory is that the 10.6 garbage collector sucks in the + following way: + + It only does a collection when a threshold of outstanding + collectable allocations has been surpassed. However, CoreGraphics + creates lots of small collectable allocations that contain pointers + to very large non-collectable allocations: a small CG object that's + collectable referencing large malloc'd allocations (non-collectable) + containing bitmap data. So the large allocation doesn't get freed + until GC collects the small allocation, which triggers its finalizer + to run which frees the large allocation. So GC is deciding that it + doesn't really need to run, even though the process has gotten + enormous. GC eventually runs once pageouts have happened, but by + then it's too late, and the machine's resident set has been + sodomized. + + So, we force an exhaustive garbage collection in this process + approximately every 5 seconds whether the system thinks it needs + one or not. + */ + { + static int tick = 0; + if (++tick > 5*30) { + tick = 0; + objc_collect (OBJC_EXHAUSTIVE_COLLECTION); + } + } +# endif // DO_GC_HACKERY }