tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christopher Schultz <ch...@christopherschultz.net>
Subject Re: GC Problem
Date Fri, 01 May 2009 16:46:16 GMT
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Pid,

On 4/29/2009 9:55 AM, Pid wrote:
> S Arvind wrote:
>> Is there any good settings for GC for tomcat running in server with 4GB and
>> Quad Core processor. I bascially need GC parameter for RESOURCE HUNGRY WEB
>> APPLICATION
> 
> Why not try fixing the memory leak instead?
>
> Reconfiguring the JVM params, memory or GC will only delay the
> inevitable OutOfMemory error.

+1

> The "YourKit" profiler is frequently mentioned on this list, but there
> are others.

You can also use the simple scripts below to help you out. We were
getting OOME errors after several years of smooth sailing, and it turned
out that our load had simply increased to the point that we needed to
allocate more than 64MB heap to our webapp. We used the scripts below to
monitor everything for a few weeks afterward.

Enjoy,
- -chris

HealthCheck.jsp
- ---------------
<?xml version="1.0" encoding="UTF-8" ?>
<%@ page
    contentType="text/xml; charset=UTF-8"
    session="false"
    language="java"
    import="
        java.lang.Runtime,
        java.sql.Connection,
        java.sql.PreparedStatement,
        java.sql.ResultSet,
        java.sql.SQLException,
        javax.sql.DataSource,
        javax.naming.Context,
        javax.naming.InitialContext,
        javax.naming.NamingException,
        org.apache.tomcat.dbcp.dbcp.BasicDataSource
    "
%><%!
    private DataSource getDataSource()
       throws NamingException
    {
        Context ctx = new InitialContext();

        DataSource ds =
(DataSource)ctx.lookup("java:/comp/env/jdbc/YOUR-DATASOURCE-NAME");


        if(null == ds)
                throw new NamingException("Cannot obtain DataSource");

        return ds;
    }

    private String escapeQuotes(Object o)
    {
        String s;

        if(o instanceof String)
            s = (String)o;
        else if(null == o)
            s = "null";
        else
            s = o.toString();

        s.replaceAll("\"", "&quot;"); // "

        return s;
    }
%><health-report time="<%= System.currentTimeMillis() %>">
<%
    response.setCharacterEncoding("UTF-8"); // Just in case

    Runtime runtime = Runtime.getRuntime();
    long maxMemory = runtime.maxMemory();
    long totalMemory = runtime.totalMemory();
    long freeMemory = runtime.freeMemory();

    int maxActiveConnections = 0;
    int maxIdleConnections = 0;
    int minIdleConnections = 0;
    int activeConnections = 0;
    int idleConnections = 0;
    long checkoutDelay = 0;

    boolean connectionOkay = false;

    Connection conn = null;
    PreparedStatement ps = null;
    ResultSet rs = null;

    try
    {
        DataSource ds = getDataSource();

        if(ds instanceof BasicDataSource)
        {
            BasicDataSource bds = (BasicDataSource)ds;

            maxActiveConnections = bds.getMaxActive();
            maxIdleConnections = bds.getMaxIdle();
            minIdleConnections = bds.getMinIdle();
            activeConnections = bds.getNumActive();
            idleConnections = bds.getNumIdle();
        }

        long elapsed = System.currentTimeMillis();
        conn = ds.getConnection();

        checkoutDelay = System.currentTimeMillis() - elapsed;

        ps = conn.prepareStatement("SELECT 1"); // Simple query
        rs = ps.executeQuery();

        connectionOkay = rs.next();
    }
    catch (Throwable t)
    {
        while(null != t)
        {
%>  <error type="<%= t.getClass().getName() %>">
<%      if(null != t.getMessage() && !"".equals(t.getMessage().trim())) { %>
    <message><%= escapeQuotes(t.getMessage()) %></message>
<%      }
%>    <stack-trace>
<%
        StackTraceElement[] st = t.getStackTrace();

        for(int i=0; i<st.length; ++i)
        {
            StackTraceElement ste = st[i];
%>    at <%= ste.getClassName() %>.<%= ste.getMethodName() %>(<%=
ste.getFileName() %>:<%= (ste.isNativeMethod() ? "native" :
ste.getLineNumber()) %>)
<%
        }
%>
    </stack-trace>
  </error>
<%
            t = t.getCause();
        }
    }
    finally
    {
        try { if(null != rs) rs.close(); } catch (SQLException sqle)
        { sqle.printStackTrace(); }
        try { if(null != ps) ps.close(); } catch (SQLException sqle)
        { sqle.printStackTrace(); }
        try { if(null != conn) conn.close(); } catch (SQLException sqle)
        { sqle.printStackTrace(); }
    }
%>
  <vm-info vendor="<%=
escapeQuotes(System.getProperty("java.vm.vendor")) %>" name="<%=
escapeQuotes(System.getProperty("java.vm.name")) %>" version="<%=
escapeQuotes(System.getProperty("java.vm.version")) %>" info="<%=
escapeQuotes(System.getProperty("java.vm.info")) %>"/>
  <memory-info max="<%= maxMemory %>" total="<%= totalMemory %>"
free="<%= freeMemory %>" />
  <jdbc-datasource-info maxActive="<%= maxActiveConnections %>"
active="<%= activeConnections %>" maxIdle="<%= maxIdleConnections %>"
minIdle="<%= minIdleConnections %>" idle="<%= idleConnections %>"
okay="<%= connectionOkay %>" checkoutTime="<%= checkoutDelay %>" />
</health-report>




health-report-memory-parser.pl
- ------------------------------
#!/usr/bin/perl
#
# Parses output from the HealthReport.jsp script to generate
# a single, tab-separated line of text showing the current time
# (in seconds) and the max, total, and free memory (in bytes).
#
# This can then be used to easily graph memory usage in a running
# Java VM.
#
my($timestamp);
my($maxMem);
my($totalMem);
my($freeMem);

while(<>) {
    if ( /<health-report.*time="([0-9]+)"/ ) {
        $timestamp = $1;

        # Convert timestamp from milliseconds to seconds
        $timestamp = int($timestamp / 1000);
    }
    elsif ( /<memory-info/ ) {
        ($maxMem) = /max="([0-9]+)"/;
        ($totalMem) = /total="([0-9]+)"/;
        ($freeMem) = /free="([0-9]+)"/;
    }
    elsif ( /<error/ ) {
        $maxMem = "ERROR";
    }
}




Then, write a script like this and run it every minute or so:

#!/bin/sh
wget -qO http://host/path/to/HealthCheck.jsp \
    | health-report-memory-parser.pl \
    >> memory-usage.txt

Graph that baby using your favorite tool and see if the memory usage
graph looks good. It should look like /\/\/\/\/\/\/\/\/\/\/\/\/\/\
and not like
                  /
                 /
                /
             /\/
            /
           /
        /\/
       /
      /
     /

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkn7J1gACgkQ9CaO5/Lv0PA5HQCeILlscpfNZXs8VXnG8xdPznXp
vFEAnjkRwD5G/LEIofWhJMaFmG+ZtY1b
=LYyX
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message