用于大图测量计算的JVM热点选项:垃圾收集

时间:2013-08-11 19:22:54

标签: java garbage-collection heap-memory

作为我的代码的一部分,我需要为具有70k顶点和700k边缘的图形计算一些中心度量。为此,我使用了数组和哈希映射数据结构。不幸的是,我在程序中间耗尽了内存。处理这种情况的最佳JVM热点参数是什么?这是我得到的例外:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.HashMap.createEntry(Unknown Source)
    at java.util.HashMap.addEntry(Unknown Source)
    at java.util.HashMap.put(Unknown Source)

所以我用-Xmx6g更改堆大小但是这个参数没有解决问题。我仍然有堆空间相同的问题。

在我的程序中,我想为每个节点计算一些度量,遗憾的是JVM保留所有节点的信息,并尝试按每个节点计算它。我想知道有没有办法以一种从内存中删除不需要的信息的方式更改JVM?例如,在计算70000个节点的1000个节点的度量后,我的代码崩溃了。无论如何在计算后从内存中删除与此1000个节点相关的信息?内存可以这种方式分配给其他节点。这与垃圾收集器有关吗? 这是我的代码(使用JUNG库)

public class FindMostCentralNodes {
    private DirectedSparseGraph<Customer, Transaction> network = new DirectedSparseGraph<Customer, Transaction>();
    static String dbName="SNfinal";
    private int numberofNodes=0;
    public static void main(String[] args) throws NumberFormatException, SQLException {
        FindMostCentralNodes f=new FindMostCentralNodes();
        int counter=1;
        DirectedSparseGraph<Customer, Transaction> tsn=f.getTSN();
        DistanceCentralityScorer<Customer,Transaction> scorer=new DistanceCentralityScorer<Customer,Transaction>(tsn,false,true,true);// un-weighted
        Collection<Customer> subscribers=tsn.getVertices();

        for(Customer node:subscribers){
            String sql="update Node set dist_centrality='"+scorer.getVertexScore(node)+"' where subscriber='"+node.getName()+"'";
            DatabaseManager.executeUpdate(sql,dbName);
            System.out.println("Update node centrality measures successfully!: "+counter++);
            node=null;
        }
    }
    public DirectedSparseGraph<Customer,Transaction> getTSN() throws NumberFormatException, SQLException{
        network= new DirectedSparseGraph<Customer,Transaction>();
        String count="select count(*) as counter from Node";
        ResultSet rscount=DatabaseManager.executeQuery(count, dbName);
        if(rscount.next()) {
            numberofNodes=rscount.getInt("counter");
        }
        Customer [] subscribers=new Customer[numberofNodes];
        String sql="select * from Node"; 
        ResultSet rs=DatabaseManager.executeQuery(sql, dbName);
        while(rs.next()){
            Customer sub=new Customer();
            sub.setName(rs.getString("subscriber"));
            network.addVertex(sub);
            subscribers[rs.getInt("nodeID")-1]=sub;
            sub=null;
        }
        String sql2="select * from TSN";
        ResultSet rs2=DatabaseManager.executeQuery(sql2, dbName);
        while(rs2.next()){
            Transaction transaction=new Transaction(Double.parseDouble(rs2.getString("weight")));
            network.addEdge( transaction, subscribers[rs2.getInt("callerNID")-1], subscribers[rs2.getInt("calleeNID")-1] );
            transaction=null;

        }
        //garbage
        rscount=null;
        rs=null;
        rs2=null;
        subscribers=null;
        return network;
    }


}

3 个答案:

答案 0 :(得分:1)

垃圾收集器将删除程序中的实时变量无法再访问的任何对象。它会在放弃并抛出OutOfMemoryError之前删除任何此类对象。如果您认为在内存中保留了太多对象,那么第一个操作过程就是放弃您不需要的任何对象,以便它们不再可访问。由于您尚未向我们展示任何代码,因此我们无法建议您进行任何具体更改。

如果修剪不必要的对象,但仍然没有足够的内存,则可以研究使用更紧凑的方法来存储数据。关键技术是使用堆外存储;这比简单地使用对象更有用,但如果正确完成,则在空间和CPU方面可以更有效。参见:

答案 1 :(得分:0)

  • 尝试更改堆大小(-Xmx)参数
  • 如果您不在HashMap中使用某些项目,请使用HashMap.remove方法。如果没有对这些对象的更多引用,它们将由GC收集..
  • 使用Trove集合:http://trove.starlight-systems.com/overview

答案 2 :(得分:0)

我通过创建一个每次处理500个节点的整个算法的方法来解决问题。每次运行此方法后,GC现在可以删除整个变量,所以我的问题就解决了。