Mercurial > hg
changeset 18026:ddc0323db78b
osutil: write a C implementation of statfiles for unix
This makes a big difference to performance.
In a clean working directory containing 170,000 files, performance of
"hg --time diff" improves from 2.38 seconds to 1.69.
author | Bryan O'Sullivan <bryano@fb.com> |
---|---|
date | Mon, 03 Dec 2012 12:40:24 -0800 |
parents | 9b05b31b413c |
children | 4ca434500dbf |
files | mercurial/osutil.c mercurial/util.py |
diffstat | 2 files changed, 54 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/osutil.c Fri Nov 30 17:40:11 2012 -0800 +++ b/mercurial/osutil.c Mon Dec 03 12:40:24 2012 -0800 @@ -389,6 +389,55 @@ return ret; } +static PyObject *statfiles(PyObject *self, PyObject *args) +{ + PyObject *names, *stats; + Py_ssize_t i, count; + + if (!PyArg_ParseTuple(args, "O:statfiles", &names)) + return NULL; + + count = PySequence_Length(names); + if (count == -1) { + PyErr_SetString(PyExc_TypeError, "not a sequence"); + return NULL; + } + + stats = PyList_New(count); + if (stats == NULL) + return NULL; + + for (i = 0; i < count; i++) { + PyObject *stat; + struct stat st; + int ret, kind; + char *path; + + path = PyString_AsString(PySequence_GetItem(names, i)); + if (path == NULL) { + PyErr_SetString(PyExc_TypeError, "not a string"); + goto bail; + } + ret = lstat(path, &st); + kind = st.st_mode & S_IFMT; + if (ret != -1 && (kind == S_IFREG || kind == S_IFLNK)) { + stat = makestat(&st); + if (stat == NULL) + goto bail; + PyList_SET_ITEM(stats, i, stat); + } else { + Py_INCREF(Py_None); + PyList_SET_ITEM(stats, i, Py_None); + } + } + + return stats; + +bail: + Py_DECREF(stats); + return NULL; +} + #endif /* ndef _WIN32 */ static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs) @@ -553,6 +602,10 @@ {"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS, "Open a file with POSIX-like semantics.\n" "On error, this function may raise either a WindowsError or an IOError."}, +#else + {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS, + "stat a series of files or symlinks\n" +"Returns None for non-existent entries and entries of other types.\n"}, #endif #ifdef __APPLE__ {
--- a/mercurial/util.py Fri Nov 30 17:40:11 2012 -0800 +++ b/mercurial/util.py Mon Dec 03 12:40:24 2012 -0800 @@ -64,7 +64,7 @@ spawndetached = platform.spawndetached split = platform.split sshargs = platform.sshargs -statfiles = platform.statfiles +statfiles = getattr(osutil, 'statfiles', platform.statfiles) termwidth = platform.termwidth testpid = platform.testpid umask = platform.umask