mirror of
https://github.com/pyenv/pyenv.git
synced 2025-11-14 14:23:53 -05:00
Speed up realpath() with dynamically loaded C extension
On systems that support both C compiling and dynamic loading, we can speed up `realpath()` (where most time in rbenv is spent) by replacing it with a dynamically loaded bash builtin. When `make -C src` is called in the project's root, `libexec/rbenv-realpath.dylib` will be created. If it exists, rbenv will attempt to load it as a builtin command. If it fails, execution will fall back to the old `realpath()` shell function.
This commit is contained in:
10
src/Makefile
Normal file
10
src/Makefile
Normal file
@@ -0,0 +1,10 @@
|
||||
SHOBJ_LDFLAGS = -dynamiclib -current_version 1.0
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
../libexec/rbenv-realpath.dylib: realpath.o
|
||||
$(CC) $(CFLAGS) $(SHOBJ_LDFLAGS) -o $@ realpath.o
|
||||
|
||||
clean:
|
||||
rm -f *.o ../libexec/*.dylib
|
||||
31
src/bash.h
Normal file
31
src/bash.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __BASH_H__
|
||||
#define __BASH_H__
|
||||
|
||||
#define EXECUTION_SUCCESS 0
|
||||
#define EXECUTION_FAILURE 1
|
||||
#define EX_USAGE 258
|
||||
|
||||
#define BUILTIN_ENABLED 1
|
||||
|
||||
typedef struct word_desc {
|
||||
char *word;
|
||||
int flags;
|
||||
} WORD_DESC;
|
||||
|
||||
typedef struct word_list {
|
||||
struct word_list *next;
|
||||
WORD_DESC *word;
|
||||
} WORD_LIST;
|
||||
|
||||
typedef int sh_builtin_func_t(WORD_LIST *);
|
||||
|
||||
struct builtin {
|
||||
char *name;
|
||||
sh_builtin_func_t *function;
|
||||
int flags;
|
||||
char * const *long_doc;
|
||||
const char *short_doc;
|
||||
char *unused;
|
||||
};
|
||||
|
||||
#endif
|
||||
43
src/realpath.c
Normal file
43
src/realpath.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "bash.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int realpath_builtin(list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int es;
|
||||
char *realbuf, *p;
|
||||
|
||||
if (list == 0) {
|
||||
// builtin_usage();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
|
||||
for (es = EXECUTION_SUCCESS; list; list = list->next) {
|
||||
p = list->word->word;
|
||||
realbuf = realpath(p, NULL);
|
||||
if (realbuf == NULL) {
|
||||
es = EXECUTION_FAILURE;
|
||||
// builtin_error("%s: cannot resolve: %s", p, strerror(errno));
|
||||
} else {
|
||||
printf("%s\n", realbuf);
|
||||
free(realbuf);
|
||||
}
|
||||
}
|
||||
return es;
|
||||
}
|
||||
|
||||
char *realpath_doc[] = {
|
||||
"Display each PATHNAME argument, resolving symbolic links. The exit status",
|
||||
"is 0 if each PATHNAME was resolved; non-zero otherwise.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin realpath_struct = {
|
||||
"realpath",
|
||||
realpath_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
realpath_doc,
|
||||
"realpath pathname [pathname...]",
|
||||
0
|
||||
};
|
||||
Reference in New Issue
Block a user