darwin: speed up uv_set_process_title()

Libuv loaded and unloaded the Core Services and Application Services for
every call to uv_set_process_title().

Change that to load them on the first call to uv_set_process_title() and
delay unloading until libuv is unloaded.

Speeds up process_title_threadsafe by about 10x on my system. It should
fail less often (hopefully not at all) on the CI now.

PR-URL: https://github.com/libuv/libuv/pull/2480
Reviewed-By: Saúl Ibarra Corretgé <s@saghul.net>
This commit is contained in:
Ben Noordhuis 2019-10-08 12:47:16 +02:00
parent e83dba7f93
commit 038eacfbf4
3 changed files with 78 additions and 86 deletions

View File

@ -33,61 +33,57 @@
# include <ApplicationServices/ApplicationServices.h>
#endif
#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
static int uv__pthread_setname_np(const char* name) {
int (*dynamic_pthread_setname_np)(const char* name);
char namebuf[64]; /* MAXTHREADNAMESIZE */
int err;
static int (*dynamic_pthread_setname_np)(const char* name);
#if !TARGET_OS_IPHONE
static CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
const char*,
CFStringEncoding);
static CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
static void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
static void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
static CFTypeRef (*pLSGetCurrentApplicationASN)(void);
static OSStatus (*pLSSetApplicationInformationItem)(int,
CFTypeRef,
CFStringRef,
CFStringRef,
CFDictionaryRef*);
static void* application_services_handle;
static void* core_foundation_handle;
static CFBundleRef launch_services_bundle;
static CFStringRef* display_name_key;
static CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
static CFBundleRef (*pCFBundleGetMainBundle)(void);
static CFBundleRef hi_services_bundle;
static CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
static void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
void*);
UV_DESTRUCTOR(static void uv__set_process_title_platform_fini(void)) {
if (core_foundation_handle != NULL) {
dlclose(core_foundation_handle);
core_foundation_handle = NULL;
}
if (application_services_handle != NULL) {
dlclose(application_services_handle);
application_services_handle = NULL;
}
}
#endif /* !TARGET_OS_IPHONE */
void uv__set_process_title_platform_init(void) {
OSStatus (*pSetApplicationIsDaemon)(int);
/* pthread_setname_np() first appeared in OS X 10.6 and iOS 3.2. */
*(void **)(&dynamic_pthread_setname_np) =
dlsym(RTLD_DEFAULT, "pthread_setname_np");
if (dynamic_pthread_setname_np == NULL)
return UV_ENOSYS;
strncpy(namebuf, name, sizeof(namebuf) - 1);
namebuf[sizeof(namebuf) - 1] = '\0';
err = dynamic_pthread_setname_np(namebuf);
if (err)
return UV__ERR(err);
return 0;
}
int uv__set_process_title(const char* title) {
#if TARGET_OS_IPHONE
return uv__pthread_setname_np(title);
#else
CFStringRef (*pCFStringCreateWithCString)(CFAllocatorRef,
const char*,
CFStringEncoding);
CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef);
void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef);
void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef);
CFTypeRef (*pLSGetCurrentApplicationASN)(void);
OSStatus (*pLSSetApplicationInformationItem)(int,
CFTypeRef,
CFStringRef,
CFStringRef,
CFDictionaryRef*);
void* application_services_handle;
void* core_foundation_handle;
CFBundleRef launch_services_bundle;
CFStringRef* display_name_key;
CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef);
CFBundleRef (*pCFBundleGetMainBundle)(void);
CFBundleRef hi_services_bundle;
OSStatus (*pSetApplicationIsDaemon)(int);
CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef);
void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t,
void*);
CFTypeRef asn;
int err;
err = UV_ENOENT;
#if !TARGET_OS_IPHONE
application_services_handle = dlopen("/System/Library/Frameworks/"
"ApplicationServices.framework/"
"Versions/A/ApplicationServices",
@ -116,8 +112,6 @@ int uv__set_process_title(const char* title) {
goto out;
}
#define S(s) pCFStringCreateWithCString(NULL, (s), kCFStringEncodingUTF8)
launch_services_bundle =
pCFBundleGetBundleWithIdentifier(S("com.apple.LaunchServices"));
@ -148,13 +142,14 @@ int uv__set_process_title(const char* title) {
"CFBundleGetInfoDictionary");
*(void **)(&pCFBundleGetMainBundle) = dlsym(core_foundation_handle,
"CFBundleGetMainBundle");
if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL)
goto out;
/* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */
hi_services_bundle =
pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices"));
err = UV_ENOENT;
if (hi_services_bundle == NULL)
goto out;
@ -168,42 +163,39 @@ int uv__set_process_title(const char* title) {
pCFBundleGetFunctionPointerForName(
launch_services_bundle,
S("_LSSetApplicationLaunchServicesServerConnectionStatus"));
if (pSetApplicationIsDaemon == NULL ||
pLSApplicationCheckIn == NULL ||
pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) {
goto out;
}
if (pSetApplicationIsDaemon(1) != noErr)
goto out;
pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
/* Check into process manager?! */
pLSApplicationCheckIn(-2,
pCFBundleGetInfoDictionary(pCFBundleGetMainBundle()));
asn = pLSGetCurrentApplicationASN();
err = UV_EINVAL;
if (pLSSetApplicationInformationItem(-2, /* Magic value. */
asn,
*display_name_key,
S(title),
NULL) != noErr) {
goto out;
}
uv__pthread_setname_np(title); /* Don't care if it fails. */
err = 0;
/* Prevent crash when LaunchServices cannot be connected to. */
pSetApplicationIsDaemon(1);
return;
out:
if (core_foundation_handle != NULL)
dlclose(core_foundation_handle);
if (application_services_handle != NULL)
dlclose(application_services_handle);
return err;
uv__set_process_title_platform_fini();
#endif /* !TARGET_OS_IPHONE */
}
void uv__set_process_title(const char* title) {
#if !TARGET_OS_IPHONE
if (core_foundation_handle != NULL) {
CFTypeRef asn;
pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL);
pLSApplicationCheckIn(/* Magic value */ -2,
pCFBundleGetInfoDictionary(pCFBundleGetMainBundle()));
asn = pLSGetCurrentApplicationASN();
pLSSetApplicationInformationItem(/* Magic value */ -2, asn,
*display_name_key, S(title), NULL);
}
#endif /* !TARGET_OS_IPHONE */
if (dynamic_pthread_setname_np != NULL) {
char namebuf[64]; /* MAXTHREADNAMESIZE */
uv__strscpy(namebuf, title, sizeof(namebuf));
dynamic_pthread_setname_np(namebuf);
}
}

View File

@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
extern void uv__set_process_title_platform_init(void);
extern void uv__set_process_title(const char* title);
static uv_mutex_t process_title_mutex;
@ -38,6 +39,9 @@ static struct {
static void init_process_title_mutex_once(void) {
uv_mutex_init(&process_title_mutex);
#ifdef __APPLE__
uv__set_process_title_platform_init();
#endif
}

View File

@ -25,11 +25,7 @@
#include <string.h>
#ifdef __APPLE__
# define NUM_ITERATIONS 10
#else
#define NUM_ITERATIONS 50
#endif
static const char* titles[] = {
"8L2NY0Kdj0XyNFZnmUZigIOfcWjyNr0SkMmUhKw99VLUsZFrvCQQC3XIRfNR8pjyMjXObllled",