Skip to content

Commit 863fd5b

Browse files
committed
Optimize path_is_media_type - up to 6x speed improvement
1 parent e79dfcc commit 863fd5b

File tree

1 file changed

+52
-13
lines changed

1 file changed

+52
-13
lines changed

retroarch.c

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2759,23 +2759,63 @@ static void ram_state_to_file(void)
27592759
command_event(CMD_EVENT_RAM_STATE_TO_FILE, state_path);
27602760
}
27612761

2762+
/**
2763+
* Compute DJB2 hash of a short string, lowercasing ASCII on the fly.
2764+
* Assumes ext points to a valid, short (extension-length) string.
2765+
*/
2766+
static INLINE uint32_t djb2_calculate_lower(const char *s)
2767+
{
2768+
uint32_t h = 5381;
2769+
for (; *s; s++)
2770+
{
2771+
unsigned char c = (unsigned char)*s;
2772+
/* Branchless ASCII tolower: set bit 5 if uppercase letter */
2773+
c |= ((unsigned int)c - 'A' < 26u) ? 0x20 : 0x00;
2774+
h = (h << 5) + h + c;
2775+
}
2776+
return h;
2777+
}
2778+
27622779
enum rarch_content_type path_is_media_type(const char *path)
27632780
{
2764-
char ext_lower[16];
2765-
strlcpy(ext_lower, path_get_extension(path), sizeof(ext_lower));
2781+
const char *ext;
2782+
2783+
if (!path || !*path)
2784+
return RARCH_CONTENT_NONE;
27662785

2767-
string_to_lower(ext_lower);
2786+
/* Fast streaming-protocol check: switch on first char to avoid
2787+
* testing all prefixes linearly. Only fall through on match. */
2788+
switch (path[0])
2789+
{
2790+
case 'u':
2791+
if (string_starts_with_size(path, "udp://", STRLEN_CONST("udp://")))
2792+
return RARCH_CONTENT_MOVIE;
2793+
break;
2794+
case 'h':
2795+
if ( string_starts_with_size(path, "http://", STRLEN_CONST("http://"))
2796+
|| string_starts_with_size(path, "https://", STRLEN_CONST("https://")))
2797+
return RARCH_CONTENT_MOVIE;
2798+
break;
2799+
case 't':
2800+
if (string_starts_with_size(path, "tcp://", STRLEN_CONST("tcp://")))
2801+
return RARCH_CONTENT_MOVIE;
2802+
break;
2803+
case 'r':
2804+
if ( string_starts_with_size(path, "rtmp://", STRLEN_CONST("rtmp://"))
2805+
|| string_starts_with_size(path, "rtp://", STRLEN_CONST("rtp://")))
2806+
return RARCH_CONTENT_MOVIE;
2807+
break;
2808+
default:
2809+
break;
2810+
}
27682811

2769-
/* hack, to detect livestreams so the ffmpeg core can be started */
2770-
if ( string_starts_with_size(path, "udp://", STRLEN_CONST("udp://"))
2771-
|| string_starts_with_size(path, "http://", STRLEN_CONST("http://"))
2772-
|| string_starts_with_size(path, "https://", STRLEN_CONST("https://"))
2773-
|| string_starts_with_size(path, "tcp://", STRLEN_CONST("tcp://"))
2774-
|| string_starts_with_size(path, "rtmp://", STRLEN_CONST("rtmp://"))
2775-
|| string_starts_with_size(path, "rtp://", STRLEN_CONST("rtp://")))
2776-
return RARCH_CONTENT_MOVIE;
2812+
ext = path_get_extension(path);
2813+
if (!ext || !*ext)
2814+
return RARCH_CONTENT_NONE;
27772815

2778-
switch (msg_hash_to_file_type(msg_hash_calculate(ext_lower)))
2816+
/* Hash the extension directly, lowercasing during hashing —
2817+
* eliminates strlcpy, string_to_lower, and the stack buffer. */
2818+
switch (msg_hash_to_file_type(djb2_calculate_lower(ext)))
27792819
{
27802820
#if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
27812821
case FILE_TYPE_OGM:
@@ -2831,7 +2871,6 @@ enum rarch_content_type path_is_media_type(const char *path)
28312871
case FILE_TYPE_BMP:
28322872
return RARCH_CONTENT_IMAGE;
28332873
#endif
2834-
case FILE_TYPE_NONE:
28352874
default:
28362875
break;
28372876
}

0 commit comments

Comments
 (0)