2010-10-14 12 views
12

¿Qué sintaxis usaría para obtener el número de bytes que representa una cadena y compararlos con el número de bytes que representa un ArrayList que contiene esa cadena, por ejemplo?¿Cómo obtener la cantidad de bytes serializados que representan un objeto Java?

Estoy utilizando un sistema de agente de agentes múltiples para enviar objetos a través de mensajes y quiero hacer un seguimiento de cuánto espacio ocupa cada mensaje. El método no tiene que ser exacto, siempre y cuando se amplíe proporcionalmente al tamaño real del objeto. P.ej. un vector de cadenas de longitud 4 informará tan pequeño que un vector de cadenas de longitud 5.

+0

Si no puede serializar porque demasiado caro: http://stackoverflow.com/questions/3069018/how- to-estimate-the-serialization-size-of-objects-in-java-without-actually-seria –

Respuesta

19

puede convertir el objeto en un conjunto de bytes con ObjectOutputStream y ByteArrayOutputStream:

public static int sizeof(Object obj) throws IOException { 

    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); 
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream); 

    objectOutputStream.writeObject(obj); 
    objectOutputStream.flush(); 
    objectOutputStream.close(); 

    return byteOutputStream.toByteArray().length; 
} 

acabo probado esto a cabo. El objeto cuyo tamaño está tratando de calcular necesita implementar Serializable (lo que significa que debe marcar cada objeto como tal simplemente para obtener su tamaño. Puede que no sea deseable). Escribí un programa rápido y sucio para probar esto:

import java.io.ByteArrayOutputStream; 
import java.io.IOException; 
import java.io.ObjectOutputStream; 
import java.io.Serializable; 

public class Sizeof { 

    public static class Person implements Serializable { 
     private String name; 
     private String age; 

     public Person(String name, String age) { 
      this.name = name; 
      this.age = age; 
     } 

     public String getName() { 
      return name; 
     } 

     public void setName(String name) { 
      this.name = name; 
     } 

     public String getAge() { 
      return age; 
     } 

     public void setAge(String age) { 
      this.age = age; 
     } 
    } 

    public static void main(String[] args) { 
     Person p1 = new Person("Alby", "20"); 
     Person p2 = new Person("VeryLongName", "100"); 
     String s1 = "This is it"; 
     String s2 = "This"; 

     try { 
      System.out.println("p1 " + sizeof(p1)); 
      System.out.println("p2 " + sizeof(p2)); 
      System.out.println("s1 " + sizeof(s1)); 
      System.out.println("s2 " + sizeof(s2));         
     } 

     catch(Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public static int sizeof(Object obj) throws IOException { 

     ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); 
     ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream); 

     objectOutputStream.writeObject(obj); 
     objectOutputStream.flush(); 
     objectOutputStream.close(); 

     return byteOutputStream.toByteArray().length; 
    } 
} 

Lo que me dio:

p1 85 
p2 94 
s1 17 
s2 11 

EDITAR

Stephen respuesta de C, se destacan algunas advertencias con este método.

+0

Muchas gracias. Exactamente el tipo de método que estaba buscando. Implementar Serializable para todas las clases en la jerarquía no es un problema. –

1

Puede serializar cada objeto en matrices y comparar la longitud de cada conjunto. Esto no es muy preciso, en el caso general, pero a menudo da una buena aproximación.

Eche un vistazo a ObjectOutputStream (que se puede utilizar para serializar un objeto y convertirlo en Bytes) y ByteArrayOutputStream (que se puede usar para contener los bytes serializados).

1

No creo que tengas más remedio que modificar tu código para que mida el tamaño de los mensajes en tiempo de ejecución.

Puede serializar objetos de ejemplo y capturar y medir el tamaño serializado. Esto tiene los siguientes problemas:

  • Nunca se puede estar seguro de que los objetos sean típicos.
  • Diversos efectos de agregación significan que es difícil deducir el tamaño de un mensaje del tamaño serializado de sus objetos componentes. (Por ejemplo, las firmas de clase solo se codifican una vez por serialización).
  • Este enfoque no le dice nada acerca de la frecuencia relativa de los diferentes tipos de mensajes.

Si puede manejar esto, obtendrá resultados más precisos si puede medir los mensajes reales. Esto probablemente implicaría modificar el marco del agente para contar, medir e (idealmente) clasificar los mensajes en diferentes tipos . El marco ya puede tener ganchos para hacer esto.

El método no tiene que ser preciso, siempre y cuando se ajuste proporcionalmente al tamaño real del objeto. P.ej. un vector de cadenas de longitud 4 informará tan grande que un vector de cadenas de longitud 5.

(supongo que significaba menor que ...)

Su ejemplo ilustra una de las problemas de tratar de estimar tamaños de objetos serializados. Una serialización de un Vector<String> de tamaño 4 podría ser más pequeña ... o más grande ... que un Vector<String> de tamaño 5. Depende de cuáles sean los valores de Cadena. Además, si un mensaje contiene dos objetos Vector<String>, el tamaño serializado ocupado por los vectores será menor que la suma de los tamaños de los dos vectores cuando se serializan por separado.

+0

Gracias por las advertencias. Tendré esto en cuenta si encuentro resultados inesperados/poco intuitivos con la serialización. –

1

Necesitaba comprobar esta escritura con precisión por memcache mientras investigaba un error del servidor donde se superaban los tamaños de Memcache. Para evitar la sobrecarga de una matriz de bytes grande para objetos grandes me ampliado OutputStream como un contador:

public class CheckSerializedSize extends OutputStream { 

    /** Serialize obj and count the bytes */ 
    public static long getSerializedSize(Serializable obj) { 
     try { 
      CheckSerializedSize counter = new CheckSerializedSize(); 
      ObjectOutputStream objectOutputStream = new ObjectOutputStream(counter); 
      objectOutputStream.writeObject(obj); 
      objectOutputStream.close(); 
      return counter.getNBytes(); 
     } catch (Exception e) { 
      // Serialization failed 
      return -1; 
     } 
    } 

    private long nBytes = 0; 

    private CheckSerializedSize() {} 

    @Override 
    public void write(int b) throws IOException { 
     ++nBytes; 
    } 

    @Override 
    public void write(byte[] b, int off, int len) throws IOException { 
     nBytes += len; 
    } 

    public long getNBytes() { 
     return nBytes; 
    } 
} 
Cuestiones relacionadas