Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Работа с сетью > Как разогнать сеть?


Автор: Lisus 2.6.2008, 21:23
Написал простенькую програмку: одна программа конектится (создаёт сокет к другой программе), и по циклу отправляет байт за байтом, затем стролько же байт читает из сокета. Вторая программа на ServerSocket читает байт и этот же байт отправляет обратно. Всё максимально тупо.

1-я программа в цикле:
Код

byte[] a = "как-то утром на расвете, заглянул в соседний сад".toByte();

for(int z=0; z<10000; z++)
{
os.write(a);
os.flush();
    for(int j=0; j<a.lenght; j++){
    is.read();
    }

}

у второй программы цикл аналогичен.
Код

int q=0;
int v=0;
while(need){
    int = is.read();
    os.write(q);
    v++;
    if(v==1000){/* Увеличиваем счётчик на 1 кб*/; v=0;}
}

Всякие там TRY{...} я опустил.

Запустил я обе программы, пропускная способность локалхоста оказалась всего-то 20бк\с(в среднем) в одну сторону. При этом ЦП грузится на полную. Получается что Ждава через 127.0.0.1 не способна передавать большие объемы. Тот же Диалоб - примерно 5-6 кб\с. Про 100 Мбит-ю сетевую карточку вообще молчу.(примерно 12Мб\с - почти в 300 раз) А если бы я ещё и обрабатывал информацию, тогда бы вообще ниже диалапа бы было....

Ну не должно же быть такого.
В чем дело?

а) Локалхост работает очень медленно, отсюда и все тормаза. Проверить на реальной сети не имею возможности.

б) Используемый мной цикл не оптимален. Как его переписать, чтобы было больше?

в) Классы Socket-ServerSocket - не оптимальны, они сами сильно тормрозят. В таком случае что использовать?

Где предел пропускной способности (ну скажем качаем файл с одного компа на другой) для программ на Java? Как "разогнать такие программы?"

Автор: v2v 2.6.2008, 22:15
как считаешь? формулу.

ты забываешь заголовки, которые передаются вместе с каждым твоим байтом , каждый по ~20 байт ..

Добавлено @ 22:27
в общем отправляй за один раз не один байт , а например 100 Кбайт, скорость значительно возрастёт.

Автор: Lisus 2.6.2008, 22:32
Цитата(v2v @  2.6.2008,  22:15 Найти цитируемый пост)
как считаешь? формулу. 



всмысле 100 мегабит в секудну(ну по сетке же большие файл просто летают) - это примерно 12 мегабайт в секунду. Если Вы про это. т.е примерно 12 000 000 байт в секунду. делим 12 000 000\ 20 000 = 600, а если учитывать поток в обе стороны (20 кб в одну сторону и 20 кб возвращается), то будет где-то 300 раз. Здесь ошибка раза в 2 - 4 погоды не делает. Всё равно очень много. 1 гиг качается по сети примерно 1 минуту. или 17 метров в секунду. через Мою Джава-программу этот гига-файл будет идти 50000 секунд = 833 минуты - 14 часов. Разница в скорости огромная.

Добавлено через 4 минуты и 24 секунды
А как сразу отправить не один байт?

ведь в Оутстринг запись идёт побайтно, то что потом многие эти байты в один пакет собираются - это другое дело. я и так байт-массив кидаю.

byte[] a....

Автор: v2v 2.6.2008, 22:40
как тебе ответить на вопрос, если ты даже не показал с какими типами данных работаешь?!

разбирайся

http://exampledepot.com/egs/java.net/WriteTextToSocket.html
http://exampledepot.com/egs/java.net/ReadFromSocket.html

Автор: Lisus 2.6.2008, 22:44
Типы данных?

яж вроде код даже вылажил
os и is - это outputStream и InputStream, которые получаются из Socket.
Чтоже ещё вас интересует Уважаемый?

Автор: COVD 2.6.2008, 22:58
Отправлять по 1 байту через tcp/ip крайне неэффективно, потому что данные передаются пакетами, у каждого пакета есть хедер и т.д. Поэтому скорость надо мерить интегрально, т.е. послать весь обьем данных в одну сторону. Сокетная имплементация отправит его пакетами оптимального размера. Надо учитывать также, что поскольку и клиент и сервер на одном компьютере, то это будет медленнее, чем на разных, соединенных в локальную сеть.  

Короче: высокие гипотезы относительно java, socket, localhost и пр. сомнительны.

