Skip to content

Commit cdd8038

Browse files
committed
[GR-14822] Improve os.stat performance.
1 parent cc6721a commit cdd8038

File tree

2 files changed

+169
-70
lines changed

2 files changed

+169
-70
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java

Lines changed: 167 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,24 @@
3232
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
3333
import static com.oracle.graal.python.runtime.exception.PythonErrorType.ValueError;
3434

35+
import static com.oracle.truffle.api.TruffleFile.CREATION_TIME;
36+
import static com.oracle.truffle.api.TruffleFile.IS_DIRECTORY;
37+
import static com.oracle.truffle.api.TruffleFile.IS_REGULAR_FILE;
38+
import static com.oracle.truffle.api.TruffleFile.IS_SYMBOLIC_LINK;
39+
import static com.oracle.truffle.api.TruffleFile.LAST_ACCESS_TIME;
40+
import static com.oracle.truffle.api.TruffleFile.LAST_MODIFIED_TIME;
41+
import static com.oracle.truffle.api.TruffleFile.SIZE;
42+
import static com.oracle.truffle.api.TruffleFile.UNIX_CTIME;
43+
import static com.oracle.truffle.api.TruffleFile.UNIX_DEV;
44+
import static com.oracle.truffle.api.TruffleFile.UNIX_INODE;
45+
import static com.oracle.truffle.api.TruffleFile.UNIX_GID;
46+
import static com.oracle.truffle.api.TruffleFile.UNIX_GROUP;
47+
import static com.oracle.truffle.api.TruffleFile.UNIX_MODE;
48+
import static com.oracle.truffle.api.TruffleFile.UNIX_NLINK;
49+
import static com.oracle.truffle.api.TruffleFile.UNIX_OWNER;
50+
import static com.oracle.truffle.api.TruffleFile.UNIX_PERMISSIONS;
51+
import static com.oracle.truffle.api.TruffleFile.UNIX_UID;
52+
3553
import java.io.IOException;
3654
import java.io.InputStream;
3755
import java.io.OutputStream;
@@ -445,108 +463,189 @@ long fileTimeToSeconds(FileTime t) {
445463
return t.to(TimeUnit.SECONDS);
446464
}
447465

