两种填充方式在同一个Object数组上的差异内存使用情况

时间:2016-07-07 17:13:56

标签: java arrays memory jdbc

我希望通过数组对象获得对象缓存 我写了一个测试代码,看看它是如何占用300万个类型对象的内存 它大约是200MB的Ram而且非常好(代码是PersonArray1)

但在我的真实项目中,我的数据是在DB(Mysql)中,必须将它们提取到数组中,所以我编写了一个代码并对其进行测试,但内存使用让我感到困惑! 因为我可以在不放入数据的情况下读取数据,而Ram的使用量大约为23MB,但是当我将它们放入数组时,只需要100,000个索引即可获得300MB的超大内存!!(代码是PersonArray2)

实在我必须有300万个指数
在我现在我的表中有100万行,我认为对于他们所有我需要大约3GB的Ram并且与第一种方式相比它不是很好
起初我认为它是由“ResultSet”或“Statement”对象拍摄的,但事实并非如此!
因为当我把它们放在数据存储器中时,为了看到45的取消注释线和43的备注线 无论如何,我认为我的代码中有一个错误,因为两个相同的数组在逻辑上没有不同,但为什么会发生这种情况以及如何纠正它?

    package test;

    public class Person {

            int province;
            int city;
            int area;
            long phone;
            int userType;
            int situation;
            int score;
            int uid;
            int priority;
            long date;
            String content;

        public Person(int province, int city, int area, long phone, int userType, int situation, int score, int uid, int priority, long date, String content) {
            this.province = province;
            this.city = city;
            this.area = area;
            this.phone = phone;
            this.userType = userType;
            this.situation = situation;
            this.score = score;
            this.uid = uid;
            this.priority = priority;
            this.date = date;
            this.content = content;
        }

    }


package test;

import java.util.Random;
import java.util.Scanner;

public class PersonArray1 {

    static Random r = new Random();

    public static void main(String[] args) {

        long t = System.currentTimeMillis();
        Person[] arr = new Person[3000000];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new Person(r.nextInt(1000), r.nextInt(1000), r.nextInt(1000), r.nextLong(),
                    r.nextInt(100), r.nextInt(5), r.nextInt(100), r.nextInt(100), r.nextInt(10000), r.nextLong(),
                    "Lorem ipsum is a pseudo-Latin text used in web design, typography, layout, "
                    + "and printing in place of English to emphasise design elements over content. "
                    + "It's also called placeholder (or filler) text. It's a convenient tool for "
                    + "mock-ups. It helps to outline the visual elements of a document or presentation,"
                    + " eg typography, font, or layout. Lorem ipsum is mostly a part of a Latin text by"
                    + " the classical author and philosopher Cicero. Its words and letters have been "
                    + "changed by addition or removal, so to deliberately render its content nonsensical;"
                    + " it's not genuine, correct, or comprehensible Latin anymore. While lorem ipsum's "
                    + "still resembles classical Latin, it actually has no meaning whatsoever. As Cicero's"
                    + " text doesn't contain the letters K, W, or Z, alien to latin, these, and others are"
                    + " often inserted randomly to mimic the typographic appearence of European languages, "
                    + "as are digraphs not to be found in the original.");
        }
        System.out.println(System.currentTimeMillis() - t);
        // using Scanner for dont aloowing to finish process and seeing Ram usage by task manager
        Scanner sc = new Scanner(System.in);
        sc.next();
    }
}


package test;

import java.sql.Connection;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import services.persistence2.DBServicesAutoCommit;

public class CreateTable {