PS Пока сочинял, v2v уже все сказал.

Автор: Lisus 3.6.2008, 00:36
Цитата(COVD @  2.6.2008,  22:58 Найти цитируемый пост)
Поэтому скорость надо мерить интегрально, т.е. послать весь обьем данных в одну сторону.


да я и сам понимаю, только как это сделать? ведь outputstream принимает только байты?
Т.е. мне в любом случае придётся разбивать блок данных на байты, чтобы переслать через OutputStream?

Или я не прав?

Автор: COVD 3.6.2008, 15:09
Мне кажется, вы неправильно интерпретируете результаты теста. В вашем тесте вы измеряете очевидно не скорость передачи данных вообще, а скорость передачи коротких сообщений примерно 50 символов на пакет. Максимальный же размер пакета примерно 1500 байт. Вы же отправляете свою строку и переключаетесь на прием. Сокет вынужден отослать это короткое сообщение, он не имеет возможности обьединить несколько коротких сообщений в один пакет, чтобы снизить накладные расходы. Он бы мог так делать если бы вы слали данные не переключаясь постоянно на прием-передачу. 

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

Автор: LSD 3.6.2008, 16:06
Цитата(COVD @  3.6.2008,  16:09 Найти цитируемый пост)
Проверить это предположение можно, если в вашем первоначальном тесте увеличить длину сообщения, например, в 10 раз.  Общее время на пересылку увеличится незначительно, а количество пересланных байтов возрастет в 10 раз. Соответственно, оценка скорости должна вырасти существенно. 

Или просто посмотреть в Диспетчере задач загрузку процессора и сети smile
Уверен, что проц будет 100% (или 50% если он двуядерный), а сеть ~1%.

Автор: Бонифаций 3.6.2008, 17:10
Код

// Create input and output streams to socket
PrintStream out = new PrintStream( s.getOutputStream()) ;


Пишем:

Код

// Write username to socket output
out.println( "Как то утром и тд");


Читаем:
Код

DataInputStream in = new DataInputStream(s.getInputStream());
String line = in.readLine();

Автор: Lisus 4.6.2008, 16:43
Цитата(LSD @  3.6.2008,  16:06 Найти цитируемый пост)
Или просто посмотреть в Диспетчере задач загрузку процессора и сети smile
Уверен, что проц будет 100% (или 50% если он двуядерный), а сеть ~1%. 


да проц на всю грузиться.

А сеть? Локал хост же там не отображается, т.е. на показатель не влияет.

Бонифаций
Я почему-то уверен, что DataInputStream и PrintStream - это надстройка над стримами, эти надстройки просто форматируют данные и переправляют их с помощью тех же read() write(), они просто форматируют, значит выигрыша в скорости не будет

Добавлено через 5 минут и 11 секунд
Ладно, теперь переделал клиент так, чтобы чтение и запись были ассинхронны.  В 2 потоках. Мерием скорость и получаем где-то 30кб\секунду. Но это тоже мало.

Автор: v2v 4.6.2008, 18:35
Lisus, ты видимо не понял что тебе толкуют ....

Автор: Lisus 4.6.2008, 19:08
Цитата(v2v @  4.6.2008,  18:35 Найти цитируемый пост)
Lisus, ты видимо не понял что тебе толкуют .... 


Возможно, ткните меня мордой в нужную строчку

Автор: LSD 5.6.2008, 13:04
Lisus, читай и пиши данные большими порциями 16 и более килобайт. И не читай по одному байту, читай сразу серию байт в буфер.

Автор: Proger10 4.2.2009, 01:16
Цитата(LSD @ 5.6.2008,  13:04)
Lisus, читай и пиши данные большими порциями 16 и более килобайт. И не читай по одному байту, читай сразу серию байт в буфер.

А кто знает, какими именно порциями читать выгоднее всего? Есть ли тут какая-то логика? smile

Автор: LSD 4.2.2009, 12:58
Цитата(Proger10 @  4.2.2009,  01:16 Найти цитируемый пост)
А кто знает, какими именно порциями читать выгоднее всего? Есть ли тут какая-то логика?

Лучше всего чтобы он совпадал по размеру, с буфером ОС, но поскольку он не известен, то можно этим и не заморачиваться. Всё равно прирост производительности будет небольшим.

Несколько килобайт, 8, 16, 32 будет вполне достаточно для большинства применений.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)