2010-04-09 3 views
2

Lors du débogage du démarrage lent d'une application Eclipse RCP sur un serveur Citrix, j'ai découvert que java.io.createTempFile (String, String, File) prenait 5 secondes. Il le fait seulement sur la première exécution et seulement pour certains comptes d'utilisateurs. Plus précisément, je remarque les comptes d'utilisateurs anonymes Citrix. Je n'ai pas essayé beaucoup d'autres types de comptes, mais ce comportement n'est pas exposé avec un compte d'administrateur.Pourquoi le premier appel à java.io.File.createTempFile (String, String, File) prend-il 5 secondes sur Citrix?

De plus, peu importe si l'utilisateur a accès ou non au répertoire donné. Si l'utilisateur n'a pas accès, l'appel prendra 5 secondes pour échouer. S'ils ont accès, l'appel prend 5 secondes pour réussir.

Ceci est sur un serveur Windows 2003. J'ai essayé les JRE 1.6.0_16 et 1.6.0_19 de Sun et j'ai observé le même comportement.

J'ai fait un peu de recherche sur Google, pensant que c'était un problème connu, mais je n'ai rien trouvé. Il semble que quelqu'un d'autre aurait dû y être confronté auparavant. La plate-forme Eclipse utilise File.createTempFile() pour tester divers répertoires pour voir s'ils sont inscriptibles pendant l'initialisation et ce problème ajoute 5 secondes au temps de démarrage de notre application.

J'imagine que quelqu'un a déjà été confronté à ce problème et pourrait avoir un aperçu. Voici un exemple de code que j'ai exécuté pour voir que c'est bien cet appel qui consomme le temps. J'ai également essayé avec un deuxième appel à createTempFile et notez que les appels suivants reviennent presque instantanément.

 
public static void main(final String[] args) throws IOException { 
     final File directory = new File(args[0]); 
     final long startTime = System.currentTimeMillis(); 
     File file = null; 
     try { 
      file = File.createTempFile("prefix", "suffix", directory); 
      System.out.println(file.getAbsolutePath()); 
     } finally { 
      System.out.println(System.currentTimeMillis() - startTime); 
      if (file != null) { 
       file.delete(); 
      } 
     } 
    } 

Exemple de sortie de ce programme est le suivant:

 
C:\>java.exe -jar filetest.jar C:/Temp 
C:\Temp\prefix8098550723198856667suffix 
5093 
+0

Je tiens également à noter, 5 deuxième fois est cohérente. Je peux courir ceci encore et encore et cela prendra toujours entre 5000-5300 millisecondes. Je suppose que les 5 secondes doivent être un certain délai d'attente à un certain niveau. De plus, cela ne se passe pas seulement sur un serveur. A l'origine, le comportement a été remarqué sur un serveur mais j'ai mis en place un autre serveur et j'ai vu la même chose. –

+0

Comme noté comme un commentaire sur l'une des réponses ci-dessous, j'ai remarqué que ce temps est réellement passé dans le premier appel de SecureRandom.nextLong(). En outre, j'ai constaté que ce problème se produit uniquement lorsqu'un utilisateur a le groupe "Invité" qui leur est associé. Je peux exécuter ce test avec un utilisateur et l'exécuter en moins de 100ms puis ré-exécuter le même test avec le même compte utilisateur après avoir simplement ajouté cet utilisateur au groupe "Invités" (sans supprimer aucune autre association de groupe de l'utilisateur avait dans la course précédente). –

Répondre

2

Il pourrait être le intialisation du générateur de nombres aléatoires sécurisé qui est à l'origine du problème. En particulier, si une graine aléatoire sécurisée ne peut pas être obtenue à partir du système d'exploitation, alors le mécanisme de repli tente de gagner de l'entropie. IIRC, l'une des choses qu'il fait est de lister les fichiers temporaires, donc si vous avez un grand nombre de ceux qui n'aideront pas les performances de démarrage.

+0

J'ai testé la génération aléatoire sécurisée séparément et ce n'est pas le problème. J'ai couru cela dans le débogueur et j'ai regardé l'implémentation de createTempFile et j'ai remarqué la génération aléatoire sécurisée et je me suis dit que je l'avais exclu après avoir testé ce morceau spécifiquement avec un programme de test. Merci pour la suggestion cependant. Je doute qu'il y ait un grand nombre de fichiers temporaires sur ce système. Je ne suis pas sûr de ce qui se qualifie comme un fichier temporaire qui compterait contre ce que vous parlez, mais le répertoire c:/temp où j'ai exécuté mon test spécifique ci-dessus n'a que 165 fichiers. –

+0

Ok, donc j'avais tort quand j'ai dit que ce n'était pas la génération aléatoire sécurisée. Après un peu plus de débogage, j'ai réalisé que mon test initial de la partie aléatoire sécurisée était insuffisant. J'avais seulement testé la construction du nouveau SecureRandom(). Quand j'ai testé la première invocation de nextLong() sur SecureRandom, j'ai vu que c'était la source du délai de 5 secondes. –

+0

Un problème similaire et la solution est discutée ici - http://stackoverflow.com/questions/38942514/simple-java-program-100-times-slower-after-plugging-in-usb-hotspot/ – apangin

0

Je ne suis pas un expert Citrix, mais je connais quelqu'un qui est, et qui Conjectures:

Les comptes peuvent être mis en place afin que l'application lecture/écriture sont redirigés vers des ressources non locales. La latence que vous rencontrez peut être liée à l'initialisation ou aux performances de cette résolution.

Une autre possibilité est que l'isolation de l'application soit effective, ce qui signifie que les lectures/écritures de fichiers se produisent sur des versions virtualisées de ressources.

+0

Merci pour ces suggestions , mais les ressources sont locales et le fait qu'un utilisateur administrateur puisse écrire au même endroit sans ce retard me suggère que cela ne pourrait pas être le problème de toute façon. –

1

Il semble que la lenteur soit due à l'amorçage de SecureRandom et uniquement lorsque l'utilisateur est membre du groupe Invités. L'initialisation de la graine SecureRandom utilise une API Windows Crypto qui échoue lorsque l'utilisateur est invité comme décrit ici [1]. En définissant la propriété système « java.security.debug » égal à « tout », je peux voir ce qui suit lorsque le programme exécuté en tant qu'invité:

 
ProviderConfig: Loaded provider SUN version 1.6 
provider: Failed to use operating system seed generator: java.io.IOException: Required native CryptoAPI features not available on this machine 
provider: Using default threaded seed generator 

Lorsqu'il est exécuté en tant qu'utilisateur non invité, la sortie est ceci:

 
ProviderConfig: Loaded provider SUN version 1.6 
provider: Using operating system seed generator 

Il semble que le générateur de graines par défaut soit assez lent.Ici [2] est un très vieux bug enregistré à Sun à ce sujet.

[1] http://www.derkeiler.com/Newsgroups/microsoft.public.platformsdk.security/2003-12/0349.html

[2] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4210047

Questions connexes