当前位置: 首页 > 面试题库 >

通过Java有效地通过套接字发送大int []

杨甫
2023-03-14
问题内容

我正在使用Java应用程序,需要通过套接字连接尽快将500,000个整数的数组从一台Android手机发送到另一台Android手机。无论是使用ObjectOutputStreams,ByteBuffers还是低级的掩码和移位转换,主要的瓶颈似乎都是在转换整数,以便套接字可以使用它们。通过套接字从一个Java应用程序向另一个Java应用程序发送int
[]的最快方法是什么?

这是到目前为止我尝试过的所有代码,其中包括我正在测试的LG Optimus V(600 MHz ARM处理器,Android 2.2)上的基准测试。

低电平遮罩和移位:0.2秒

public static byte[] intToByte(int[] input)
{
    byte[] output = new byte[input.length*4];

    for(int i = 0; i < input.length; i++) {
        output[i*4] = (byte)(input[i] & 0xFF);
        output[i*4 + 1] = (byte)((input[i] & 0xFF00) >>> 8);
        output[i*4 + 2] = (byte)((input[i] & 0xFF0000) >>> 16);
        output[i*4 + 3] = (byte)((input[i] & 0xFF000000) >>> 24);
    }

    return output;
}

使用ByteBuffer和IntBuffer:0.75秒

public static byte[] intToByte(int[] input)
{
    ByteBuffer byteBuffer = ByteBuffer.allocate(input.length * 4);        
    IntBuffer intBuffer = byteBuffer.asIntBuffer();
    intBuffer.put(input);

    byte[] array = byteBuffer.array();

    return array;
}

ObjectOutputStream:3.1秒(我尝试使用DataOutPutStream和writeInt()而不是writeObject()对此进行了变体,但是并没有太大的区别)

public static void sendSerialDataTCP(String address, int[] array) throws IOException
{
    Socket senderSocket = new Socket(address, 4446);

    OutputStream os = senderSocket.getOutputStream();
    BufferedOutputStream  bos = new BufferedOutputStream (os);
    ObjectOutputStream oos = new ObjectOutputStream(bos);
    oos.writeObject(array);

    oos.flush();
    bos.flush();
    os.flush();
    oos.close();
    os.close();
    bos.close();

    senderSocket.close();
}

最后,我用来发送byte []的代码比intToByte()函数还要花费0.2秒的时间

public static void sendDataTCP(String address, byte[] data) throws IOException
{
    Socket senderSocket = new Socket(address, 4446);

    OutputStream os = senderSocket.getOutputStream();
    os.write(data, 0, data.length);
    os.flush();

    senderSocket.close();
}

我正在套接字的两边编写代码,因此我可以尝试各种字节序,压缩,序列化等。必须有一种方法可以在Java中更有效地进行此转换。请帮忙!


问题答案:

正如我在评论中指出的那样,我认为您正在打破处理器的限制。因为这可能对其他人有帮助,所以我将其分解。这是将整数转换为字节的循环:

    for(int i = 0; i < input.length; i++) {
        output[i*4] = (byte)(input[i] & 0xFF);
        output[i*4 + 1] = (byte)((input[i] & 0xFF00) >>> 8);
        output[i*4 + 2] = (byte)((input[i] & 0xFF0000) >>> 16);
        output[i*4 + 3] = (byte)((input[i] & 0xFF000000) >>> 24);
    }

该循环执行500,000次。您的600Mhz处理器每秒可以处理大约600,000,000次操作。因此,循环的每次迭代将为每个操作消耗大约1/1200秒。

同样,使用非常粗糙的数字(我不知道ARM指令集,因此每个动作可能或多或少),这是一个操作计数:

  • 测试/分支:5(检索计数器,检索数组长度,比较,分支,增量计数器)
  • 掩码和移位:10 x 4(检索计数器,检索输入数组基数,相加,检索掩码,以及移位,乘法计数器,相加偏移量,相加到输出基数,存储)

好的,所以从粗略的角度来看,此循环 最多
需要55/1200秒或0.04秒。但是,您没有处理最佳情况。一方面,对于如此大的阵列,您将不会从处理器缓存中受益,因此,您将在每个阵列存储和加载中引入等待状态。

另外,我描述的基本操作可能会也可能不会直接翻译成机器代码。如果没有(我怀疑没有),那么循环将比我所描述的花费更多。

最后,如果您真的很不幸,JVM尚未对您的代码进行JIT编辑,因此对于循环的某些部分(或全部),它解释字节码而不是执行本机指令。我对Dalvik的了解不足,无法对此发表评论。



 类似资料:
  • 问题内容: 您好,我尝试使用Java中的客户端-服务器类发送文件。由于某种原因,当调用发送文件的方法时,套接字关闭。这是代码: 和来自客户端的代码: 和我得到的错误消息:严重:null java.net.SocketException:套接字已关闭 我对此并没有真正的经验,所以如果有帮助的话会很棒。 问题答案: 该方法返回一个,代表它实际读取的字节数。不能保证从字节数组中读取所需的字节数。它通常会

  • 我正试图通过Java的socket发送一个custome对象。我知道我需要将具有我需要发送的对象的类放在相同的包中,具有相同的serialVersionUID并实现Serializable。我已经这样做了,但我仍然不能通过套接字发送对象。我错在哪里了? 以下是客户端代码: 客户端中的类用户 发送user类对象的代码: 这里是服务器的代码: user类的代码:与客户端的user完全相同(我从客户端复

  • 问题内容: 我有2个java netbeans项目,一个是Server,另一个是Client。我已经创建了一个Message类,该类要传递给服务器,并在服务器上进行修改后以另一种方式返回给客户端。我在两个项目中都包含了Message类。我使用和传递对象。服务器和客户端之间的连接正常,并且对象通过,但在服务器上,当我从using 方法读取对象时,将其类型转换为类。但是在服务器上抛出 ClassNot

  • 问题内容: 我有工作的服务器和客户端应用程序,它们在发送小文件时可以完美工作,但是当我尝试通过套接字发送例如700mb的电影文件时,它给了我 我在互联网上搜索并找到了一些有关发送大文件的教程,但并不太了解它们,但是我认为我的麻烦在于编写文件。 这是服务器用来写入我的文件的代码: 这是我的客户用来发送文件的代码: 问题答案: 它之所以给您,是因为您试图在发送之前将整个文件读入内存。这完全是100%完

  • 我有一个问题,然后通过套接字发送列表,它必须是字节样的对象,好吧,我可以转换它字符串,然后做,但问题是字符串,这是很难重建它 列表从字符串,和从库 没有工作,然后我有这样的东西: 这就是问题所在,我必须拥有这些对象,我的问题是如何发送python对象而不需要将其转换为字符串,或者类似于JSON之类的对象符号? 这可以通过Python套接字文档在基本套接字服务器上进行测试。 失败的文本评估: 错误:

  • 问题内容: 我有两个脚本,Server.py和Client.py。我有两个目标: 为了能够一次又一次地从客户端向服务器发送数据。 为了能够将数据从服务器发送到客户端。 这是我的Server.py: 这是我的客户: 该函数首次运行(“ e”进入服务器,我返回返回消息),但是如何使它一遍又一遍地发生(类似于聊天应用程序)?该问题在第一次之后开始。消息不会在第一次之后发送。我究竟做错了什么?我是pyth