mirror of
https://github.com/pyenv/pyenv.git
synced 2024-11-21 20:47:00 -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:
parent
13a474c4e9
commit
16c7eb4135
5 changed files with 89 additions and 1 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -4,3 +4,5 @@
|
||||||
/versions
|
/versions
|
||||||
/sources
|
/sources
|
||||||
/cache
|
/cache
|
||||||
|
/libexec/*.dylib
|
||||||
|
/src/*.o
|
||||||
|
|
|
@ -19,6 +19,7 @@ if [ -z "$RBENV_COMMAND" ]; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! enable -f "${BASH_SOURCE%/*}"/rbenv-realpath.dylib realpath 2>/dev/null; then
|
||||||
READLINK=$(type -p greadlink readlink | head -1)
|
READLINK=$(type -p greadlink readlink | head -1)
|
||||||
if [ -z "$READLINK" ]; then
|
if [ -z "$READLINK" ]; then
|
||||||
echo "rbenv: cannot find readlink - are you missing GNU coreutils?" >&2
|
echo "rbenv: cannot find readlink - are you missing GNU coreutils?" >&2
|
||||||
|
@ -42,13 +43,14 @@ realpath() {
|
||||||
echo "$(pwd)/$name"
|
echo "$(pwd)/$name"
|
||||||
cd "$cwd"
|
cd "$cwd"
|
||||||
}
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
IFS=: hook_paths=($RBENV_HOOK_PATH)
|
IFS=: hook_paths=($RBENV_HOOK_PATH)
|
||||||
|
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
for path in "${hook_paths[@]}"; do
|
for path in "${hook_paths[@]}"; do
|
||||||
for script in "$path/$RBENV_COMMAND"/*.bash; do
|
for script in "$path/$RBENV_COMMAND"/*.bash; do
|
||||||
echo $(realpath $script)
|
realpath "$script"
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
shopt -u nullglob
|
shopt -u nullglob
|
||||||
|
|
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
|
||||||
|
};
|
Loading…
Reference in a new issue