The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



Вариант для распечатки  
Пред. тема | След. тема 
Форум Разговоры, обсуждение новостей
Режим отображения отдельной подветви беседы [ Отслеживать ]

Оглавление

Релиз языка программирования Go 1.14, opennews (??), 26-Фев-20, (0) [смотреть все]

Сообщения [Сортировка по времени | RSS]


68. "Релиз языка программирования Go 1.14"  +/
Сообщение от nelsonemail (??), 27-Фев-20, 11:56 
>> оператор проброса ошибок

это же полная дичь, как можно всерьёз говорить о каком-то надёжном коде, написанном на язычке, допускающим подобное
>> if err != nil

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

Ответить | Правка | Наверх | Cообщить модератору

75. "Релиз языка программирования Go 1.14"  +2 +/
Сообщение от Аноним (75), 27-Фев-20, 12:19 
Вы хоть разобрались бы, о чем речь. Под пробросом ошибок подразумевается, что вместо копипасты "if err!= nil {return err;}" на Rust можно написать что-нибудь в духе "let response = service.get_data()?;", и если из get_data вернулась ошибка Result::Err(error), то она вернется из функции, а если нет, то результат исполнения Result::Ok(response) распакуется и поместится в переменную response, а функция продолжит выполнение. Т.е. абсолютно то же, что и с Go, только тело функции не засрано бойлерплейтом. И даже более того, в Go 2.0, насколько я помню, подумывают добавить похожую фичу. К тому же, учитывая, что в Rust ошибки упакованы в алгебраический тип Result, семантика языка не даст их не проверить/не пробросить выше, и никакой линтер для этого, как в случае с Go, не нужен.

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

Ответить | Правка | Наверх | Cообщить модератору

81. "Релиз языка программирования Go 1.14"  +3 +/
Сообщение от PnD (??), 27-Фев-20, 13:42 
Из последнего, такая "троица":
* агент — демон на "голом" C (вообще-то "на голом" разве что ядра, реально в роли "фреймворков" glibc, libpthread, zlib и т.д.) — ≈2c CPU за сутки, 1.5 недели на написание/отладку. От 200к до 2М RSS (x86), в зависимости от багов glibc (внезапно, там кое-что может вообще никогда не вычищаться и это мало кого парит т.к. "не течёт же дальше"). Бинарник 28к (т.к. динамическая линковка). На самом деле, 28к для такой финтифлюшки — тоже безобразно много, но тут и 64бит и более-менее свежий GCC 7.4.1 — против компактности.

* Сервер-коллектор на golang (раньше вполне мог оказаться на python, но теперь всё убивает вопрос "какой версии"). ≈20с CPU за сутки (из них половина — GC), пара дней на написание/отладку. 4…8МБ RSS (т.к. GC). Бинарник 3МБ (всё статикой, "-ldflags "-s -w" --tags static_all").
На С такое даже пытаться бы не стал, т.к. не имею бесконечного времени. А так — почти честный демон (один форк со сбросом привилегий, но без второго с отвязкой от всяких консолей/fd).

* "Экспертная система" — псевдо-демон на баше. День на расписывание выходов "автомата", ещё день на зачистку багов (примерно в каждой строке). Главный баг (писать на баше) при этом сохраняется на неопределённое время. Вызываемые в процессе find/grep/etc. едят в среднем 3МБ RSS, но CPU за сутки набегает до 300с (и в дальнейшем ещё добавится некий logN от числа обрабатываемых отчётов).
Аналогичная функциональность сразу на каком-нибудь go заняла бы около недели времени т.к. изначально не было готовой концепции "как правильно". Или вот так как я сделал (из г&п) и затем переписать (опять таки +время, но можно разбить на более короткие/предсказуемые фазы и вообще переписку отдать пофессиональному кодеру).

Это я всё к тому, что не "игрушечный вариант С", а каждому свои задачи. Go свою нишу нашёл, а вот от "взятия на вооружение" rust пока отпугивает текущий состав комьюнити. (Во как я политкорректно выдал). И вообще есть риск что rust повторит судьбу haskel "прикольно но".

Ответить | Правка | К родителю #68 | Наверх | Cообщить модератору

146. "Релиз языка программирования Go 1.14"  +1 +/
Сообщение от anonymous (??), 29-Фев-20, 13:10 
> из них половина — GC

Использую активно Go с 2012-го года, но чтобы половина была сожрана GC -- такого ни разу не было. Хотя на старых версиях Go, и когда я ещё не умел писать на Go, GC бывало сжирал 30-40 процентов.

Можно на код глянуть? :)

Ответить | Правка | Наверх | Cообщить модератору

162. "Релиз языка программирования Go 1.14"  +1 +/
Сообщение от PnD (??), 02-Мрт-20, 11:16 
> Использую активно Go с 2012-го года, но чтобы половина была сожрана GC
> -- такого ни разу не было. Хотя на старых версиях Go,
> и когда я ещё не умел писать на Go, GC бывало
> сжирал 30-40 процентов.

  В данном случае (сервис крутится практически вхолостую, "коту нечего делать") — вполне нормально.
