Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


¿Las clases Java de ByteBuffer / IntBuffer / ShortBuffer son rápidas?

Estoy trabajando en una aplicación de Android (en Java, obviamente) y recientemente he actualizado mi código de lector UDP. En ambas versiones, configuré algunos buffers y recibo un paquete UDP:

byte[] buf = new byte[10000]; short[] soundData = new short[1000]; DatagramPacket packet = new DatagramPacket (buf, buf.length); socket.receive (packet); 

En la versión inicial, puse los datos de nuevo juntos un byte a la vez (en realidad es 16 datos de audio PCM):

 for (int i = 0; i < count; i++) soundData[i] = (short) (((buf[k++]&0xff) << 8) + (buf[k++]&0xff)); 

En la versión actualizada, usé algunas herramientas de Java que no conocía cuando empecé:

 bBuffer = ByteBuffer.wrap (buf); sBuffer = bBuffer.asShortBuffer(); sBuffer.get (soundData, 0, count); 

En ambos casos, "count" se está poblando correctamente (he comprobado). Sin embargo, parece que hay nuevos problemas con mi streaming de audio – tal vez no se está manejando lo suficientemente rápido – que no tiene ningún sentido para mí. Obviamente, el código del búfer está compilando en mucho más que tres declaraciones del código de JVM, pero parece seguro como una suposición razonable cuando comienzo esto que la 2da versión sería más rápida que la 1ra.

Patentemente, no estoy insistiendo en que mi código tiene que utilizar buffers Java NIO, pero a primera vista, al menos, parece como un mo 'betta' para ir sobre esto.

¿Cualquier persona consiguió cualquier recomendación para un lector rápido, simple del Java UDP y si hay una "manera generalmente aceptada mejor" ??

Gracias, R.

    3 Solutions collect form web for “¿Las clases Java de ByteBuffer / IntBuffer / ShortBuffer son rápidas?”

    En general, trabajar directamente con tipos primitivos va a ser más eficiente que trabajar con objetos, ya que evita algunos de los gastos generales de creación de objetos, llamadas a funciones, etc.

    Hay razones para utilizar los objetos de utilidad distintos de la velocidad: conveniencia, seguridad, etc.

    La mejor manera de probar la diferencia en este caso particular sería medirla realmente. Pruebe los dos métodos con un conjunto de datos grande y tiempo. Entonces, usted puede decidir si vale la pena los beneficios en este caso.

    También puedes usar el profiler de Android para ver dónde están realmente tus problemas. Vea TraceView .

    Su código sería más eficiente si en vez de leer un paquete en una matriz de bytes (copiando los datos de un buffer nativo en la matriz) y luego envolviéndolo en un nuevo ByteBuffer (creando un nuevo objeto) y convirtiéndolo a un ShortBuffer (creando un Nuevo objeto), configuró sus objetos una sola vez y evitó la copia.

    Puede hacerlo usando DatagramChannel.socket () para crear su socket, luego conectándolo como de costumbre y usuing socket.getChannel () para obtener un objeto DatagramChannel. Este objeto le permitirá leer paquetes directamente en un ByteBuffer existente (que debe crear con ByteBuffer.allocateDirect para obtener la máxima eficiencia). Usted puede entonces nosotros comoShortBuffer () apenas una vez para crear una visión de sus datos como cortocircuitos, y leer de ese ShortBuffer después de cada vez que usted rellena el ByteBuffer.

    El código se ve así:

      DatagramSocket socket = DatagramChannel.socket(); // code to connect socket DatagramChannel channel = socket.getChannel(); ByteBuffer buffer = ByteBuffer.allocateDirect (10000); // you may want to invoke buffer.order(...) here to tell it what byte order to use ShortBuffer shortBuf = buffer.asShortBuffer(); // in your receive loop: buffer.clear(); channel.receive(buffer); shortBuf.position(0).limit(buffer.position()/2); // may ignore a byte if odd number received shortBuf.get(soundBuf,0,shortBuf.limit()); 

    Usted debe encontrar esto es mucho más eficiente que su código anterior, ya que evita una copia entera de los datos y la conversión de formato se maneja a mano de código optimizado en lugar de manipulación de byte generado por el compilador que puede ser subóptima. Será algo más eficiente si usas el orden de bytes nativo de la plataforma (creo que Android usa el orden de bytes little-endian en todas las plataformas para las que está disponible, y tu código anterior parece ser big-endian, por lo que puede que no sea posible Para usted), en cuyo caso shortBuf.get () se convierte en una copia de memoria directa.

    Usaría DataInputStream para esta tarea, envuelto alrededor de un ByteArrayInputStream envuelto alrededor de la matriz del byte. Encapsula el cambio en readShort () sin los overheads de ByteBuffer.

    Alternativamente, puede leer directamente en un DirectByteBuffer a través de un DatagramChannel, en lugar de utilizar DatagramPacket & DatagramSocket. Actualmente usas una mezcla de java.net y java.nio.

    No esperaría grandes diferencias de rendimiento entre estos dos enfoques, pero esperaría que ambos fueran más rápidos que su enfoque híbrido.

      FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.