466+
@TruffleBoundary
448467
Object stat(String path, boolean followSymlinks) {
449468
TruffleFile f = getContext().getEnv().getTruffleFile(path);
450469
LinkOption[] linkOptions = followSymlinks ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS};
451470
try {
452-
if (!f.exists(linkOptions)) {
453-
throw fileNoFound(path);
471+
return unixStat(f, linkOptions);
472+
} catch (UnsupportedOperationException unsupported) {
473+
try {
474+
return posixStat(f, linkOptions);
475+
} catch (UnsupportedOperationException unsupported2) {
476+
return basicStat(f, linkOptions);
454477
}
455-
} catch (SecurityException e) {
456-
throw fileNoFound(path);
457-
}
458-
int mode = 0;
459-
long size = 0;
460-
long ctime = 0;
461-
long atime = 0;
462-
long mtime = 0;
463-
long gid = 0;
464-
long uid = 0;
465-
if (f.isRegularFile(linkOptions)) {
466-
mode |= S_IFREG;
467-
} else if (f.isDirectory(linkOptions)) {
468-
mode |= S_IFDIR;
469-
} else if (f.isSymbolicLink()) {
470-
mode |= S_IFLNK;
471-
} else {
472-
// TODO: differentiate these
473-
mode |= S_IFSOCK | S_IFBLK | S_IFCHR | S_IFIFO;
474-
}
475-
try {
476-
mtime = fileTimeToSeconds(f.getLastModifiedTime(linkOptions));
477-
} catch (IOException e1) {
478-
mtime = 0;
479-
}
480-
try {
481-
ctime = fileTimeToSeconds(f.getCreationTime(linkOptions));
482-
} catch (IOException e1) {
483-
ctime = 0;
484478
}
479+
}
480+
481+
private PTuple unixStat(TruffleFile file, LinkOption... linkOptions) {
485482
try {
486-
atime = fileTimeToSeconds(f.getLastAccessTime(linkOptions));
487-
} catch (IOException e1) {
488-
atime = 0;
483+
TruffleFile.Attributes attributes = file.getAttributes(Arrays.asList(
484+
UNIX_MODE,
485+
UNIX_INODE,
486+
UNIX_DEV,
487+
UNIX_NLINK,
488+
UNIX_UID,
489+
UNIX_GID,
490+
SIZE,
491+
LAST_ACCESS_TIME,
492+
LAST_MODIFIED_TIME,
493+
UNIX_CTIME), linkOptions);
494+
return factory().createTuple(new Object[]{
495+
attributes.get(UNIX_MODE),
496+
attributes.get(UNIX_INODE),
497+
attributes.get(UNIX_DEV),
498+
attributes.get(UNIX_NLINK),
499+
attributes.get(UNIX_UID),
500+
attributes.get(UNIX_GID),
501+
attributes.get(SIZE),
502+
fileTimeToSeconds(attributes.get(LAST_ACCESS_TIME)),
503+
fileTimeToSeconds(attributes.get(LAST_MODIFIED_TIME)),
504+
fileTimeToSeconds(attributes.get(UNIX_CTIME)),
505+
});
506+
} catch (IOException | SecurityException e) {
507+
throw fileNoFound(file.getPath());
489508
}
490-
UserPrincipal owner;
509+
}
510+
511+
private PTuple posixStat(TruffleFile file, LinkOption... linkOptions) {
491512
try {
492-
owner = f.getOwner(linkOptions);
513+
int mode = 0;
514+
long size = 0;
515+
long ctime = 0;
516+
long atime = 0;
517+
long mtime = 0;
518+
long gid = 0;
519+
long uid = 0;
520+
TruffleFile.Attributes attributes = file.getAttributes(Arrays.asList(
521+
IS_DIRECTORY,
522+
IS_SYMBOLIC_LINK,
523+
IS_REGULAR_FILE,
524+
LAST_MODIFIED_TIME,
525+
LAST_ACCESS_TIME,
526+
CREATION_TIME,
527+
SIZE,
528+
UNIX_OWNER,
529+
UNIX_GROUP,
530+
UNIX_PERMISSIONS), linkOptions);
531+
mode |= fileTypeBitsFromAttributes(attributes);
532+
mtime = fileTimeToSeconds(attributes.get(LAST_MODIFIED_TIME));
533+
ctime = fileTimeToSeconds(attributes.get(CREATION_TIME));
534+
atime = fileTimeToSeconds(attributes.get(LAST_ACCESS_TIME));
535+
size = attributes.get(SIZE);
536+
UserPrincipal owner = attributes.get(UNIX_OWNER);
493537
if (owner instanceof UnixNumericUserPrincipal) {
494-
uid = strToLong(((UnixNumericUserPrincipal) owner).getName());
538+
try {
539+
uid = strToLong(((UnixNumericUserPrincipal) owner).getName());
540+
} catch (NumberFormatException e2) {
541+
}
495542
}
496-
} catch (NumberFormatException | IOException | UnsupportedOperationException | SecurityException e2) {
497-
}
498-
try {
499-
GroupPrincipal group = f.getGroup(linkOptions);
543+
GroupPrincipal group = attributes.get(UNIX_GROUP);
500544
if (group instanceof UnixNumericGroupPrincipal) {
501-
gid = strToLong(((UnixNumericGroupPrincipal) group).getName());
545+
try {
546+
gid = strToLong(((UnixNumericGroupPrincipal) group).getName());
547+
} catch (NumberFormatException e2) {
548+
}
502549
}
503-
} catch (NumberFormatException | IOException | UnsupportedOperationException | SecurityException e2) {
550+
final Set<PosixFilePermission> posixFilePermissions = attributes.get(UNIX_PERMISSIONS);
551+
mode = posixPermissionsToMode(mode, posixFilePermissions);
552+
int inode = getInode(file);
553+
return factory().createTuple(new Object[]{
554+
mode,
555+
inode, // ino
556+
0, // dev
557+
0, // nlink
558+
uid,
559+
gid,
560+
size,
561+
atime,
562+
mtime,
563+
ctime,
564+
});
565+
} catch (IOException | SecurityException e) {
566+
throw fileNoFound(file.getPath());
504567
}
568+
}
569+
570+
private PTuple basicStat(TruffleFile file, LinkOption... linkOptions) {
505571
try {
506-
final Set<PosixFilePermission> posixFilePermissions = f.getPosixPermissions(linkOptions);
507-
mode = posixPermissionsToMode(mode, posixFilePermissions);
508-
} catch (UnsupportedOperationException | IOException e1) {
509-
if (f.isReadable()) {
572+
int mode = 0;
573+
long size = 0;
574+
long ctime = 0;
575+
long atime = 0;
576+
long mtime = 0;
577+
long gid = 0;
578+
long uid = 0;
579+
TruffleFile.Attributes attributes = file.getAttributes(Arrays.asList(
580+
IS_DIRECTORY,
581+
IS_SYMBOLIC_LINK,
582+
IS_REGULAR_FILE,
583+
LAST_MODIFIED_TIME,
584+
LAST_ACCESS_TIME,
585+
CREATION_TIME,
586+
SIZE), linkOptions);
587+
mode |= fileTypeBitsFromAttributes(attributes);
588+
mtime = fileTimeToSeconds(attributes.get(LAST_MODIFIED_TIME));
589+
ctime = fileTimeToSeconds(attributes.get(CREATION_TIME));
590+
atime = fileTimeToSeconds(attributes.get(LAST_ACCESS_TIME));
591+
size = attributes.get(SIZE);
592+
if (file.isReadable()) {
510593
mode |= 0004;
511594
mode |= 0040;
512595
mode |= 0400;
513596
}
514-
if (f.isWritable()) {
597+
if (file.isWritable()) {
515598
mode |= 0002;
516599
mode |= 0020;
517600
mode |= 0200;
518601
}
519-
if (f.isExecutable()) {
602+
if (file.isExecutable()) {
520603
mode |= 0001;
521604
mode |= 0010;
522605
mode |= 0100;
523606
}
607+
int inode = getInode(file);
608+
return factory().createTuple(new Object[]{
609+
mode,
610+
inode, // ino
611+
0, // dev
612+
0, // nlink
613+
uid,
614+
gid,
615+
size,
616+
atime,
617+
mtime,
618+
ctime,
619+
});
620+
} catch (IOException | SecurityException e) {
621+
throw fileNoFound(file.getPath());
524622
}
525-
try {
526-
size = f.size(linkOptions);
527-
} catch (IOException e) {
528-
size = 0;
623+
}
624+
625+
private static int fileTypeBitsFromAttributes(TruffleFile.Attributes attributes) {
626+
int mode = 0;
627+
if (attributes.get(IS_REGULAR_FILE)) {
628+
mode |= S_IFREG;
629+
} else if (attributes.get(IS_DIRECTORY)) {
630+
mode |= S_IFDIR;
631+
} else if (attributes.get(IS_SYMBOLIC_LINK)) {
632+
mode |= S_IFLNK;
633+
} else {
634+
// TODO: differentiate these
635+
mode |= S_IFSOCK | S_IFBLK | S_IFCHR | S_IFIFO;
529636
}
637+
return mode;
638+
}
639+
640+
private int getInode(TruffleFile file) {
530641
TruffleFile canonical;
531642
try {
532-
canonical = f.getCanonicalFile();
643+
canonical = file.getCanonicalFile();
533644
} catch (IOException | SecurityException e) {
534645
// best effort
535-
canonical = f.getAbsoluteFile();
646+
canonical = file.getAbsoluteFile();
536647
}
537-
int inode = getContext().getResources().getInodeId(canonical.getPath());
538-
return factory().createTuple(new Object[]{
539-
mode,
540-
inode, // ino
541-
0, // dev
542-
0, // nlink
543-
uid,
544-
gid,
545-
size,
546-
atime,
547-
mtime,
548-
ctime,
549-
});
648+
return getContext().getResources().getInodeId(canonical.getPath());
550649
}
551650

552651
private PException fileNoFound(String path) {

mx.graalpython/suite.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@
4444
},
4545
{
4646
"name": "sulong",
47-
"version": "f7f14f5d4d9ac7c2537932810082fc9f54cb635e",
47+
"version": "48408a3a99130928a114cc881ad6badfb9d2210d",
4848
"subdir": True,
4949
"urls": [
5050
{"url": "https://github.com/oracle/graal", "kind": "git"},
5151
]
5252
},
5353
{
5454
"name": "regex",
55-
"version": "f7f14f5d4d9ac7c2537932810082fc9f54cb635e",
55+
"version": "48408a3a99130928a114cc881ad6badfb9d2210d",
5656
"subdir": True,
5757
"urls": [
5858
{"url": "https://github.com/oracle/graal", "kind": "git"},

0 commit comments

Comments
 (0)