* "Холостой" экземпляр в паре A-S — вообще ничего не потребляет (кроме RSS). Т.к. один тред висит на futex() пока сигнал не случится, а payload ничего не делает пока сокет пустой.

> Можно на код глянуть? :)

  Да пожалуйста https://github.com/ds-voix/VX-PBX/tree/master/IPADDRD

Ответить | Правка | Наверх | Cообщить модератору

171. "Релиз языка программирования Go 1.14"  +/
Сообщение от anonymous (??), 03-Мрт-20, 11:13 
Если вам важны процессорные циклы и нагрузка на GC, то буду рад предложить PR, чтобы лёгким исправлением слегка поправить ситуацию. Актуально? :)
Ответить | Правка | Наверх | Cообщить модератору

172. "Релиз языка программирования Go 1.14"  +/
Сообщение от PnD (??), 03-Мрт-20, 13:19 
> Если вам важны процессорные циклы и нагрузка на GC, то буду рад
> предложить PR, чтобы лёгким исправлением слегка поправить ситуацию. Актуально? :)

  Просто ткните носом (любым удобным способом).
Здесь, повторюсь, оно не важно. Но это не значит, что мне не интересен принцип.
* Сейчас взял калькулятор, 20с на том хосте где крутится это ≈0.003% от местной "полезной нагрузки". Однако, это совсем другая проблема. И она (внезапно) про python.

** Там же, выше по каталогу, лежат куски от flowchart-based АТС. Которая прочно застряла в b2b по причине отсутствия фронт-энда с одной стороны и интеграции с популярными CRM — с другой. Здесь возможен как fixed-price, так и выпуск ООО с долями под проект. Проблема найти заинтересованного специалиста: задача (про фронт-энд) достаточно нестандартная.

Ответить | Правка | Наверх | Cообщить модератору

179. "Релиз языка программирования Go 1.14"  +/
Сообщение от anonymous (??), 08-Мрт-20, 14:46 
По-хорошему надо написать benchmark-тесты, найти узкие места и устранить. И обычно, когда пишут на Go, стараются в main-е держать лишь парсер флагов и запускатель когда и другого пакета. Таким образом легко становится делать тесты и разбираться почему что-то медленно работает.

Если это не очень актуально (как я понял), то, конечно же, лень тратить время на это. Поэтому давайте посмотрим хотя бы быстрым взглядом поверхностно (извиняюсь за низкое качество анализа):

1. Вы каждый раз выделаете огромный буфер:
buf := make([]byte, BUF_LEN)

Если убрать `go` от `serve`, то можно было бы один раз выделить этот буфер (просто вне `for`-а) и постоянно его использовать. Если `go` нужен. то можно постараться либо изменить serve (перенести функционал), чтобы ему не нужен был этот буфер, либо в крайнем случае хотя бы просто применить `sync.Pool` для переиспользования буферов. По факту в отдельной рутине (`go serve`) достаточно было оставить только ту часть, что с syscall-ами, ибо вычислительная часть занимает сильно меньше, что позволило бы сделать один статический буфер (и избежать даже `sync.Pool`).

Есть ощущение, что именно эта строчка и портит вам всю статистику.

2. Что такое `daemon`? Не вижу его в import-ах.

3.
            ipv4 = append(ipv4, fmt.Sprintf("%b %s", (head>>1), ip.String()))
...
    hostname = fmt.Sprintf("%s", buf[pointer+1:length-4-16])
...
    report := fmt.Sprintf("addr=%s\nhost=%s\n", addr.String(), hostname)
    if overhead {
        report += "overhead\n"
    }
... и т.п.

Это всё тоже в некоторых случаях нехило давит и на CPU и на GC. Опять же, sync.Pool + strings.Builder (вместо Sprintf).

Кроме того, преобразование []byte в string делает копию (давит и на CPU и на GC). Вы могли вообще без string тут обойтись (см. bytes.Builder, вместо strings.Builder).

То есть да, Sprintf удобен, но когда пишешь именно тот кусочек кода, где действительно важна производительность, то лучше избегать его использования.

---

В целом, если вам будет действительно важно что-то прооптимизировать на Go, то я буду рад разочек помочь. Если вам важно прооптимизировать именно эту программу, то с вашей стороны я бы попросил написать unit/integration тест для той части кода, что мы хотим оптимизировать. А я со своей стороны пообещаю добиться производительности близкой к Сишной без особых костылей.

Сделать unit/integration тест очень несложно: просто превратите listen_udp в функцию, которая принимает этот `pc` извне аргументом типа net.Conn и напишите тест, который вызывает эту функцию, посылает туда хотя бы парочку разных пакетов и проверяет правильность результата.

Я добавлю benchmark тест. Сделаю `go test ./ -bench=. -cpuprofile /tmp/cpu.pprof -memprofile /tmp/mem.pprof`, глянем на реально слабые места этой программы и исправим ;)

https://golang.org/pkg/testing/

