[systemd-devel] [PATCH 1/2] RFC: util: Avoid memory allocations for formatting paths
Holger Freyther
holger at freyther.de
Tue Apr 2 13:35:50 PDT 2013
From: Holger Hans Peter Freyther <holger at moiji-mobile.com>
Avoid memory allocations to construct the path for files in the
procfs. The procfs paths are way shorter than the PATH_MAX so we
can use snprintf on a string located on the stack. This shows up
as a win on x86 using the benchmark program below.
$ make libsystemd-shared.la; gcc -O2 -Isrc/systemd/ -Isrc/ \
-o simple-perf-test simple-perf-test.c \
.libs/libsystemd-shared.a -lrt
#include "shared/util.h"
void test_once(void) {
pid_t pid = getpid();
char *tmp = NULL;
get_process_comm(pid, &tmp);
free(tmp);
tmp = NULL;
get_process_cmdline(pid, 0, 1, &tmp);
free(tmp);
is_kernel_thread(pid);
tmp = NULL;
get_process_exe(pid, &tmp);
free(tmp);
}
int main(int argc, char **argv)
{
int i;
for (i = 0; i < 50000; ++i)
test_once();
}
---
src/shared/util.c | 48 +++++++++++++++++++-----------------------------
1 file changed, 19 insertions(+), 29 deletions(-)
diff --git a/src/shared/util.c b/src/shared/util.c
index b516b9b..ce8f866 100644
--- a/src/shared/util.c
+++ b/src/shared/util.c
@@ -567,6 +567,10 @@ char *truncate_nl(char *s) {
return s;
}
+#define format_procfs_path(buffer, path, pid) \
+ snprintf(buffer, sizeof(buffer) - 1, "/proc/%lu/%s", (unsigned long) pid, path); \
+ char_array_0(buffer);
+
int get_process_comm(pid_t pid, char **name) {
int r;
@@ -575,12 +579,9 @@ int get_process_comm(pid_t pid, char **name) {
if (pid == 0)
r = read_one_line_file("/proc/self/comm", name);
else {
- char *p;
- if (asprintf(&p, "/proc/%lu/comm", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- r = read_one_line_file(p, name);
- free(p);
+ char path[PATH_MAX];
+ format_procfs_path(path, "comm", pid);
+ r = read_one_line_file(path, name);
}
return r;
@@ -596,12 +597,9 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
if (pid == 0)
f = fopen("/proc/self/cmdline", "re");
else {
- char *p;
- if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
- free(p);
+ char path[PATH_MAX];
+ format_procfs_path(path, "cmdline", pid);
+ f = fopen(path, "re");
}
if (!f)
@@ -688,7 +686,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
}
int is_kernel_thread(pid_t pid) {
- char *p;
+ char path[PATH_MAX];
size_t count;
char c;
bool eof;
@@ -697,11 +695,8 @@ int is_kernel_thread(pid_t pid) {
if (pid == 0)
return 0;
- if (asprintf(&p, "/proc/%lu/cmdline", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
- free(p);
+ format_procfs_path(path, "cmdline", pid);
+ f = fopen(path, "re");
if (!f)
return -errno;
@@ -726,12 +721,9 @@ int get_process_exe(pid_t pid, char **name) {
if (pid == 0)
r = readlink_malloc("/proc/self/exe", name);
else {
- char *p;
- if (asprintf(&p, "/proc/%lu/exe", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- r = readlink_malloc(p, name);
- free(p);
+ char path[PATH_MAX];
+ format_procfs_path(path, "exe", pid);
+ r = readlink_malloc(path, name);
}
return r;
@@ -739,7 +731,7 @@ int get_process_exe(pid_t pid, char **name) {
static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
_cleanup_fclose_ FILE *f = NULL;
- _cleanup_free_ char *p = NULL;
+ char path[PATH_MAX];
char line[LINE_MAX];
assert(field);
@@ -748,10 +740,8 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
if (pid == 0)
return getuid();
- if (asprintf(&p, "/proc/%lu/status", (unsigned long) pid) < 0)
- return -ENOMEM;
-
- f = fopen(p, "re");
+ format_procfs_path(path, "status", pid);
+ f = fopen(path, "re");
if (!f)
return -errno;
--
1.7.10.4
More information about the systemd-devel
mailing list