comparison ALmixer.c @ 24:e085cbc573cf

iOS optimization/bug/workaround. It seems that usleep(10) is paradoxically causing the background thread to hog a bunch of CPU on iOS. (I don't see this on Mac.) Increasing the time to about 60 seems to start helping. More so at 100, but I began to worry about sleeping to long. So instead I have an evil hack to change the thread priority for just iOS. (In theory, this approach can be applied to other platforms, but it is risky to muck with this.) Since SDL_thread doesn't have a priortiy API, I do some evil pointer math to get the pthread so I can call pthread_setschedparam. If SDL changes the implementation of SDL_thread including the structure layout, this will completely break.
author Eric Wing <ewing . public |-at-| gmail . com>
date Fri, 24 Dec 2010 03:32:02 -0800
parents 58f03008ea05
children 46e82b415520
comparison
equal deleted inserted replaced
23:ee96f91ba887 24:e085cbc573cf
338 #include "SDL.h" /* For SDL_GetTicks(), SDL_Delay */ 338 #include "SDL.h" /* For SDL_GetTicks(), SDL_Delay */
339 #define ALmixer_GetTicks SDL_GetTicks 339 #define ALmixer_GetTicks SDL_GetTicks
340 #define ALmixer_Delay SDL_Delay 340 #define ALmixer_Delay SDL_Delay
341 #endif 341 #endif
342 342
343 343 /* On iOS, usleep() of small numbers (say less than 100, very pronounced from 0-50)
344 * seems to be sucking up quite a bit of CPU time and causing performance problems.
345 * Instead of increasing the sleep time, I started changing the thread priority.
346 * This seemed to help the problem.
347 * Experimentally, the default priority seems to be 31. According to the docs,
348 * valid ranges are from 0 to 31. 6 was still giving me some hiccups so setting to
349 * 0 (PTHREAD_MIN_PRIORITY) seems to be the best value so far.
350 * Mac also reports 31 as the default. However, I have not noticed the same
351 * performance problems and cannot get audio to show up as a significant percentage
352 * of the CPU time in Shark/Instruments.
353 */
354 #if defined(__APPLE__) && !defined(ALMIXER_COMPILE_WITHOUT_SDL) && ( (TARGET_OS_IPHONE == 1) || (TARGET_IPHONE_SIMULATOR == 1) )
355 #include <pthread.h>
356 #endif
357 static void Internal_LowerThreadPriority(SDL_Thread* simple_thread)
358 {
359 /* Might open to other platforms as needed */
360 #if defined(__APPLE__) && ( (TARGET_OS_IPHONE == 1) || (TARGET_IPHONE_SIMULATOR == 1) )
361 #ifdef ALMIXER_COMPILE_WITHOUT_SDL
362 SimpleThread_SetThreadPriority(Stream_Thread_global, 0);
363 #else
364 struct sched_param schedule_param;
365 int sched_policy;
366 int ret_val;
367 schedule_param.sched_priority = 0; /* PTHREAD_MIN_PRIORITY, max=31 */
368 /* EVIL! This will break if the SDL_Thread structure layout changes. */
369 pthread_t* native_thread_ptr_hack = (pthread_t*)(((char*)(Stream_Thread_global))+sizeof(unsigned long));
370 ret_val = pthread_setschedparam(*native_thread_ptr_hack, SCHED_OTHER, &schedule_param);
371 #endif
372 #else
373 /* No-Op */
374 #endif
375 }
344 376
345 /* If ENABLE_PARANOID_SIGNEDNESS_CHECK is used, 377 /* If ENABLE_PARANOID_SIGNEDNESS_CHECK is used,
346 * these values will be reset on Init() 378 * these values will be reset on Init()
347 * Consider these values Read-Only. 379 * Consider these values Read-Only.
348 */ 380 */
753 785
754 return Compute_Total_Time_Decomposed(bytes_per_sample, info->rate, info->channels, total_bytes); 786 return Compute_Total_Time_Decomposed(bytes_per_sample, info->rate, info->channels, total_bytes);
755 } /* End Compute_Total_Time */ 787 } /* End Compute_Total_Time */
756 788
757 789
790 #ifdef ALMIXER_DISABLE_PREDECODED_PRECOMPUTE_BUFFER_SIZE_OPTIMIZATION
758 static size_t Compute_Total_Bytes_Decomposed(ALuint bytes_per_sample, ALuint frequency, ALubyte channels, ALuint total_msec) 791 static size_t Compute_Total_Bytes_Decomposed(ALuint bytes_per_sample, ALuint frequency, ALubyte channels, ALuint total_msec)
759 { 792 {
760 double total_sec; 793 double total_sec;
761 ALuint bytes_per_sec; 794 ALuint bytes_per_sec;
762 size_t total_bytes; 795 size_t total_bytes;
799 */ 832 */
800 bytes_per_sample = (ALuint) ((info->format & 0xFF) / 8); 833 bytes_per_sample = (ALuint) ((info->format & 0xFF) / 8);
801 834
802 return Compute_Total_Bytes_Decomposed(bytes_per_sample, info->rate, info->channels, total_msec); 835 return Compute_Total_Bytes_Decomposed(bytes_per_sample, info->rate, info->channels, total_msec);
803 } 836 }
837
804 838
805 /* The back-end decoders seem to need to decode in quantized frame sizes. 839 /* The back-end decoders seem to need to decode in quantized frame sizes.
806 * So if I can pad the bytes to the next quanta, things might go more smoothly. 840 * So if I can pad the bytes to the next quanta, things might go more smoothly.
807 */ 841 */
808 static size_t Compute_Total_Bytes_With_Frame_Padding(Sound_AudioInfo *info, ALuint total_msec) 842 static size_t Compute_Total_Bytes_With_Frame_Padding(Sound_AudioInfo *info, ALuint total_msec)
839 */ 873 */
840 /* 874 /*
841 fprintf(stderr, "remainder_frames=%d, padded_total_bytes=%d\n", remainder_frames, return_bytes); 875 fprintf(stderr, "remainder_frames=%d, padded_total_bytes=%d\n", remainder_frames, return_bytes);
842 */ 876 */
843 return return_bytes; 877 return return_bytes;
844 878 }
845 } 879 #endif /* ALMIXER_DISABLE_PREDECODED_PRECOMPUTE_BUFFER_SIZE_OPTIMIZATION */
846
847 880
848 881
849 882
850 /**************** REMOVED ****************************/ 883 /**************** REMOVED ****************************/
851 /* This was removed because I originally thought 884 /* This was removed because I originally thought
3403 static ALint Internal_FadeInChannelTimed(ALint channel, ALmixer_Data* data, ALint loops, ALuint fade_ticks, ALint expire_ticks) 3436 static ALint Internal_FadeInChannelTimed(ALint channel, ALmixer_Data* data, ALint loops, ALuint fade_ticks, ALint expire_ticks)
3404 { 3437 {
3405 ALfloat value; 3438 ALfloat value;
3406 ALenum error; 3439 ALenum error;
3407 ALfloat original_value; 3440 ALfloat original_value;
3408 ALuint current_time = ALmixer_GetTicks(); 3441 /* ALuint current_time = ALmixer_GetTicks(); */
3409 ALint retval; 3442 ALint retval;
3410 3443
3411 3444
3412 3445
3413 if(channel >= Number_of_Channels_global) 3446 if(channel >= Number_of_Channels_global)
6739 alcCloseDevice(dev); 6772 alcCloseDevice(dev);
6740 ALmixer_Initialized = 0; 6773 ALmixer_Initialized = 0;
6741 Number_of_Channels_global = 0; 6774 Number_of_Channels_global = 0;
6742 return AL_FALSE; 6775 return AL_FALSE;
6743 } 6776 }
6777
6778 /* Note: Only a few platforms change the priority. See implementation for notes. */
6779 Internal_LowerThreadPriority(Stream_Thread_global);
6744 6780
6745 /* 6781 /*
6746 fprintf(stderr, "Using threads\n"); 6782 fprintf(stderr, "Using threads\n");
6747 */ 6783 */
6748 #endif /* End of ENABLE_ALMIXER_THREADS */ 6784 #endif /* End of ENABLE_ALMIXER_THREADS */
7289 free(Source_Map_List); 7325 free(Source_Map_List);
7290 ALmixer_Initialized = 0; 7326 ALmixer_Initialized = 0;
7291 Number_of_Channels_global = 0; 7327 Number_of_Channels_global = 0;
7292 return AL_FALSE; 7328 return AL_FALSE;
7293 } 7329 }
7294 7330
7331 /* Note: Only a few platforms change the priority. See implementation for notes. */
7332 Internal_LowerThreadPriority(Stream_Thread_global);
7333
7295 /* 7334 /*
7296 fprintf(stderr, "Using threads\n"); 7335 fprintf(stderr, "Using threads\n");
7297 */ 7336 */
7298 #endif /* End of ENABLE_ALMIXER_THREADS */ 7337 #endif /* End of ENABLE_ALMIXER_THREADS */
7299 7338