From b3184fcafee79f7c31a92c1574d98a1c66414a06 Mon Sep 17 00:00:00 2001 From: Jamie Mac Date: Mon, 21 Nov 2022 15:56:43 +0000 Subject: [PATCH] Deep learning memory leak fix Fixed a memory leak whereby reloading the model every file (even if the model is closed) caused a memory leak. --- .../dlClassification/DLClassifyProcess.java | 5 ++++- .../genericModel/GenericDLClassifier.java | 6 +++++- .../genericModel/GenericModelWorker.java | 20 +++++++++++++++++-- .../genericModel/PamGenericModel.java | 8 +++----- .../dlClassification/ketos/KetosWorker.java | 19 ++++++++++++++++-- 5 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java index 987c34dd..ae048b20 100644 --- a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java +++ b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java @@ -36,6 +36,7 @@ import rawDeepLearningClassifier.segmenter.SegmenterProcess.GroupedRawData; */ public class DLClassifyProcess extends PamInstantProcess { + /** * Holds all model results but no other information */ @@ -538,7 +539,9 @@ public class DLClassifyProcess extends PamInstantProcess { @Override public void pamStop() { runModel(); //make sure to run the last data in the buffer. - this.dlControl.getDLModel().closeModel(); + + //21/11/2022 - it seems like this causes a memory leak when models are reopened and closed every file... + //this.dlControl.getDLModel().closeModel(); } /** diff --git a/src/rawDeepLearningClassifier/dlClassification/genericModel/GenericDLClassifier.java b/src/rawDeepLearningClassifier/dlClassification/genericModel/GenericDLClassifier.java index d0af8127..4f64407f 100644 --- a/src/rawDeepLearningClassifier/dlClassification/genericModel/GenericDLClassifier.java +++ b/src/rawDeepLearningClassifier/dlClassification/genericModel/GenericDLClassifier.java @@ -168,7 +168,11 @@ public class GenericDLClassifier implements DLClassiferModel, PamSettings { @Override public void closeModel() { - // TODO Auto-generated method stub + //very important to prevent memory leak for long term processing. + if (genericModelWorker.getModel()!=null && genericModelWorker.getModel().getModel()!=null) { + //System.out.println("CLOSE GENERNIC MODEL"); + genericModelWorker.getModel().getModel().close(); + } } diff --git a/src/rawDeepLearningClassifier/dlClassification/genericModel/GenericModelWorker.java b/src/rawDeepLearningClassifier/dlClassification/genericModel/GenericModelWorker.java index 388b6b0a..2742054c 100644 --- a/src/rawDeepLearningClassifier/dlClassification/genericModel/GenericModelWorker.java +++ b/src/rawDeepLearningClassifier/dlClassification/genericModel/GenericModelWorker.java @@ -1,5 +1,7 @@ package rawDeepLearningClassifier.dlClassification.genericModel; +import java.nio.file.Paths; + import org.apache.commons.io.FilenameUtils; import org.jamdev.jdl4pam.genericmodel.GenericModel; import org.jamdev.jdl4pam.transforms.DLTransform; @@ -69,8 +71,22 @@ public class GenericModelWorker extends DLModelWorker { // Thread.currentThread().setContextClassLoader(newCL); // } - //first open the model and get the correct parameters. - genericModel = new PamGenericModel(genericParams.modelPath); +// if (genericModel!=null) { +// System.out.println(Paths.get(genericModel.getModel().getName())); +// System.out.println(Paths.get(genericParams.modelPath)); +// System.out.println(Paths.get(genericModel.getModel().getName()).equals(Paths.get(genericParams.modelPath))); +// } + + //first open the model and get the correct parameters. + //21/11/2022 - Added a null and filename check here to stop the mdoel reloading everytime PAMGuard hits a new file or + //is stopped or started - this was causing a memory leak. + if (genericModel==null || !Paths.get(genericModel.getModel().getName()).equals(Paths.get(genericParams.modelPath))) { + //System.out.println(Paths.get(genericParams.modelPath)); + genericModel = new PamGenericModel(genericParams.modelPath); + + //System.out.println("LOAD A NEW MODEL: "); + //System.out.println(genericModel.getModel().getModelPath().getFileName()); + } //is this a waveform or a spectrogram model? DLTransform transform = genericParams.dlTransfroms.get(genericParams.dlTransfroms.size()-1); diff --git a/src/rawDeepLearningClassifier/dlClassification/genericModel/PamGenericModel.java b/src/rawDeepLearningClassifier/dlClassification/genericModel/PamGenericModel.java index b06f38cc..f81da14d 100644 --- a/src/rawDeepLearningClassifier/dlClassification/genericModel/PamGenericModel.java +++ b/src/rawDeepLearningClassifier/dlClassification/genericModel/PamGenericModel.java @@ -55,7 +55,7 @@ public class PamGenericModel { */ private Shape outShape = null; - + private SpectrogramTranslator specTranslator; @@ -64,6 +64,8 @@ public class PamGenericModel { public PamGenericModel(String modelPath) throws MalformedModelException, IOException{ + + //System.out.println("NEW GENERIC MODEL:"); File file = new File(modelPath); @@ -95,7 +97,6 @@ public class PamGenericModel { if (model == null) { System.err.println("Generic Model: Could not load model: " + modelPath); } - else { if (model!=null && model.describeInput()!=null) { System.out.println("Generic Model: Input: " + model.describeInput().toString()); @@ -117,7 +118,6 @@ public class PamGenericModel { //predictor for the model if using wavePredictor = model.newPredictor(waveTranslator); - } } @@ -201,8 +201,6 @@ public class PamGenericModel { } - - public Model getModel() { return model; } diff --git a/src/rawDeepLearningClassifier/dlClassification/ketos/KetosWorker.java b/src/rawDeepLearningClassifier/dlClassification/ketos/KetosWorker.java index 546f5b89..d39c40ce 100644 --- a/src/rawDeepLearningClassifier/dlClassification/ketos/KetosWorker.java +++ b/src/rawDeepLearningClassifier/dlClassification/ketos/KetosWorker.java @@ -1,6 +1,7 @@ package rawDeepLearningClassifier.dlClassification.ketos; import java.io.File; +import java.nio.file.Paths; import java.util.ArrayList; import org.jamdev.jdl4pam.ketos.KetosModel; @@ -15,6 +16,7 @@ import PamModel.PamModel.PluginClassloader; import rawDeepLearningClassifier.DLControl; import rawDeepLearningClassifier.dlClassification.animalSpot.StandardModelParams; import rawDeepLearningClassifier.dlClassification.genericModel.DLModelWorker; +import rawDeepLearningClassifier.dlClassification.genericModel.PamGenericModel; /** * @@ -30,7 +32,12 @@ public class KetosWorker extends DLModelWorker { /** * The ketos model */ - private KetosModel ketosModel; + private KetosModel ketosModel; + + /** + * Thelast loaded model path., + */ + private String currentPath; /** @@ -56,7 +63,15 @@ public class KetosWorker extends DLModelWorker { Thread.currentThread().setContextClassLoader(newCL); } //first open the model and get the correct parameters. - ketosModel = new KetosModel(new File(ketosDLParams.modelPath)); + //21/11/2022 - Added a null and filename check here to stop the mdoel reloading everytime PAMGuard hits a new file or + //is stopped or started - this was causing a memory leak. + if (ketosModel==null || currentPath ==null || !Paths.get(currentPath).equals(Paths.get(ketosDLParams.modelPath))) { + //System.out.println(Paths.get(genericParams.modelPath)); + this.currentPath = ketosDLParams.modelPath; + ketosModel = new KetosModel(new File(ketosDLParams.modelPath)); + //System.out.println("LOAD A NEW MODEL: "); + //System.out.println(genericModel.getModel().getModelPath().getFileName()); + } } catch (Exception e) { e.printStackTrace();