J'ai un code qui accède à une base de données SQLITE à l'aide de JDBC.
J'ai remarqué que chaque fois qu'une requête est faite, l'utilisation de la mémoire augmente - et cela ne diminue pas, même après la fermeture de la connexion. P>
Voici ce que je fais: p>
1) Fermeture du 2) Fermeture du 3) Fermeture de la connexion P> Voici une capture d'écran de l'analyse du tas: P> Il affiche beaucoup de Voici le code (son in Scala mais doit être facilement comparable à Java): p> Voici le test que j'ai écrit pour tester ceci: p> Paretstatement Code> P>
Resultats Code> p>
java.lang.ref.finaliseur code> et beaucoup de
préparéystatement code> et
résultatsset code> objets. P>
test("detect memory leak") {
log.info("Starting in 10 sec")
Thread.sleep(10.seconds.toMillis)
//Calls a method over and over to see if there's a memory leak or not..
(1 to 1000).par.foreach(i => {
val randomWord = getRandomWord() //this produces a random word
val sql = "SELECT foo FROM myTable where bar = ?"
val results = getStringsByQuery(sql, randomWord, "bar")
})
conn.close() //close the connection
log.info("Closed conn, closing in 30 sec")
Thread.sleep(1.minutes.toMillis)
}
3 Réponses :
Nous exécutons SQLite-JDBC dans un environnement de production et nous avons remarqué un comportement similaire lors de l'inspection des décharges de tas. P>
Ces objets ne sont que sur le tas car ils n'ont pas encore été couru à travers le collecteur des ordures. Dans le sens de https://blog.nelhage.com/post/three -Kinds-of-Fuaks / Il s'agit d'une "fuite de mémoire de type 2", dans laquelle les objets ont été alloués et vivent un peu plus longtemps que prévu. P>
Le problème que cela nous a causé est des machines conserveraient la mémoire sur le tas Java pour des périodes de temps de manière inattendue, de la pression de mémoire pendant les temps de la requête de pointe. Nous avons fait quelques choses différentes pour que ces objets soient collectés plus fréquemment. P>
Ceux-ci peuvent ne pas correspondre à votre cas d'utilisation, mais il s'agit de certaines options que vous pouvez envisager en fonction de ce que vous rencontrez. P>
Hey Tildeave - Utilisez-vous également JDBC pour accéder à SQLite? Avez-vous également vu des prises de préparation / Resulats n'étant pas GC'D? Étions-ils éventuellement éventuellement gc'd - si oui, après combien de temps?
Oui, nous exécutons SQLite-JDBC en utilisant la bibliothèque Xerial-SQLite, fondamentalement dans votre question. Les services courent pendant des jours ou des semaines à la fois. (Édité la réponse à être un peu plus clair.) Je ne suis pas certain de quoi les objets seront collectés. Cela dépend de la manière dont vous avez configuré le collecteur des ordures, donc si vous voyez des problèmes (au-delà de votre cas de test), c'est un endroit où vous pouvez commencer à chercher.
Pouvez-vous partager vos paramètres GC que vous avez finis par utiliser?
Les paramètres GC que nous avons sont assez spécifiques à notre application et je ne suis pas sûr qu'ils sont généralement utiles. Le principal avantage que nous avons eu était de réduire notre taille de tas qui est où je commencerais si vous voyez des problèmes de mémoire dans votre application. Nous remplaçons également actuellement l'initiationHeapeccupupbanypercent (GC plus fréquemment), G1oldcsetregionthresholdPercent (GC plus fréquemment), G1MaxNewSizEpercent (donnez plus d'espace de tas à de nouveaux objets) qui ont également contribué.
J'ai résolu ce problème en portant mes jeux de données SQLite à CQEngine. Ne pouvait pas être plus heureux. P>
J'ai fermé l'objet de connexion et de base de données, j'ai créé une nouvelle base de données d'objets avec les mêmes paramètres et une nouvelle connexion, puis appelée la collection de déchets. P>
Répétez le processus dont vous avez besoin. Je fais un compteur pour répéter le processus lorsque je remplisse la moitié de la mémoire de mon ordinateur. P>
Maintenant, je peux courir sans erreurs. P>
Connexion fermée Chaque itération
Aucune différence @ user7294900
J'ai aussi mis à jour la dernière version de SQLite Driver - Aucune différence
Avez-vous essayé d'ajouter une clause d'essayer? Stackoverflow.com/questions/51263449/...
@ user7294900 Je pense que cela ne devrait pas être nécessaire dans ce cas car les ressources sont fermées directement sans aucune exception.
Je regarderais dans st.setfetchsize (integer.max_value) et le raisonnement pourquoi il est défini sur INTEGER.MAX_VALUE?
@mkane Je veux qu'il retourne tous les résultats dans la même requête sans plusieurs requêtes - depuis son tout dans un fichier SQLite local. Je viens de tester la taille de la format de récupération à 1k. Il provoque une mémoire parfois descendant et non seulement - mais dans l'ensemble, cela finit toujours de monter sensiblement avec chaque itération