Mercurial > almixer_isolated
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 |