简体   繁体   English

Java创建新对象的性能

[英]Java creating new objects performance

I have the below class. 我有以下课程。

class MyObject implements Serializable {
    private String key;
    private String val;
    private int num;

    MyObject(String a, String b, int c) {
        this.key = a;
        this.val = b;
        this.num = c;
    }
}

I need to create a list of Objects, the following method is called repeatedly (say 10K times or more) 我需要创建一个对象列表,以下方法被反复调用(比如说10K次或更多)

public void addToIndex(String a, String b, int c) {
    MyObject ob = new MyObject(a,b,c);
    list.add(ob); // List<MyObject>
}

I used a profiler to see the memory footprint, and it increases so much due to creation of object everytime. 我使用了探查器来查看内存占用量,由于每次创建对象,它都会增加太多。 Is there a better way of doing this? 有更好的方法吗? I am writing the list then to disk. 我将列表写入磁盘。

EDIT: This is how I write once the list is fully populated. 编辑:这是清单写满后我的写法。 Is there a way to append once the memory goes beyond a value (size of list). 一旦内存超出值(列表大小),是否有一种附加方法。

ObjectOutputStream oos = new ObjectOutputStream(
                        new DeflaterOutputStream(new FileOutputStream(
                                list)));
                oos.writeObject(list);
                oos.close();

I used a profiler to see the memory footprint, and it increases so much due to creation of object everytime. 我使用了探查器来查看内存占用量,由于每次创建对象,它都会增加太多。 Is there a better way of doing this? 有更好的方法吗?

Java Serialization doesn't use that much memory in your situation. Java序列化在您的情况下不会使用太多内存。 What it does so is create a lot of garbage, far more than you might imagine. 这样做是造成大量垃圾,远远超出您的想象。 It also has a very verbose output which can be improved using compression as you do. 它还具有非常冗长的输出,可以像使用压缩一样进行改进。

A simple way to improve this situation is to use Externalizable instead of Serializable. 改善这种情况的一种简单方法是使用Externalizable而不是Serializable。 This can reduce the garbage produced dramatically and make it more compact. 这可以大大减少产生的垃圾并使它更紧凑。 It can also be much faster with lower over head. 降低头顶开销也可以更快。

BTW You can get even better performance if you use custom serialization for the list itself. 顺便说一句,如果您对列表本身使用自定义序列化,则可以获得更好的性能。

public class Main {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        List<MyObject> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            list.add(new MyObject("key-" + i, "value-" + i, i));
        }

        for (int i = 0; i < 10; i++) {
            timeJavaSerialization(list);
            timeCustomSerialization(list);
            timeCustomSerialization2(list);
        }
    }

    private static void timeJavaSerialization(List<MyObject> list) throws IOException, ClassNotFoundException {
        File file = File.createTempFile("java-serialization", "dz");
        long start = System.nanoTime();
        ObjectOutputStream oos = new ObjectOutputStream(
                new DeflaterOutputStream(new FileOutputStream(file)));
        oos.writeObject(list);
        oos.close();
        ObjectInputStream ois = new ObjectInputStream(
                new InflaterInputStream(new FileInputStream(file)));
        Object o = ois.readObject();
        ois.close();
        long time = System.nanoTime() - start;
        long size = file.length();
        System.out.printf("Java serialization uses %,d bytes and too %.3f seconds.%n",
                size, time / 1e9);
    }

    private static void timeCustomSerialization(List<MyObject> list) throws IOException {
        File file = File.createTempFile("custom-serialization", "dz");
        long start = System.nanoTime();
        MyObject.writeList(file, list);
        Object o = MyObject.readList(file);
        long time = System.nanoTime() - start;
        long size = file.length();
        System.out.printf("Faster Custom serialization uses %,d bytes and too %.3f seconds.%n",
                size, time / 1e9);
    }

    private static void timeCustomSerialization2(List<MyObject> list) throws IOException {
        File file = File.createTempFile("custom2-serialization", "dz");
        long start = System.nanoTime();
        {
            DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(
                    new DeflaterOutputStream(new FileOutputStream(file))));
            dos.writeInt(list.size());
            for (MyObject mo : list) {
                dos.writeUTF(mo.key);
            }
            for (MyObject mo : list) {
                dos.writeUTF(mo.val);
            }
            for (MyObject mo : list) {
                dos.writeInt(mo.num);
            }
            dos.close();
        }
        {
            DataInputStream dis = new DataInputStream(new BufferedInputStream(
                    new InflaterInputStream(new FileInputStream(file))));
            int len = dis.readInt();
            String[] keys = new String[len];
            String[] vals = new String[len];
            List<MyObject> list2 = new ArrayList<>(len);
            for (int i = 0; i < len; i++) {
                keys[i] = dis.readUTF();
            }
            for (int i = 0; i < len; i++) {
                vals[i] = dis.readUTF();
            }
            for (int i = 0; i < len; i++) {
                list2.add(new MyObject(keys[i], vals[i], dis.readInt()));
            }
            dis.close();
        }
        long time = System.nanoTime() - start;
        long size = file.length();
        System.out.printf("Compact Custom serialization uses %,d bytes and too %.3f seconds.%n",
                size, time / 1e9);
    }


    static class MyObject implements Serializable {
        private String key;
        private String val;
        private int num;

        MyObject(String a, String b, int c) {
            this.key = a;
            this.val = b;
            this.num = c;
        }

        MyObject(DataInput in) throws IOException {
            key = in.readUTF();
            val = in.readUTF();
            num = in.readInt();
        }

        public void writeTo(DataOutput out) throws IOException {
            out.writeUTF(key);
            out.writeUTF(val);
            out.writeInt(num);
        }

        public static void writeList(File file, List<MyObject> list) throws IOException {
            DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(
                    new DeflaterOutputStream(new FileOutputStream(file))));
            dos.writeInt(list.size());
            for (MyObject mo : list) {
                mo.writeTo(dos);
            }
            dos.close();
        }

        public static List<MyObject> readList(File file) throws IOException {
            DataInputStream dis = new DataInputStream(new BufferedInputStream(
                    new InflaterInputStream(new FileInputStream(file))));
            int len = dis.readInt();
            List<MyObject> list = new ArrayList<>(len);
            for (int i = 0; i < len; i++) {
                list.add(new MyObject(dis));
            }
            dis.close();
            return list;
        }
    }
}

prints finally 最终打印

Java serialization uses 61,168 bytes and too 0.061 seconds.
Faster Custom serialization uses 62,519 bytes and too 0.024 seconds.
Compact Custom serialization uses 68,225 bytes and too 0.020 seconds.

As you can see my attempts to make the file more compact instead made it faster, which is a good example of why you should test performance improvements. 如您所见,我试图使文件更紧凑而不是使其更快,这是为什么您应该测试性能改进的一个很好的例子。

Consider using fast-serialization. 考虑使用快速序列化。 It is source-level compatible to JDK-serialization, and creates less bloat. 它在源代码级别上与JDK序列化兼容,并减少了膨胀。 Additionally it beats most of handcrafted "Externalizable" serialization, as its not only the JDK-serialization implementation itself, but also inefficient In/Output stream implementations of stock JDK which hurt performance. 另外,它击败了大多数手工制作的“可外部化”序列化,因为它不仅具有JDK序列化实现本身,而且还降低了库存JDK的效率低下的In / Output流实现。

http://code.google.com/p/fast-serialization/ http://code.google.com/p/fast-serialization/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM