2

私は以下のクラスを持っています。

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;
    }
}

オブジェクトのリストを作成する必要があります。次のメソッドが繰り返し呼び出されます (たとえば、10,000 回以上)

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

プロファイラーを使用してメモリのフットプリントを確認しましたが、毎回オブジェクトが作成されるため、メモリのフットプリントが大幅に増加します。これを行うより良い方法はありますか?リストをディスクに書き込んでいます。

編集:これは、リストが完全に入力されたら、私が書く方法です。メモリが値(リストのサイズ)を超えたら追加する方法はありますか?

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

2 に答える 2

5

プロファイラーを使用してメモリのフットプリントを確認しましたが、毎回オブジェクトが作成されるため、メモリのフットプリントが大幅に増加します。これを行うより良い方法はありますか?

あなたの状況では、Javaシリアライゼーションはそれほど多くのメモリを使用しません。そうすることで、想像をはるかに超える多くのゴミが生まれます。また、圧縮を使用して改善できる非常に詳細な出力もあります。

この状況を改善する簡単な方法は、Serializable の代わりに Externalizable を使用することです。これにより、発生するゴミを劇的に減らし、よりコンパクトにすることができます。また、オーバーヘッドが低いため、はるかに高速になります。

ところで、リスト自体にカスタムのシリアル化を使用すると、さらに優れたパフォーマンスを得ることができます。

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;
        }
    }
}

最終的に印刷します

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.

ご覧のとおり、ファイルをよりコンパクトにしようとした代わりに高速化されました。これは、パフォーマンスの改善をテストする必要がある理由の良い例です。

于 2013-10-05T16:42:23.380 に答える