2013-10-05 4 views
2

У меня есть класс ниже.Создание Java-объектов для создания новых объектов

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

Мне нужно создать список объектов, следующий метод вызывается несколько раз (скажем, 10K или более раз)

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

Я использовал профайлер, чтобы увидеть объем памяти, и это увеличивает так много из-за создания объекта каждый раз. Есть ли лучший способ сделать это? Я пишу список на диск.

EDIT: Вот как я пишу, как только список полностью заполнен. Есть ли способ добавить, когда память выходит за пределы значения (размер списка).

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

Использование массивов было бы быстрее, если бы вы знали с самого начала, сколько объектов вы нуждаетесь. – GGrec

+1

Вам нужно постоянно хранить все элементы в списке? Если нет, вы можете переместить некоторые данные на диск в виде файла/db –

+0

Нет, я не смогу это узнать. – NEO

ответ

5

Я использовал профайлер, чтобы увидеть объем памяти, и это увеличивает столько за счет создания объекта каждый раз. Есть ли лучший способ сделать это?

Java Serialization не использует столько памяти в вашей ситуации. То, что он делает, это создать много мусора, гораздо больше, чем вы могли себе представить. Он также имеет очень подробный вывод, который можно улучшить с помощью сжатия, как и вы.

Простым способом улучшения ситуации является использование Externalizable вместо Serializable. Это может значительно сократить количество мусора и сделать его более компактным. Он также может быть намного быстрее с более низкой головой.

BTW Вы можете получить еще лучшую производительность, если вы используете пользовательскую сериализацию для самого списка.

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. 

Как вы можете видеть мои попытки сделать файл более компактным, а не сделал это быстрее, что является хорошим примером того, почему вы должны проверить улучшение производительности.

+0

Я выполнил с этим кодом. Это отчет памяти из предыдущего запуска http://commondatastorage.googleapis.com/naren%2FMem_2.html, и это из замещенного запуска кода http://commondatastorage.googleapis.com/naren%2FMem_1.html – NEO

+1

Вы можете видеть что большинство объектов, созданных при замене, - это строки в 'key' и' val', которые вы не можете избежать без существенных структурных изменений. –

0

Рассмотрите возможность использования быстрой сериализации. Он совместим с исходным кодом с сериализацией JDK и создает меньше наворотов. Кроме того, это превосходит большинство рутинных сериализаций «Externalizable», так как это не только сама реализация сериализации JDK, но также и неэффективные реализации In/Output stream of Stock JDK, которые ухудшают производительность.

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

Смежные вопросы