2011-05-20 1 views
2

Dans le cadre de mon projet actuel, nous prévoyons d'implémenter un DSL spécial pour permettre à l'utilisateur final d'effectuer des personnalisations de flux de travail. Nous envisageons plusieurs façons de le faire et l'un d'eux est d'utiliser Scala Interpreter (IMain) et DSL écrit dans Scala lui-même. Faire quelques expériences initiales que j'ai trouvé suite à un simple programme d'avoir des fuites de mémoire et conduit à la consommation de tas complète. Il pourrait être résolu en créant un nouvel objet IMain à chaque fois mais c'est une opération très coûteuse (temps et mémoire) donc il vaut mieux utiliser un seul interpréteur. La méthode interpreter.reset est appelée à chaque fois mais cela n'aide pas.Scala Interpreter pour DSL personnalisé conduit à des fuites de mémoire?

Si quelqu'un a de l'expérience avec Scala Interpreter, pourriez-vous dire comment l'utiliser correctement et éviter les fuites de mémoire?

Nous utilisons Scala 2.9.

import scala.tools.nsc.interpreter._ 
import scala.tools.nsc.Settings 
import java.util.concurrent.TimeUnit 

object DslTest { 
    val settings = new Settings() 
    settings.usejavacp.value = true 

    var interpreter = new IMain(settings); 

    def main(args : Array[String]) { 
     val t = System.currentTimeMillis 
     do { 
      test() 
     } while (System.currentTimeMillis - t < TimeUnit.SECONDS.toMillis(3000)) 
    } 

    def test() { 
     interpreter.interpret(""" 
      def sort(a:Array[Int]): Array[Int] = 
       if (a.length < 2) a 
       else { 
        val pivot = a(a.length/2) 
        sort (a filter (pivot>)) ++ 
         (a filter (pivot ==)) ++ 
        sort (a filter(pivot <)) 
      }"""); 
     interpreter.reset 
    } 
} 

Répondre

2

Ceci n'est pas une fuite de mémoire. Vous ajoutez constamment de nouvelles définitions sort pour la durée de la boucle while et, naturellement, chaque définition de tri augmentera l'utilisation de la mémoire. Voir aussi class unload.

+0

Cela ne ressemble pas à un problème de chargement de fichiers. J'appelle des méthodes interpreter.reset qui créent un nouveau chargeur de classe pour charger de nouvelles définitions. Et VisualVM montre que les définitions de classe inutilisées sont en cours de récupération. –