Проблема производительности с помощью потоков Объекта Javas с Сокетами

Я пытаюсь сделать локальный IPC с помощью Сокетов и Объектных потоков в Java однако, я вижу низкую производительность.

Я тестирую время ping отправки объекта через ObjectOutputStream к получению ответа через ObjectInputStream по Сокету.

Вот проситель:

public SocketTest(){

    int iterations = 100;
    try {
        Socket socket = new Socket("localhost", 1212);

        ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream()); 
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream()); 

        double start = System.currentTimeMillis();
        for (int i = 0; i < iterations; ++i) {

            Request request = new Request();
            objectOutputStream.writeObject(request);

            Response response = (Response)objectInputStream.readObject();
        }
        double finish = System.currentTimeMillis();
        System.out.println("Per ping: " + (finish - start) / iterations );

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

Вот респондент:

public ServerSocketTest(){

    try {

        ServerSocket serverSocket = new ServerSocket(1212);
        Socket socket = serverSocket.accept();

        ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
        ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());

        Request request = (Request)objectInputStream.readObject();
        while (request != null) {

            Response response = new Response();
            objectOutputStream.writeObject(response);
            request = (Request)objectInputStream.readObject();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Результат, который я получаю:

На ping: 80.35

80 мс далеки для замедления для локального трафика.

Запрос и классы Ответа являются очень маленькими, и их сериализация быстра.

Я попытался наивно добавить:

socket.setKeepAlive(true);  
socket.setTcpNoDelay(true);

с небольшим эффектом.

выполнение ping localhost:

64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=64 time=0.035 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.037 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.049 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=3 ttl=64 time=0.039 ms  
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=4 ttl=64 time=0.056 ms  

также быстро.

Версия 1.6.0_05l Java, Работающая на RedHat 2.4

10
задан ROMANIA_engineer 10 April 2018 в 21:15
поделиться

4 ответа

Вы пробовали встраивать запросы и ответы в BufferedInputStream / BufferedOutputStream ? Это должно значительно улучшить выступления.

5
ответ дан 4 December 2019 в 03:38
поделиться

Я ожидаю, что вам придется вызвать objectOutputStream.flush() с обеих сторон, чтобы гарантировать, что данные будут немедленно отправлены в сеть. В противном случае стек TCP может ждать некоторое время для получения дополнительных данных, чтобы заполнить неполный IP-пакет.

-1
ответ дан 4 December 2019 в 03:38
поделиться

Помимо использования буферизованных потоков и вызова flush () перед каждым чтением, вы также должны сначала создать ObjectOutputStream на обоих концах. Кроме того, тестирование для readObject (), возвращающего null, бессмысленно, если вы не планируете вызывать writeObject (null). Тест для EOS с readObject () - это catch (EOFException exc).

0
ответ дан 4 December 2019 в 03:38
поделиться

Итак, создайте BufferedOutputStream и очистите его перед созданием BufferedInputStream. Чтобы избежать зависания.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4788782

говорится, что в соответствии с документацией

Если вы измените тестовый пример таким образом, что как сервер AServer, так и AClient создает ObjectOutputStream перед ObjectInputStream, тест не блокирует . Это ожидаемое поведение с учетом следующей документации :

Конструктор ObjectOutputStream:
Создает ObjectOutputStream, который записывает в указанный
OutputStream. Этот конструктор записывает заголовок потока сериализации в базовый поток; вызывающие могут немедленно очистить поток , чтобы гарантировать, что конструкторы для получения
ObjectInputStreams не будут блокироваться при чтении заголовка .

Конструктор ObjectInputStream:
Создает ObjectInputStream, который читает из указанного
InputStream. Заголовок потока сериализации считывается из потока и проверяется. Этот конструктор будет блокировать до тех пор, пока соответствующий
ObjectOutputStream не запишет и не очистит заголовок.

1
ответ дан 4 December 2019 в 03:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: