Skip to content

Commit

Permalink
darwin: speed up uv_set_process_title()
Browse files Browse the repository at this point in the history
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.

PR-URL: libuv#2064
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
  • Loading branch information
bnoordhuis committed Nov 4, 2018
1 parent e94c184 commit 00c6b16
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 84 deletions.
148 changes: 69 additions & 79 deletions src/unix/darwin-proctitle.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,61 +33,56 @@
# 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;

/* 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);
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 OSStatus (*pSetApplicationIsDaemon)(int);
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;
}

return 0;
if (application_services_handle != NULL) {
dlclose(application_services_handle);
application_services_handle = NULL;
}
}
#endif /* !TARGET_OS_IPHONE */


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;
void uv__set_process_title_platform_init(void) {
/* 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 !TARGET_OS_IPHONE
application_services_handle = dlopen("/System/Library/Frameworks/"
"ApplicationServices.framework/"
"Versions/A/ApplicationServices",
Expand Down Expand Up @@ -116,8 +111,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"));

Expand Down Expand Up @@ -148,13 +141,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;

Expand All @@ -168,42 +162,38 @@ 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;
return;

out:
if (core_foundation_handle != NULL)
dlclose(core_foundation_handle);
uv__set_process_title_platform_fini();
#endif /* !TARGET_OS_IPHONE */
}

if (application_services_handle != NULL)
dlclose(application_services_handle);

return err;
void uv__set_process_title(const char* title) {
#if !TARGET_OS_IPHONE
if (core_foundation_handle != NULL && pSetApplicationIsDaemon(1) != noErr) {
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 */
strncpy(namebuf, title, sizeof(namebuf) - 1);
namebuf[sizeof(namebuf) - 1] = '\0';
dynamic_pthread_setname_np(namebuf);
}
}
4 changes: 4 additions & 0 deletions src/unix/proctitle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
}


Expand Down
6 changes: 1 addition & 5 deletions test/test-process-title-threadsafe.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@

#include <string.h>

#ifdef __APPLE__
# define NUM_ITERATIONS 10
#else
# define NUM_ITERATIONS 50
#endif
#define NUM_ITERATIONS 50

static const char* titles[] = {
"8L2NY0Kdj0XyNFZnmUZigIOfcWjyNr0SkMmUhKw99VLUsZFrvCQQC3XIRfNR8pjyMjXObllled",
Expand Down

0 comments on commit 00c6b16

Please sign in to comment.