Simple heap size monitor

Tagged:

Voila ... le java le gros problème ... c'est la mémoire utilisée ... on a des softs java qui tournent toutes les deux minutes, puis d'autre dans la journée occasionnellement, puis les webapps, un websphere et un tomcat ...

Grosso modo la machine sun a 4 Go de mémoire et elle est complètement à genoux !!! (elle va passer a 12G bientot histoire de régler le soucis !!!)

Bref pour savoir si on développe bien et si on consomme pas trop de mémoire, j'ai fait en sorte de pouvoir lancer mes softs avec un paramètre HEAP et ils loggent directement la taille mémoire toutes les secondes ... Voici comment je m'y suis pris :

public class MemoryMonitorHelper extends Thread {
 
	private static MemoryMonitorHelper _instance = null;
	private static MemoryMonitorHelper getInstance() {
		if (_instance == null) {
			_instance = new MemoryMonitorHelper();
		}
		return _instance;
	}
	
	public static void startMonitoring(File file, String title) {
		startMonitoring(file, title, 1);
	}
	
	public static void startMonitoring(File file, String title, double refreshInSec) {
		System.out.println("Start Monitoring");
		MemoryMonitorHelper i = getInstance();
		i.setFile(file);
		i.setTitle(title);
		i.setRefreshInSec(refreshInSec);
		i.start();
	}
	
	public static void stopMonitoring() {
		System.out.println("Stop Monitoring");
		getInstance().finish();
	}
 
	
	private File file = null;
	private String title = null;
	private double refreshInSec = 1.0;
	private boolean enabled = false;
	
	public MemoryMonitorHelper() {
	}
	
	public void setFile(File file) {
		this.file = file;
	}
 
	public void setRefreshInSec(double refreshInSec) {
		this.refreshInSec = refreshInSec;
	}
 
	public void setTitle(String title) {
		this.title = title;
	}
 
	private String getSize(double size) {
		String[] suffix = {
				"B", "K", "M", "G"
		};
		int si = 0;
		while (size > 1024) {
			size /= 1024;
			si++;
		}
		return DoubleHelper.format(size, "#,##0.00") + suffix[si];
	}
	
	public void run() {
		enabled = true;
		while (enabled) {
			long total = Runtime.getRuntime().totalMemory();
			long free = Runtime.getRuntime().freeMemory();
			
			String data = "[" + DateHelper.getFormattedDate("yy/MM/dd HH:mm:ss") + "] " + 
				title + "=> total:" + getSize(total) + 
						" free:" + getSize(free) + 
						" " + DoubleHelper.format(((double)free/(double)total*100.0), "#0") + "%";
			System.out.println(data);
			try {
				FileHelper.createContent(file, data + "\n", true, FileHelper.UTF8);
				sleep((int)(refreshInSec * 1000));
			} catch (Exception e) {
				e.printStackTrace();
				enabled = false;
			}
		}
	}
	
	public synchronized void finish() {
		enabled = false;
	}
	
}

Donc sommes toutes assez simple a utiliser :

public static void main(String[] args) {
	boolean heap = (args.length > 0) && args[0].equals("HEAP");
	if (heap) {
		MemoryMonitorHelper.startMonitoring(new File("mem.log"), "MyProcess");
	}
 
	/*- processes -*/
 
	if (heap) {
		MemoryMonitorHelper.stopMonitoring();
	}
}

Je file pas le code des helpers c'est pas le sujet mais imaginez ce qu'ils font, c'est assez simple a refaire !!!

Et conclusion ... je suis presque a 100M utilisé pour chacun de mes softs ... le java c'est le cancer de la RAM !

Comments

Bonjour,
j'ai un serveur sur lequel la gestion de la mémoire pose quelques soucis.
Pour des questions de performances, nous utilisons énormément d'objets uniques instanciés une seule et unique fois.
Cela peut parfois engendrer des pics au niveau de la mémoire utilisée par les JVM.
Je pense, que dans une certaine mesure, certaines JVM ne sont pas convenablement 'stoppée' et sont maintenues dans les process en cours.
j'ai longuement cherché dans mon code l'origine de ces problèmes.
L'activité de ma société s'accroissant, j'ai fait faire une toute nouvelle config de serveur par un pro ( je suis à l'origine de la config du premier serveur ) et là, miracle, le problème ne se pose plus ( pas une seule modif de code ). Il m'a également vivement conseiller d'éviter d'utiliser plusieurs JVM distinctes sur la même machine, et conseillé de travailler sur des serveurs virtuel si il n'est pas possible de faire autrement. Dans ce cas, la communication est assurée en RMI.

De plus, pour avoir essayer de faire appel à des applications Java externe à ma webapp principal, j'ai constaté des "fuites" de mémoire difficiles à resorber.

Serveur posant soucis :
serveur Bi-Xeon avec 2G de RAM,
Linux Debian Woody,
Apache 2.0 ( avec et sans SSL )
Tomcat 5.3
Java 1.4.2
mod_jk2 pour la passerelle apache / tomcat
Postgresql 7.3

A vrai dire, si c'était a refaire, il y aurait pas mal de choses qui ne tourneraient pas de cette manière sur cette machine ...

C'est une sun solaris avec 3 instances (dev, cert et prod) donc c'est de l'ultrasparc 4 proc 2.5Ghz avec 4G de Ram ... donc la machine devrait suivre sans soucis, mais bon ... 3 instances et des JVM lancées par floppées toutes les 2 a 5 minutes ... un carnage ...

le RMI c'est sympa mais comme dit, il faut que toute ta logique applicative soit basée la dessus, or pour l'instant, tout est fait pour ne pas fonctionner avec ça chez nous !!! Domage ...

On a aussi un tomcat, il faut le redémarrer de temps a autre, mais il tourne pas trop mal ... a coté on a un WebSphere et ça ... c'est RAMophage !!!

Bref maintenant on compose un peu avec ce qu'on a, peut être qu'un jour il faudra modifier tout ça si les besoins augmentent encore !!!

Merci pour ton commentaire :)