LINUX.ORG.RU

Кто там кукарекал про С++?


1

8

Задача: разработать кроссплатформенное клиент-серверное приложение под Windows/Linux на С++ (boost, ace, etc.), клиент построчно считывает с консольки введёные числа, отправляет на сервер, сервер в ответ плюёт разложением чисел на простые множители. Стандартное тестовое задание, ничего интересного.

Ну что же, собрался духом, за вечер родил чуть около пол тысячи строк, чтоб всё как положено: асинхронность, многопоточность, все дела. Такое ощущение, коллеги, будто накормили грязью, кресты не умеют ни в замыкания, ни в нормальную асинхронность, ни в управление памятью, они вообще ничего не умеют. Вроде бы, написано 5 строк, а на деле почти не фига не делают, код раздут, абсолютно невыразителен, я уж не представляю что с ним будет, если его ещё раскидать на десяток классов, как это обожают делать отдельные особо одарённые личности.

К слову, скелет сервера получился не сильно отличающимся от того, что написано в доках буста.
Что это за вырвиглазие??

class server
{
public:
  server(boost::asio::io_service& io_service, short port)
    : io_service_(io_service),
      acceptor_(io_service, tcp::endpoint(tcp::v4(), port))
  {
    session* new_session = new session(io_service_);
    acceptor_.async_accept(new_session->socket(),
        boost::bind(&server::handle_accept, this, new_session,
          boost::asio::placeholders::error));
  }
  .......

Смеха ради, да и чтоб не вырвало от такого кода, накидал за полчаса решение на Haskell.
Что получилось:

  • Разбор параметров командной строки
  • Клиент-серверная архитектура
  • Полностью асинхронный многопоточный tcp-сервер
  • Поддержка unicode, IPv6 и BigInteger из коробки
  • Мемоизация (благодаря ленивости) из коробки
  • Полная кроссплатформенность (*nix, Mac OS, Windows etc.)
  • Правильность тривиально доказывается мат. индукцией по коду
  • Исходник чуть больше 60 строк (в 8 раз меньше, чем на крестах)

Если поднатужиться (я не стал) и заменить алгоритм нахождения простых чисел/простых множителей на более оптимальный, то ко всему прочему получаем автоматическую распараллелизацию алгоритмов из коробки (см. Data Parallel Haskell) и произодительность на уровне чистого Си/Фортрана.

Кто там пищал, что хаскель сугубо академический язык, что ничего реальго на нём написать невозможно? Кто там кукарекал про С++? Как вы с ним вообще работаете? Это же мазохизм в чистом виде (см. мыши и кактус)

★★★★★

Ответ на: комментарий от mix_mix

> вынеси в метод и не будет
Так вот у кого ООП головного мозга, теперь понятно.

А использование boost там, где он нафиг не нужен это не ООП головного мозга?

andreyu ★★★★★ ()
Ответ на: комментарий от LongLiveUbuntu

Хотеть уровня Netbeans )

мне почему-то хватало дефолтного вима + haddock

Waterlaz ★★★★★ ()
Ответ на: комментарий от LongLiveUbuntu

Хотеть уровня Netbeans )

Есть manate, творение сумрачного китайского гения ;)

Есть, кстати, EclipseFP но это больше прототип.

Macil ★★★★★ ()

Не люблю в таких темах участвовать, но замечу пару моментов: 1) по кросс-платформенности Хаскель у С++ с Бустом мощно отсасывает. (пример - Солярис) 2) Нет никакой «мемоизации (благодаря ленивоасти) из коробки»

ratatosk ()
Ответ на: комментарий от Macil

Хотя бы потому что некоторые хаскельные приложения вынуждены тащить за собой сторонние либы. А раз так, то почему бы не тащить и свои собственные.

что-то я не понял, о чем ты. Зачем тащить либы отдельно? Почему не в бинарнике?

Кроме того, динамическая линковка теоретически должна упрощать развертывание (при наличии стабильного ABI).

не понимаю, каким образом?

Ну и разделяемая память - не пустой звук вообще-то.

Особенно приятно, когда оказывается, что динамически слинкованные бинарники + их либы жрут больше памяти, чем статически слинкованные.

Waterlaz ★★★★★ ()
Ответ на: комментарий от vertexua

А хаскеллевский точно асинхронный? Скоро загнется если я буду подключаться и ничего не делать?

Включаем сервер, запускаем 10000 экзепляров клиентов, которые все требуют разложения чисел с 10000 по 20000

for((j=0;j<10000;j++)); do \
> echo "( for((i=10000;i<20000;i++)); do echo \$i; done | ./fact client ::1 12345 ) &"; \
> done | bash

Получаем fork: Resource temporarily unavailable, но не страшно, у нас есть уже открытый bash, в нём и проверяем:

mix_mix$ time echo 43423432234 | ./fact client ::1 12345 2>/dev/null
Answer := [2,7,13,13,3083,5953]

real	0m0.030s
user	0m0.003s
sys	0m0.007s

Будет время, проведу настоящее нагрузочное тестирование.

mix_mix ★★★★★ ()
Ответ на: комментарий от Waterlaz

не понимаю, каким образом?

Представь у тебя в GNU/Linux все пакеты статически слинкованы ;) И вместо обновления одной мелкой либы тебе нужно тянуть обновления для 10500 пакетов, ее использующих.

их либы жрут больше памяти, чем статически слинкованные

Жрут больше, зато память - разделяемая. Например, Qt и KDE ;)

Macil ★★★★★ ()
Ответ на: комментарий от Waterlaz

Особенно приятно, когда оказывается, что динамически слинкованные бинарники + их либы жрут больше памяти, чем статически слинкованные.

А про виртуальную память в ваших краях доводилось слышать?

geekless ★★ ()
Ответ на: комментарий от andreyu

А использование boost там, где он нафиг не нужен это не ООП головного мозга?

А использовать С++ там, где он нафиг не нужен это не ЦПП головного мозга?
А если серьёзно, то что использовать? Qt? Так это как мёртвому припарки.

mix_mix ★★★★★ ()
Ответ на: комментарий от geekless

А про виртуальную память в ваших краях доводилось слышать?

В случае GHC - все намного печальнее. Уж больно много он за собой тащит либ.

Недавно проводил эксперименты под виндой. Статический бинарник ~2 мегабайта, и динамический бинарник в ~180 килобайт + ~48 мегабайт различных либ.

Macil ★★★★★ ()
Ответ на: комментарий от Macil

Представь у тебя в GNU/Linux все пакеты статически слинкованы ;) И вместо обновления одной мелкой либы тебе нужно тянуть обновления для 10500 пакетов, ее использующих.

Я буду тянуть те пакеты, которые действительно нужно обновить(которые работали неправильно или не так, как надо)

Сейчас я смотрю на свой GNU/Linux и вижу:

1) Часто новая версия либы ломает старую программу. В программе А(версии 1.0) нашли ошибку, обновляю А до 2.0, которая требует foo_lib_2. Обновляю foo_lib и ломаю программу B, для которой еще не запилили поддержку foo_lib версии 2.

2) versioned symbols (говно по типу printf@@GLIBC_2.2.5). Обновив либу, я не уверен, используют ли мои приложения исправленный вариант бажной функции или нет. Я обновил glibc, а мои проги ссылаются на старые символы. Хуже того, часто одна программа юзает сразу несколько версий функции(например, посредством других либ).

Жрут больше, зато память - разделяемая. Например, Qt и KDE ;)

Иногда бывают приятные сюрпризы, когда это не помогает =)

Waterlaz ★★★★★ ()

Ну что же, собрался духом, за вечер родил чуть около пол тысячи строк, чтоб всё как положено: асинхронность, многопоточность, все дела.

С этого места тока мне стало смешно? И где же сие полутыщестроковоезавечересделанное чудо?

Если по делу - каждый инструмент хорош для своей задачи, и его хорошесть определяется в частности кривизной рук. Есть круг задач, в которых С++ гораздо лучше всего остального, и хаскеля в том числе.

AIv ★★★★★ ()
Ответ на: комментарий от geekless

Особенно приятно, когда оказывается, что динамически слинкованные бинарники + их либы жрут больше памяти, чем статически слинкованные.

А про виртуальную память в ваших краях доводилось слышать?

Опять этот детский сад. Да, слышали. Очень часто это не спасает. Особенно, когда либы большие, жирные и 90% их содержимого никто не юзает.

Waterlaz ★★★★★ ()
Ответ на: комментарий от Macil

~48 мегабайт различных либ.

Ну плюсовые libstdc++, libboost* и прочие (qt там всякие) тоже не 1 мегабайт весят.

mix_mix ★★★★★ ()
Ответ на: комментарий от Macil

В RSS идут только те страницы, которые реально используются.

geekless ★★ ()
Ответ на: комментарий от mix_mix

Алсо статически слинкованый Hello world на крестах весит столько же.

Тому виной во многом glibc.

Статически слинкованный пострипанный хеллоу ворлд на Си с glibc весит 600-700КБ. Сравни с FreeBSDшным 60-70КБ

Waterlaz ★★★★★ ()
Ответ на: комментарий от Waterlaz

Часто новая версия либы ломает старую программу.

Это случается не так часто. Мейнтейнеры обычно стараются поддерживать ABI, даже тогда, когда это становится тормозом (всякие function, function2, functionEx и т.п.).

А исправление багов вообще изменений в ABI не вызывает.

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

Так что поддержка динамической линковки и грамотное разделение рантайма на библиотеки - мощный политический инструмент по овладеванию миром. ;)

Macil ★★★★★ ()

Судя по всему участь хаскеля - служить инструментом для написания программ из 60-ти строк и средством потешить ЧСВ.

Legioner ★★★★★ ()
Ответ на: комментарий от Macil

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

но случается. И скачать новые версии пакетов, слинкованных с новой либой уж куда проще и надежнее.

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

Общепринятый - не значит, что хороший.

Так что поддержка динамической линковки и грамотное разделение рантайма на библиотеки - мощный политический инструмент по овладеванию миром. ;)

Ну разве что политический.

Waterlaz ★★★★★ ()
Ответ на: комментарий от mix_mix

Алсо статически слинкованый Hello world на крестах весит столько же.

Ну, это далеко не HelloWorld: Parsec, BlazeBuilder, ByteSyting, Text и т.д. HelloWorld занимает намного меньше.

Ну плюсовые libstdc++, libboost* и прочие (qt там всякие) тоже не 1 мегабайт весят.

Проблема в том, что программа с какого-то перепугу цепляет libHsghc, которая занимает ~30 мегабайт O_o.

Macil ★★★★★ ()
Ответ на: комментарий от Waterlaz

И в самом деле детский сад

детский сад

Особенно, когда либы большие, жирные и 90% их содержимого никто не юзает.

vadim@host3:~/tmp$ cat 1.cpp
#include <iostream>

int main()
{
	while (1)
	{
		std::cout << ".";
	}
}
vadim@host3:~/tmp$ g++ -O2 1.cpp
vadim@host3:~/tmp$ ./a.out > /dev/null

vadim@host3:~/tmp$ ldd ~/tmp/a.out | awk '{print $3}' | grep '^/' | xargs -L1 readlink -f | xargs du -hs
912K	/usr/lib/libstdc++.so.6.0.16
176K	/lib/libm-2.15.so
120K	/usr/lib/libgcc_s.so.1
1,9M	/lib/libc-2.15.so
vadim@host3:~/tmp$ ps o rss,vsize,cmd -p `pgrep a.out`
  RSS    VSZ CMD
  848   3204 ./a.out
geekless ★★ ()
Ответ на: комментарий от mix_mix

Алсо статически слинкованый Hello world на крестах весит столько же.

a.cpp

#include <cstdio>

int main()
{
	printf( "Hello world\n" );
}

$ g++ -Os -static -s ./a.cpp
$ ldd ./a.out 
	not a dynamic executable
$ du ./a.out 
776	./a.out
anonymous ()
Ответ на: Re: Кто-то должен был это запостить от anonymous

Почему я не люблю С++

«Почему я не люблю молотки: потому что бьет по пальцам»
Это не молотки бьют, это вы сами себя бьете молотком по рукам. Молоток не виноват.

С++ «виноват» только в том, что может много чего и многими путями. А значит программист на C++ должен прочитать чуть больше чем пару страниц в интернете и иметь опыт написания программ чуть сложнее чем «Hello world».

3) УТЕЧКИ УТЕЧКИ УТЕЧКИ

Расскажите, как вы это делаете?

P. S. Не являюсь фанатом C++, к такому выводу пришел когда начал копать что скрывается за выкриками «С++ отстой». Нашел только 2 реальных недостатка. Подскажете еще - буду только признателен. Но только с пруфами с без нубовских замашек.

Kroz ★★★★★ ()
Ответ на: комментарий от andreyu

60 строк={парсинг командной строки,много потоков,клиент-сервер,чтение с консоли и вывод,уникод} и это на серваки и на клиенте означает только одно: 1)кто то сделал 99% работы за афтара 2)что-то не сильно-тривиальное вызовет у афтара приступ баттхерт и приведет к написанию 7500 строк велосипедного кода потому что кто-то не сделал за афтара эту работу

ckotinko ☆☆☆ ()
Ответ на: комментарий от anonymous
vadim@host3:~/tmp$ cat 1.cpp
#include <iostream>

int main()
{
	while (1)
	{
		std::cout << ".";
	}
}
vadim@host3:~/tmp$ g++ -O2 -static -s 1.cpp
vadim@host3:~/tmp$ ldd a.out 
	не является динамическим исполняемым файлом
Status: 1
vadim@host3:~/tmp$ du -h a.out
1,2M	a.out
geekless ★★ ()
Ответ на: комментарий от Waterlaz

Общепринятый - не значит, что хороший.

Общепринятый - значит общепринятый. Вон C++, он тоже на волне общепринятости вылез. И Java. И даже разработчикам Ceylon приходится разыгрывать всю ту же карту «общепринятости».

И хаскелю придется играть по правилам. Как бы несовершенны они бы не были. А именно:

1. Запилить компактный и модульный рантайм. 2. Обеспечивать стабильный ABI. 3. Поддерживать динамические библиотеки.

Кстати, все вышеперечисленное может быть организовано и без поддержки LD_PRELOAD/DLL, а с помощью собственных велосипедов.

Macil ★★★★★ ()
Ответ на: комментарий от anonymous

При чем тут «комплексы», если ты не использовал функций крестовой stdlib? И соответственно, она была выкинута при линковке, вся. Это только ваше незнакомство с матчасть, не более.

geekless ★★ ()

Пишу на яве, скале, с++, objc, когда надо — на баше и php. А вы все еще пихаете один язык во все задачи? Тогда мы идем к вам.

note173 ★★★★★ ()

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

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

alex_custov ★★★★★ ()
Ответ на: комментарий от alex_custov

ты по молодости ещё не понимаешь, что выразительность гораздо важнее количества строк

выразительность

C++

Вы сделали мой день.

geekless ★★ ()

Исходник чуть больше 60 строк (в 8 раз меньше, чем на крестах)

производительность проверял? Просто ради интереса, дай этот проект человеку с прямыми С++ руками, и потом сравни его проект и свой со, скажем, 500-ми клиентами. Это не наезд, это реально интересно. Иначе всё это красивые слова. Давно известен тот факт, что иногда для оптимизации скорости работы кода этого самого кода нужно написать БОЛЬШЕ, а не меньше.

alex_custov ★★★★★ ()
Ответ на: комментарий от alex_custov

ты по молодости ещё не понимаешь, что выразительность гораздо важнее количества строк, и если вместо 100 строк лапши можно написать 150 строк, только с разбиением по классам, - лучше это сделать, т.к. читабельность возрастёт на порядок

Яро плюсую!!!

Kroz ★★★★★ ()
Ответ на: комментарий от ckotinko

диаграмма рисуется ДО НАПИСАНИЯ КОДА

это в книжке так написано. Если проект не состоит из 500 классов, её реально можно нарисовать и потом. Главное чтобы человек, который пишет код, не писал его по принципу «я уж не представляю что с ним будет, если его ещё раскидать на десяток классов».

alex_custov ★★★★★ ()
Ответ на: комментарий от geekless

При чем тут «комплексы», если ты не использовал функций крестовой stdlib?

а зачем их тут было использовать? я, например, не люблю iostream

Это только ваше незнакомство с матчасть, не более.

не нервничайте, конечно это мое незнакомство с матчастью, а не ваше желание показать, что hello world должен использовать libstdc++

anonymous ()
Ответ на: комментарий от alex_custov

читабельность возрастёт на порядок

За игру с абсолютными/относительными цифрами нужно давать по рукам, я щитаю.

Macil ★★★★★ ()
Ответ на: комментарий от anonymous

Совершенно очевидно, что речь шла о коде, использующем stdlib крестов. (Мы тут сейчас линковку обсуждаи — если что.) Ты тред вообще читал, или как истинный Ъ, только пару слов разглядел?

geekless ★★ ()
Ответ на: комментарий от geekless

Совершенно очевидно, что речь шла о коде, использующем stdlib крестов.

с какой радости? fltk вон на плюсах написан, а stdc++ не использует, я еще раз повторяю - это твои комплексы

Ты тред вообще читал

давай ссылку из которой очевидно «что речь шла о коде, использующем stdlib крестов», пока что это все похоже на твои личные фантазии

anonymous ()
Ответ на: комментарий от anonymous

хотя write таки не стандарт, а printf - вполне

Вообще-то write определен в POSIX. А то по контексту приходится угадывать, что речь идёт о C99. За пределами C99 «стандарта» нет? :}

geekless ★★ ()
Ответ на: комментарий от geekless

Вообще-то write определен в POSIX

речь шла про ЯП и его стандарт

За пределами C99 «стандарта» нет? :}

кто-то решил перейти на мелкие придирки, стандарты то они разные бывают, вот только код по таким стандартам не везде соберется

anonymous ()
Ответ на: комментарий от anonymous

статически слинкованый Hello world на крестах весит столько же.

a.cpp

#include <cstdio>

int main()

{

printf( «Hello world\n» );

}

От Си++ в этой программе - только имя заголовочного файла cstdio

tailgunner ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.