Скорость сокета составляет 120 МБ/с на компьютере, это нормально?

Я тестировал производительность передачи данных из программы на другой поверх сокета на одном компьютере, а скорость 120 Мбайт/с, это нормально?

Мои серверные и клиентские программы очень просты.

И мой компьютер - AMD Athlon X2 4000+, 4G DDR2 667, с окнами xp sp3.

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

UPDATE

Серверные и клиентские программы были на моем собственном компьютере, на одном компьютере. Сетевая карта ограничит скорость или нет?


Server.java

import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class SimpleServer {
    public static void main(String[] args) throws Exception {
        ServerSocket server = new ServerSocket(6666);
        Socket socket = server.accept();
        OutputStream output = socket.getOutputStream();

        byte[] bytes = new byte[10 * 1024]; // 10K
        for (int i = 0; i < bytes.length; i++) { bytes[i] = 12; } // fill the bytes

        // send them again and again
        while (true) {
            output.write(bytes);
        }
    }
}

Client.java

public class SimpleClient {

    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1", 6666);
        InputStream input = socket.getInputStream();
        long total = 0;
        long start = System.currentTimeMillis();

        byte[] bytes = new byte[10240]; // 10K

        // read the data again and again
        while (true) {
            int read = input.read(bytes);
            total += read;
            long cost = System.currentTimeMillis() - start;
            if (cost > 0 && System.currentTimeMillis() % 1000 == 0) {
                 System.out.println("Read " + total + " bytes, speed: " + (total / (1024.0*1024)) / (cost / 1000.0) + " MB/s");
            }
        }
    }

}

Ответ 1

Можете ли вы дать мне результат этой программы?

public class SimpleServer {
    public static void main(String[] args) throws Exception {
        ServerSocket server = new ServerSocket(6666);
        Socket socket = server.accept();
        OutputStream output = socket.getOutputStream();

        byte[] bytes = new byte[32*1024]; // 32K
        while (true) {
            output.write(bytes);
        }
    }
}
public class SimpleClient {
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1", 6666);
        InputStream input = socket.getInputStream();
        long total = 0;
        long start = System.currentTimeMillis();

        byte[] bytes = new byte[32*1024]; // 32K
        for(int i=1;;i++) {
            int read = input.read(bytes);
            if (read < 0) break;
            total += read;
            if (i % 500000 == 0) {
                long cost = System.currentTimeMillis() - start;
                System.out.printf("Read %,d bytes, speed: %,d MB/s%n", total, total/cost/1000);
            }
        }
    }
}

на моей машине печатает

Read 25,586,204,672 bytes, speed: 5,245 MB/s
Read 53,219,426,304 bytes, speed: 5,317 MB/s
Read 85,018,968,064 bytes, speed: 5,416 MB/s
Read 117,786,968,064 bytes, speed: 5,476 MB/s

Попробуйте отправить блоки 32K много раз (в течение как минимум 2 секунд), и вы должны получить 400 МБ/с или больше. например не менее 10 000 раз.

На очень быстрой машине вы можете получить 1 ГБ/с на одном клиенте. С несколькими клиентами вы можете получить 8 ГБ/с.

Вот пример

Сделать передачу файлов более эффективной Java


Если у вас есть карта на 100 Мб, вы можете ожидать около 11 МБ/с (байт в секунду).

Аналогично для 1 Gb ethernet вы ожидаете около 110 МБ/с

Для 10 Gig-E ethernet вы можете получить до 1 ГБ/с, но вы можете получить только половину этой системы unles syour, которая очень настроена.

Ответ 2

Вы передаете только 10 тыс. байт для выполнения теста. Накладные расходы на многое из того, что вы делаете, и такой небольшой набор данных может быть искажен этими накладными расходами. (например, создание сокетов, выделение памяти и т.д.). Вы должны создать и передать гораздо больший набор данных (десятки МБ +), чтобы получить более реалистичное представление о том, что происходит. Выполнение этого приведет к уменьшению накладных расходов, меньшей значимости в процессе передачи данных.

Вы также должны выполнить этот тест несколько раз ( > 10) и принять среднее значение, потому что ваш компьютер будет находиться под нагрузкой от служб, сетевых передач и т.д. в разные случайные моменты времени, и эти нагрузки повлияют на вашу скорость передачи, С помощью 10 итераций вы также можете отбросить любое время работы, которое необычно медленное, напримеp > 2 стандартных отклонения.

Ответ 3

Сетевая карта ограничит скорость или нет?

Вы используете 127.0.0.1 - локальный/loopback-адрес. Трафик с/на этот адрес не проходит через сетевую карту.

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


Было бы интересно сравнить результат, который вы получаете с эквивалентной парной клиент/сервер, написанной на C или С++.

Ответ 4

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

Ответ 5

WinXP не поддерживает масштабирование с автоматическим окном и, вероятно, размер буфера отправки/получения сокета слишком мал для теста пропускной способности.

Кроме того, FileInputStream (сокет использует FileInputStream практически) имеет меньший буфер char [] в Windows, чем Linux в собственном коде. Чтение/запись выполняется через вспомогательный буфер в стеке, и большой кусок, который вы положили, проходит через.

Использование большого прямого буфера (размером с буферов сокетов) - лучший выбор для пропускной способности.

Ответ 6

Ну, это интересно, но эта реализация nio была на одном уровне с предоставленным выше SimpleServer/SimpleClient (а иногда и фактически обыграла его) (Хотя это только при запуске в однопоточном режиме, который в любом случае является одним-единственным!!)

Оба SimpleServer/SimpleClient и nio IntegTestLocalhostThroughput.java предоставлены в этом каталоге...

https://github.com/deanhiller/webpieces/tree/master/core/core-asyncserver/src/test/java/org/webpieces/nio/api/throughput

Я просто подумал, что было довольно интересно, что nio в основном так же быстро, но масштабируется лучше, чем старый материал io.