Ответить | Правка | Наверх | Cообщить модератору

180. "Релиз языка программирования Go 1.14"  +/
Сообщение от anonymous (??), 08-Мрт-20, 14:48 
Прошу прощения за опечатки...

> запускатель когда и другого пакета.

->

> запускатель кода из другого пакета.

... и т.п. Только проснулся :)

Ответить | Правка | Наверх | Cообщить модератору

189. "Релиз языка программирования Go 1.14"  +1 +/
Сообщение от PnD (??), 11-Мрт-20, 15:00 
> 1. Вы каждый раз выделаете огромный буфер:
> buf := make([]byte, BUF_LEN)

  Мне самому глаза мозолит, но тут по большому счёту референсный кейс: "по-быстрому обслужи пришедшее соединение и форкни то что долгое в отдельный тред". Соответственно, просто переиспользовать в такой схеме не прокатит. Но таки да, make(buf) всё портит. Не сильно заморачиваясь, есть вариант выделить "кольцо" статикой…
* Альтернативно кон. автомат и пул воркеров как в схемах с nginx (и гонять туда данные по каналам? не, лучше сообщения "возьми этот буфер"), но тут это "из пушки по воробьям".

> Если убрать `go` от `serve`, то можно было бы один раз выделить
> этот буфер (просто вне `for`-а) и постоянно его использовать. Если `go`
> нужен. то можно постараться либо изменить serve (перенести функционал), чтобы ему
> не нужен был этот буфер, либо в крайнем случае хотя бы
> просто применить `sync.Pool` для переиспользования буферов. По факту в отдельной рутине
> (`go serve`) достаточно было оставить только ту часть, что с syscall-ами,
> ибо вычислительная часть занимает сильно меньше, что позволило бы сделать один
> статический буфер (и избежать даже `sync.Pool`).
> Есть ощущение, что именно эта строчка и портит вам всю статистику.

Насчёт syscall's — архи-разумная мысль. Обязательно попробую в след. раз. разнести мухи/котлеты.
sync.Pool + "кольцо" буферов — ага. Тогда вообще есть вариант сразу выпустить воркеров "статикой", по одному на буфер. Дальше "семафорить" или блокировкой, или каналы "сделай"/"сделал".

> 2. Что такое `daemon`? Не вижу его в import-ах.

Пакет go-daemon → "daemon".

>[оверквотинг удален]
>  report := fmt.Sprintf("addr=%s\nhost=%s\n", addr.String(), hostname)
>  if overhead {
>   report += "overhead\n"
>  }
> ... и т.п.
> Это всё тоже в некоторых случаях нехило давит и на CPU и
> на GC. Опять же, sync.Pool + strings.Builder (вместо Sprintf).
> Кроме того, преобразование []byte в string делает копию (давит и на CPU
> и на GC). Вы могли вообще без string тут обойтись (см.
> bytes.Builder, вместо strings.Builder).

  Да. Не слишком красиво/привычно (аналогичные "Sprintf()" есть в большинстве ЯП ), зато без дурных копий.

>[оверквотинг удален]
> программу, то с вашей стороны я бы попросил написать unit/integration тест
> для той части кода, что мы хотим оптимизировать. А я со
> своей стороны пообещаю добиться производительности близкой к Сишной без особых костылей.
> Сделать unit/integration тест очень несложно: просто превратите listen_udp в функцию,
> которая принимает этот `pc` извне аргументом типа net.Conn и напишите тест,
> который вызывает эту функцию, посылает туда хотя бы парочку разных пакетов
> и проверяет правильность результата.
> Я добавлю benchmark тест. Сделаю `go test ./ -bench=. -cpuprofile /tmp/cpu.pprof -memprofile
> /tmp/mem.pprof`, глянем на реально слабые места этой программы и исправим ;)
> https://golang.org/pkg/testing/

Да, идею я понял: для бенча нужна точка куда удобно напихать данных.
Соответственно, "хороший тон" делать так "из коробки". Конкретно здесь — вынести начало обработки пакета в новую функцию (? +пенальти на вызов. Или тесты в GO умеют изображать работу net-сокетов?).
Быстро не обещаю т.к. конкретно этот код "сделал-работает-забыл". Или "на досуге потренироваться", или подвернётся что-нибудь более требовательное к качеству.

Ответить | Правка | К родителю #179 | Наверх | Cообщить модератору

183. "Релиз языка программирования Go 1.14"  +/
Сообщение от Аноним (-), 08-Мрт-20, 23:06 
> Использую активно Go с 2012-го года, но чтобы половина была сожрана GC
> -- такого ни разу не было.

А ты попробуй покодить как вон там в fuchsia - драйверок ФС, какой, чтоли. И посмотри чего будет дальше, и почему хипстеры такой languages.md, или как там его накорябали :)

Ответить | Правка | К родителю #146 | Наверх | Cообщить модератору

Архив | Удалить

Рекомендовать для помещения в FAQ | Индекс форумов | Темы | Пред. тема | След. тема




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру