/* * Copyright 2010-2015 Institut Pasteur. * * This file is part of Icy. * * Icy is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Icy is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Icy. If not, see <http://www.gnu.org/licenses/>. */ package icy.gui.system; import icy.image.ImageUtil; import icy.math.UnitUtil; import icy.network.NetworkUtil; import icy.resource.ResourceUtil; import icy.system.SystemUtil; import icy.system.thread.ThreadUtil; import icy.util.ColorUtil; import icy.util.GraphicsUtil; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.image.BufferedImage; import java.util.Timer; import java.util.TimerTask; import javax.swing.JPanel; import vtk.vtkObjectBase; /** * Memory monitor. * * @author Fab & Stephane */ public class MemoryMonitorPanel extends JPanel implements MouseListener { private static final long serialVersionUID = 5629509450385435829L; private static int NBVAL = 94; /** * 0 est la valeur la plus ancienne. */ private final double[][] valeur; private final String[] infos; private final Timer updateTimer; private final Color cpuColor = ColorUtil.mix(Color.blue, Color.white); private final Color cpuTextColor = ColorUtil.mix(cpuColor, Color.white); private final Color memColor = Color.green; private final Color memTextColor = ColorUtil.mix(memColor, Color.white); private final Color connectionColor = ColorUtil.mix(Color.red, Color.white); private final BasicStroke cpuStroke = new BasicStroke(2); private final BasicStroke memStroke = new BasicStroke(3); private final Font textFont = new Font("Arial", Font.BOLD, 9); private BufferedImage background = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); private final Image networkImage = ImageUtil.getColorImageFromAlphaImage(ResourceUtil.ICON_NETWORK, Color.gray); private final Image deleteImage = ImageUtil.getColorImageFromAlphaImage(ResourceUtil.ICON_DELETE, Color.red); boolean displayHelpMessage = false; public MemoryMonitorPanel() { super(); updateTimer = new Timer("Memory / CPU monitor"); // init tables valeur = new double[NBVAL][2]; for (int i = 0; i < NBVAL; i++) { valeur[i][0] = 0; valeur[i][1] = 0; } infos = new String[2]; for (int i = 0; i < 2; i++) infos[i] = ""; setMinimumSize(new Dimension(120, 50)); setPreferredSize(new Dimension(140, 55)); addMouseListener(this); updateTimer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { updateMemoryMessageBar(); } }, 100, 100); } @Override protected void paintComponent(Graphics g) { final int w = getWidth(); final int h = getHeight(); if ((background.getWidth() != w) || (background.getHeight() != h)) { background = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D background_g2 = background.createGraphics(); GraphicsUtil.paintIcyBackGround(w, h, background_g2); } g.drawImage(background, 0, 0, null); final Graphics2D g2 = (Graphics2D) g.create(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // display graph if (valeur != null) { float x; double max; double ymul; final float step = w / 100f; // draw used memory g2.setStroke(memStroke); g2.setColor(memColor); max = SystemUtil.getJavaMaxMemory(); ymul = (h - 8) / max; x = 6; for (int i = 0; i < NBVAL - 1; i++) { final double v1 = Math.min(valeur[i][0], max); final double v2 = Math.min(valeur[i + 1][0], max); final int y1 = h - (int) (v1 * ymul); final int y2 = h - (int) (v2 * ymul); g2.drawLine((int) x, y1 - 4, (int) (x + step), y2 - 4); x += step; } // draw CPU load g2.setStroke(cpuStroke); g2.setColor(cpuColor); max = 100d; ymul = (h - 8) / max; x = 6; for (int i = 0; i < NBVAL - 1; i++) { final double v1 = Math.min(valeur[i][1], max); final double v2 = Math.min(valeur[i + 1][1], max); final int y1 = h - (int) (v1 * ymul); final int y2 = h - (int) (v2 * ymul); g2.drawLine((int) x, y1 - 4, (int) (x + step), y2 - 4); x += step; } } // display text g2.setFont(textFont); // display Used & Max Memory g2.setColor(Color.black); GraphicsUtil.drawHCenteredString(g2, infos[0], (w / 2) + 1, 6 + 1, false); g2.setColor(memTextColor); GraphicsUtil.drawHCenteredString(g2, infos[0], w / 2, 6, false); // display CPU Load g2.setColor(Color.black); GraphicsUtil.drawHCenteredString(g2, infos[1], (w / 2) + 1, 18 + 1, false); g2.setColor(cpuTextColor); GraphicsUtil.drawHCenteredString(g2, infos[1], w / 2, 18, false); String text; // display internet connection if (!NetworkUtil.hasInternetAccess()) { g2.drawImage(networkImage, 10, 30, 16, 16, null); g2.drawImage(deleteImage, 13, 35, 10, 10, null); if (displayHelpMessage) { text = "Not connected to internet"; g2.setColor(Color.black); GraphicsUtil.drawHCenteredString(g2, text, (w / 2) + 1, 30 + 1, false); g2.setColor(connectionColor); GraphicsUtil.drawHCenteredString(g2, text, w / 2, 30, false); } } if (displayHelpMessage) { text = "click to force a garbage collector event"; g2.setColor(Color.black); GraphicsUtil.drawHCenteredString(g2, text, (w / 2) + 1, 44 + 1, false); g2.setColor(Color.white); GraphicsUtil.drawHCenteredString(g2, text, w / 2, 44, false); } g2.dispose(); } void updateMemoryMessageBar() { final double usedMemory = SystemUtil.getJavaUsedMemory(); final int cpuLoad = SystemUtil.getCpuLoad(); // save used memory newValue(0, usedMemory); // save CPU load newValue(1, cpuLoad); setInfo(0, "Memory: " + UnitUtil.getBytesString(usedMemory) + " (Max: " + UnitUtil.getBytesString(SystemUtil.getJavaMaxMemory()) + ")"); setInfo(1, "CPU: " + cpuLoad + "%"); repaint(); } /** * Scroll les valeurs et en ajoute ( un seeker serait plus joli...) */ public void newValue(int curve, double val) { for (int i = 0; i < NBVAL - 1; i++) valeur[i][curve] = valeur[i + 1][curve]; valeur[NBVAL - 1][curve] = val; } public void setInfo(int infonb, String info) { infos[infonb] = info; } @Override public void mouseClicked(MouseEvent event) { final MouseEvent e = event; ThreadUtil.bgRun(new Runnable() { @Override public void run() { final double freeBefore = SystemUtil.getJavaFreeMemory(); // force garbage collector System.gc(); final double freeAfter = SystemUtil.getJavaFreeMemory(); final double released = freeAfter - freeBefore; final double usedMemory = SystemUtil.getJavaUsedMemory(); System.out.println("Max / Used memory: " + UnitUtil.getBytesString(SystemUtil.getJavaMaxMemory()) + " / " + UnitUtil.getBytesString((usedMemory > 0) ? usedMemory : 0) + " (released by GC: " + UnitUtil.getBytesString((released > 0) ? released : 0) + ")"); } }); // double click --> force VTK garbage collection (need to be done in EDT or it crashes on OSX) if (e.getClickCount() > 1) { vtkObjectBase.JAVA_OBJECT_MANAGER.gc(true); System.out.println("VTK GC forced"); } } @Override public void mouseEntered(MouseEvent arg0) { displayHelpMessage = true; } @Override public void mouseExited(MouseEvent arg0) { displayHelpMessage = false; } @Override public void mousePressed(MouseEvent arg0) { } @Override public void mouseReleased(MouseEvent arg0) { } }