Skip to content

Commit

Permalink
* Speed up Loader on Windows when there are no symbolic links or l…
Browse files Browse the repository at this point in the history
…ibrary versions (pull #512)
  • Loading branch information
saudet committed Jan 24, 2022
1 parent 2616b0b commit e8b5734
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

* Speed up `Loader` on Windows when there are no symbolic links or library versions ([pull #512](https://github.com/bytedeco/javacpp/pull/512))
* Enhance `Pointer.physicalBytes()` by excluding shared pages from memory-mapped files, etc ([issue #468](https://github.com/bytedeco/javacpp/issues/468))
* Fix `Parser` not correctly encoding files of top-level classes produced with `@Properties(target=..., global=...)`
* Add `Pointer.interruptDeallocatorThread()` method to make JavaCPP classes eligible for GC ([discussion bytedeco/javacpp-presets#1115](https://github.com/bytedeco/javacpp-presets/discussions/1115))
Expand Down
31 changes: 21 additions & 10 deletions src/main/java/org/bytedeco/javacpp/Loader.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2011-2020 Samuel Audet
* Copyright (C) 2011-2022 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -500,7 +500,7 @@ public static File cacheResource(URL resourceURL, String target) throws IOExcept
boolean reference = false;
long size = 0, timestamp = 0;
File cacheDir = getCacheDir();
File cacheSubdir = Loader.getCanonicalFile(cacheDir);
File cacheSubdir = cacheDir;
String s = System.getProperty("org.bytedeco.javacpp.cachedir.nosubdir", "false").toLowerCase();
boolean noSubdir = s.equals("true") || s.equals("t") || s.equals("");
URLConnection urlConnection = resourceURL.openConnection();
Expand Down Expand Up @@ -661,7 +661,7 @@ public static File cacheResource(URL resourceURL, String target) throws IOExcept
}
// ... check if it has not already been extracted, and if not ...
if (!file.exists() || file.length() != size || file.lastModified() != timestamp
|| !cacheSubdir.equals(Loader.getCanonicalFile(file).getParentFile())) {
|| (canCreateSymbolicLink && !cacheSubdir.equals(Loader.getCanonicalFile(file).getParentFile()))) {
// ... add lock to avoid two JVMs access cacheDir simultaneously and ...
synchronized (Runtime.getRuntime()) {
try {
Expand All @@ -672,7 +672,7 @@ public static File cacheResource(URL resourceURL, String target) throws IOExcept
lock = lockChannel.lock();
// ... check if other JVM has extracted it before this JVM get the lock ...
if (!file.exists() || file.length() != size || file.lastModified() != timestamp
|| !cacheSubdir.equals(Loader.getCanonicalFile(file).getParentFile())) {
|| (canCreateSymbolicLink && !cacheSubdir.equals(Loader.getCanonicalFile(file).getParentFile()))) {
// ... extract it from our resources ...
if (logger.isDebugEnabled()) {
logger.debug("Extracting " + resourceURL);
Expand Down Expand Up @@ -790,7 +790,8 @@ public static File extractResource(URL resourceURL, File directoryOrFile,
if (entry.isDirectory()) {
file.mkdirs();
} else if (!cacheDirectory || !file.exists() || file.length() != entrySize
|| file.lastModified() != entryTimestamp || !file.equals(Loader.getCanonicalFile(file))) {
|| file.lastModified() != entryTimestamp
|| (canCreateSymbolicLink && !file.equals(Loader.getCanonicalFile(file)))) {
// ... extract it from our resources ...
file.delete();
String s = resourceURL.toString();
Expand Down Expand Up @@ -937,14 +938,19 @@ public static URL[] findResources(Class cls, String name, int maxLength) throws
static Map<String,URL[]> foundLibraries = new HashMap<String,URL[]>();
/** Contains all the native libraries that we have loaded to avoid reloading them. */
static Map<String,String> loadedLibraries = new HashMap<String,String>();
/** Will be set to false when symbolic link creation fails, such as on Windows. */
static boolean canCreateSymbolicLink = true;

/** Will be set to false when symbolic link creation fails, such as on Windows.
* Set via "org.bytedeco.javacpp.canCreateSymbolicLink" system property, defaults to false on Windows only. */
static boolean canCreateSymbolicLink = !WINDOWS;
/** Default value for {@code load(..., pathsFirst)} set via "org.bytedeco.javacpp.pathsFirst" system property. */
static boolean pathsFirst = false;
static {
String s = System.getProperty("org.bytedeco.javacpp.pathsfirst", "false").toLowerCase();
s = System.getProperty("org.bytedeco.javacpp.pathsFirst", s).toLowerCase();
pathsFirst = s.equals("true") || s.equals("t") || s.equals("");

s = System.getProperty("org.bytedeco.javacpp.cancreatesymboliclink", WINDOWS ? "false" : "true").toLowerCase();
s = System.getProperty("org.bytedeco.javacpp.canCreateSymbolicLink", s).toLowerCase();
canCreateSymbolicLink = s.equals("true") || s.equals("t") || s.equals("");
}

/** Creates and returns {@code System.getProperty("org.bytedeco.javacpp.cachedir")} or {@code ~/.javacpp/cache/} when not set. */
Expand All @@ -959,7 +965,7 @@ public static File getCacheDir() throws IOException {
File f = new File(dirName);
try {
if ((f.exists() || f.mkdirs()) && f.canRead() && f.canWrite() && f.canExecute()) {
cacheDir = f;
cacheDir = getCanonicalFile(f);
break;
}
} catch (SecurityException e) {
Expand Down Expand Up @@ -1246,7 +1252,7 @@ public static String load(Class cls, Properties properties, boolean pathsFirst,

String cacheDir = null;
try {
cacheDir = Loader.getCanonicalPath(getCacheDir());
cacheDir = getCacheDir().toString();
} catch (IOException e) {
// no cache dir, no worries
}
Expand Down Expand Up @@ -1457,6 +1463,11 @@ public static URL[] findLibrary(Class cls, ClassProperties properties, String li
prefix + libname2 + version2 + suffix, // Mac OS X style
prefix + libname2 + suffix // without version
};
if (version.length() == 0 && version2.length() == 0) {
// optimize a bit for this case in particular on Windows
styles = new String[] { prefix + libname + suffix };
styles2 = new String[] { prefix + libname2 + suffix };
}

String[] suffixes = properties.get("platform.library.suffix").toArray(new String[0]);
if (suffixes.length > 1) {
Expand Down

0 comments on commit e8b5734

Please sign in to comment.