    public static void main(String[] args) {

        // "DBServicesAutoCommit" is a static Connection Pool
        Connection con = DBServicesAutoCommit.getConnection();
        try {
            Statement ps = con.createStatement();
            ps.execute("CREATE TABLE `person`(\n"
                    + "`province` INT NOT NULL,\n"
                    + "`city` INT,\n"
                    + "`area` INT,\n"
                    + "`phone` bigint,\n"
                    + "`usertype` INT NOT NULL,\n"
                    + "`situation` TINYINT NOT NULL,\n"
                    + "`score` INT,\n"
                    + "`uid` INT NOT NULL,\n"
                    + "`priority` INT NOT NULL,\n"
                    + "`date` BIGINT NOT NULL,\n"
                    + "`content` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL\n"
                    + ") ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci;");
        } catch (Throwable ex) {
            Logger.getLogger(CreateTable.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}


package test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import services.persistence2.DBServicesManualCommit;

public class FillPersonDB {

    static Random r = new Random();
    private static String createPersons = "insert into person(province,city,area,phone,usertype,situation,score,uid,priority,date,content)values(?,?,?,?,?,?,?,?,?,?,?)";

    public static void createPersons() {
        PreparedStatement ps = null;
        Connection con = null;
        try {
            // "DBServicesManualCommit" is a static Connection Pool without auto commit
            con = DBServicesManualCommit.getConnection();
            ps = con.prepareStatement(createPersons);
            // it's take long time but you could to set for 50,000 and fill DB by 20 concurrent connections (multi thread) for just 5 minutes
            for (int i = 0; i < 1000000; i++) {
                ps.setInt(1, r.nextInt(1000));
                ps.setInt(2, r.nextInt(1000));
                ps.setInt(3, r.nextInt(1000));
                ps.setLong(4, r.nextLong());
                ps.setInt(5, r.nextInt(100));
                ps.setInt(6, r.nextInt(5));
                ps.setInt(7, r.nextInt(100));
                ps.setInt(8, r.nextInt(100));
                ps.setInt(9, r.nextInt(10000));
                ps.setLong(10, r.nextLong());
                ps.setString(11, "Lorem ipsum is a pseudo-Latin text used in web design, typography, layout, "
                        + "and printing in place of English to emphasise design elements over content. "
                        + "It's also called placeholder (or filler) text. It's a convenient tool for "
                        + "mock-ups. It helps to outline the visual elements of a document or presentation,"
                        + " eg typography, font, or layout. Lorem ipsum is mostly a part of a Latin text by"
                        + " the classical author and philosopher Cicero. Its words and letters have been "
                        + "changed by addition or removal, so to deliberately render its content nonsensical;"
                        + " it's not genuine, correct, or comprehensible Latin anymore. While lorem ipsum's "
                        + "still resembles classical Latin, it actually has no meaning whatsoever. As Cicero's"
                        + " text doesn't contain the letters K, W, or Z, alien to latin, these, and others are"
                        + " often inserted randomly to mimic the typographic appearence of European languages, "
                        + "as are digraphs not to be found in the original.");
                ps.addBatch();
                if (i % 10000 == 0) {
                    ps.executeBatch();
                    con.commit();
                }
            }
            ps.executeBatch();
            con.commit();
        } catch (SQLException ex) {
            Logger.getLogger(FillPersonDB.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            if (con != null) {
                try {
                    con.close();
                } catch (SQLException ex) {
                    Logger.getLogger(FillPersonDB.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException ex) {
                    Logger.getLogger(FillPersonDB.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
}


package test;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import services.persistence2.DBServicesManualCommit;

public class PersonArray2 {

    private static String getPersons = "select * from person limit 100000";

    public static void main(String[] args) {
        PersonArray2 pa = new PersonArray2();
        Person[] person = pa.getPersons();
        pa = null;
        System.gc();
        // using Scanner for dont aloowing to finish process and seeing Ram usage by task manager
        Scanner sc = new Scanner(System.in);
        sc.next();
    }

    public Person[] getPersons() {
        Statement s = null;
        Connection con = null;
        ResultSet rs = null;
        Person[] person = new Person[1000000];

        try {

            int c = 0;
            long l = System.currentTimeMillis();
            con = DBServicesManualCommit.getConnection();
            s = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
            s.setFetchSize(Integer.MIN_VALUE);
            rs = s.executeQuery(getPersons);
            System.out.println("before while");
            while (rs.next()) {
                // when i dont asign new Person Object to Array ram usage is very low but just asigning Object to array eaten memory a lot
                person[c] = new Person(rs.getInt(1), rs.getInt(2), rs.getInt(3), rs.getLong(4), rs.getInt(5), rs.getInt(6), rs.getInt(7), rs.getInt(8), rs.getInt(9), rs.getLong(10), rs.getString(11));
                // normal memory usage without putting into array
                //new Person(rs.getInt(1), rs.getInt(2), rs.getInt(3), rs.getLong(4), rs.getInt(5), rs.getInt(6), rs.getInt(7), rs.getInt(8), rs.getInt(9), rs.getLong(10), rs.getString(11));
                if (c++ % 10000 == 0) {
                    System.out.println("Current Index is :"+(c-1));
                }
            }
           System.out.println(System.currentTimeMillis() - l);
           System.out.println(person.length + "|" + person[99999].phone);
            return person;
        } catch (SQLException ex) {
            Logger.getLogger(PersonArray2.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        } finally {
            if (rs != null) {
                try {
                    rs.close();
                    rs = null;
                } catch (SQLException ex) {
                    Logger.getLogger(PersonArray2.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            if (s != null) {
                try {
                    s.close();
                    s = null;
                } catch (SQLException ex) {
                    Logger.getLogger(PersonArray2.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            if (con != null) {
                try {
                    con.close();
                    con = null;
                } catch (SQLException ex) {
                    Logger.getLogger(PersonArray2.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }
}

0 个答案:

没有答案