LINUX.ORG.RU

Опубликован выпуск «Learning Go» 0.3

 ,


0

3

Язык Go ещё очень молод и динамично развивается. Несмотря на то, что язык отлично документирован на golang.org, чувствуется недостаток книг.

На сегодняшний день «Learning Go» — наиболее объёмная книга по этому перспективному языку программирования, хотя, как пишет автор, Miek Gieben, это скорее слепок текущего состояния, чем её финальная версия.

Скачать

>>> Подробности



Проверено: JB ()
Последнее исправление: Dendy (всего исправлений: 2)

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

> Пока что ты храбро уклоняешься от прямых ответов.

А какие были прямые вопросы?

Кстати, с C++ не всё весело. Если в STL класть объекты — копирование, медленно. Если указатели --- то секс как со списками в Си (auto_ptr не пойдёт). Или переходить на контейнеры указателей из буста или самописные.

В общем, я в очередной раз понял что C++ хорош когда есть Qt.

Хотя я субъективен, в детстве меня сильно пичкали идеей «ни шагу без иерархии классов на 100 позиций», теперь у меня аллергия.

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

> Решает задачу получения готовой к запуску программы из прекомпилированных модулей.

Ясно. Я вообще-то спрашивал о проблеме, а не о задаче, но всё равно спасибо, что ответил.

А что?

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

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

> Я же ясно сказал - хотелось услышать о проблеме, которую решает статическая линковка.

Второй ответ катит?

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

> Второй ответ катит?

Ты пока не дал ни одного ответа.

Повторяю - меня интересует не задачи, решаемые статической линковкой, а проблемы, которые она решает. Или, если переформулировать: почему проблемы, вызываемые статичнской линковкой, меньше, чем проблемы, вызываемые динамическойю

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

На еще более высоком: задачу реюзания функциональности из конкретного языка программирования (или разных языков с совместимым ABI). Причем предполагается, что это простая, утилитарная функциональность, которая не должна требовать много кода, которая часто специфична для данного ЯП и которая не предполагает масштабирования. Словом, для которой нет смысла писать файловый сервер. Так к библиотекам подходят разработчики Plan 9.

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

> Или, если переформулировать: почему проблемы, вызываемые статичнской линковкой, меньше, чем проблемы, вызываемые динамическойю

Она решает проблемы, которые решаются revdev-rebuild на gentoo

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

> Повторяю - меня интересует не задачи, решаемые статической линковкой, а проблемы, которые она решает. Или, если переформулировать: почему проблемы, вызываемые статичнской линковкой, меньше, чем проблемы, вызываемые динамическойю

Так тебя интересуют проблемы, которые она решает, или проблемы, которые она вызывает? Или которые не вызывает?

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

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

Реюзани ка ты мне Gtk или Qt, статически слинкованные. Почему разработчиков библиотек должен заботить отдельно взятый убогий загрузчик плана?

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

> Реюзани ка ты мне Gtk или Qt, статически слинкованные.

Как было сказано, динамическая линковка - костыль вокруг bloated софта.

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

динамическая линковка - костыль вокруг bloated софта.

Какое прекрасное утро, однако.

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

сразу видно настоящего гогнокодера на жабе.

слаб заточен под аллокацию маленьких объектов, и устроен очень просто: есть блоки по 4-8-12-.. кб, размер которых подбирается для каждого размера объекта так, чтоб было меньше потерь на «лишнюю память». Принцип его работы таков:

#define BLOCK_SIZE 32768
struct slab_block {
   size_t nodesize;
//односвязный список свободных нод размера nodesize
   volatile void * first_free_node;
   ... other fields used by heap manager
   char items[0];
}__attribute__((aligned(BLOCK_SIZE)));
void * __fastcall slab_alloc(size_t size){
   slab_block * block;
   while((block=find_block_with_free_mem(heap, size))!=0)
   {
     do{
        register void * tmp=block->first_free_node;
        if(!tmp)break; //find another slab block
        void * tmp2=atomic_cmpxchg(
               &block->first_free_node, 
               tmp, //prev value
               *((void**)tmp);
        if(tmp2==tmp)return tmp;
     }while(true);//block was stolen by somebody else
   }
   return 0;
}    
сложность сего кода в 90% случаев - это
 
   call find_block_with_free_mem
1: mov reg1, mem
   mov eax, [reg1]
   lock cmpxchg mem, reg1
   cmp eax, reg1
   jne 1b
   return reg1
find_block_with_free_mem имеет сходную сложность.
Освобождение памяти состоит в нахождении по указателю начала блока(а т.к. он выровнен на BLOCK_SIZE, то нахождение состоит в операции (void*)((~(BLOCK_SIZE-1))&(long)ptr). после чего аналогичным кодом в список добавляется указатель на освобождённый блок. Всё. Никакой фрагментации. Всё что больше blocksize - отдельным mallocом. Ни один GC до такой простоты и быстроты аллокации не доберётся никогда.

Теперь еще один ньюанс: в С#ных программах деструктор не несет никакой осмысленной функции(разве что из него можно Dispose дергать) и у большинства классов его тупо нет. Так что мешает его дергать на выходе из scope? Конечно же нежелание считать ссылки, ведь мы не знаем когда его вызывать. А считать ссылки мы не будем, потому что для этого нужны страшные операции
   lock add dword [reg1+offset of refcount], 1
и
   lock xadd dword [reg1+offset of refcount], -1
   ja 1f
   call delete;reg1 = argument of delete
1:
Они такие медленные и страшные, и размер объектов вырастет на 4 или 8(на х64) байт, мы лучше будем возиться со списками, сканировать память, лишь бы только не использовать страшные атомарные операции. И в принципе жабистов можно понять: жаба ведь работает быстрее процессора, и для жабы slab ооочень тормозит.

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

это проблемы linuxа. я бы посмотрел на ололо, когда в их статической программе после пары mmapов скорость форкания так же бы упала: как бы они объяснили сей феномен.

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

> сразу видно настоящего гогнокодера на жабе.

Сразу видно настоящую школоту, нахватавшейся верхов, с амбициями и чсв.

Сравнение аллокатора и GC - это сравнение лопаты и пальца.

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

а что писать еще на go?

Бинго! Если найдешь применение для go, которое зарулит существующие языки, обязательно сообщи.

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

жабистов, я гляжу, задело. щас они нам расскажут, какие у них Продвинутые Технологии, Управление Памятью и Объектно-Ориентированный Подход. Наверняка жабисты знают кучу других Умных Слов, придуманных для того, чтобы объяснять клиентам, что жаба вовсе не тормозит, а наоборот очень быстро, объектно-ориентированно работает. А то, что память жрёт - это только кажется, на самом деле это жаба так памятью «управляет».

Но вот в чем беда: slab работает в ведре там, где надо быстро и часто получать и отдавать память. И выделяет он память в самой простой реализации за ~20 клоков процессора, не считая кэш-промахов и случая, когда в пуле нет свободного блока. И если к разработчикам ведра придут жабисты, и скажут им «а у нас есть Сборщик Мусора и Продвинутые Технологии», то разрабы ведра молча укажут жабистам на дверь. Просто потому, что пользователям нужно, чтоб ведро работало, а вовсе не лапша на ушах.

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

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

Да, такой багаж знаний весьма давит на плечи. Сочувствую. Предлагаю начать с простого - поискать докторские по разным GC на arxiv и написать авторам, как «нужно делать правильно».

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

я не понимаю «докторские». я понимаю оценки производительности выраженные в клоках процессора и байтах оперативной памяти. авторитет аятолл с arxiv.org для меня значения не имеет - мне за него никто не заплатит.

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

Доброе утро. И с праздником.

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

Какие проблемы решает молоток? Не задачи, а именно проблемы?

Назрел ответ, блин.

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

> сразу видно настоящего гогнокодера на жабе.

Голоса в голове тебя обманули - я не пишу на яве.

слаб

[куча понтов на Си и ассемблере поскипана]

SLAB allocator придуман уж лет 15-20 назад, и понтоваться его знанием может только школота.

Заменой GC он не является.

в С#ных программах деструктор не несет никакой осмысленной функции(разве что из него можно Dispose дергать) и у большинства классов его тупо нет. Так что мешает его дергать на выходе из scope?

Смарт-пойнтеры тоже изобретены очень давно и заменой GC не являются

я понимаю оценки производительности выраженные в клоках процессора и байтах оперативной памяти.

Для оценки алгоритма его нужно знать. Алгоритмов выделения и освобождения памяти в JVM ты не знаешь.

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

я не пишу на яве

жабист это не профессия а образ мыслей.

Заменой GC он не является.

обгоните по скорости, в чем проблема-то?

пока что я вижу, как жабисты изо всех сил соревнуются с стандартным libcшным mallocом, и даже научились его чуть-чуть обгонять. правда, меряются они с через жопу написанными программами на С++. Везде операторов new понатыкают вместо того, чтоб в стеке размещать временные объекты - и надо же, жаба быстрее. ну и накладные расходы на GC не учитывают бггг.

а потом клиенты, потыкавшись с жабой,пишут:

Yep, we've considered various solutions involving managing our own ref-counted slices of a single pre-allocated byte array - essentially writing our own slab allocator.

потому что кому нужна жаба, если для минимально вменяемой работы, ей нужно чтоб хип был заполнен не более, чем на 40%?

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

> >Заменой GC он не является.

обгоните по скорости, в чем проблема-то?

Замени штаны рубашкой

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

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

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

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

ну почему. если сделать IDE аля Delphi, то Go победит много языков и станет вторым Delphi. как замену жабе я go не рассматриваю. жаба зло, а go точно не зло. но пока и не добро тоже.

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

ну почему. если сделать IDE аля Delphi, то brainfuck победит много языков и станет вторым Delphi. как замену жабе я brainfuck не рассматриваю. жаба зло, а brainfuck точно не зло. но пока и не добро тоже.

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

Вклинюсь-ка.

Если в STL класть объекты — копирование, медленно. Если указатели --- то секс как со списками в Си (auto_ptr не пойдёт).

shared_ptr?

Или переходить на контейнеры указателей из буста или самописные.

Или переходить на сторонний фреймворк или писать свой - другого выхода в C++ нет.

В общем, я в очередной раз понял что C++ хорош когда есть Qt.

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

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

сарказм не оценил. bf точно делфями не станет :)

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

>Ни один GC до такой простоты и быстроты аллокации не доберётся никогда.

Поиск по списку (O(N)) в двойном вложенном цикле? Нет, GC до такой «быстроты» далеко, там ведь new к сдвигу указателя кучи сводится.

Так что мешает его дергать на выходе из scope? Конечно же нежелание считать ссылки, ведь мы не знаем когда его вызывать.

Как подсчетом ссылок узнать, нужно ли грохнуть объект и, соответственно, вызвать его деструктор при выходе из области видимости? Если действует на нервы, что объект не удаляется немедленно - GC.Collect. Джава вроде пытается распознать короткоживущие объекты и на стеке распределить. В шарпе ValueType тоже, если можно, на стеке распределяются.

Они такие медленные и страшные, и размер объектов вырастет на 4 или 8(на х64) байт, мы лучше будем возиться со списками, сканировать память, лишь бы только не использовать страшные атомарные операции.

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

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

> Или, если переформулировать: почему проблемы, вызываемые статичнской линковкой, меньше, чем проблемы, вызываемые динамическойю

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

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

> На более высоком уровне: решает задачу реюзания прекомпилированных модулей.

такая формулировка не катит. Потому что под неё подходят обе, и статическая и динамическая линковка.

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

> динамическая линковка привносит в уравнение ещё два компонента, динамический линкер + динамический загрузчик

Динамический линкер или статический - без разницы для подсчета компонентов. Динамический загрузчик тоже штука не сложная.

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

> но программы на vala собираются везде, где есть glib и компилятор С.

glib не обязателен. С valac --profile=posix получим бинарник, не зависящий ни от glib ни от gio ни от GObject. Можно выпиливать напильником C биндинги, а можно взять библиотеку Dova http://live.gnome.org/Dova http://gitorious.org/dova

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

>без разницы для подсчета компонентов.
ldd сплоет с тобой не согласен.

Динамический загрузчик тоже штука не сложная.

ну да. только нужен перемещаемый код или fixup-ы. написав свой загрузчик можно и libfoo.a грузить динамически.

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

>> без разницы для подсчета компонентов.

ldd сплоет с тобой не согласен.

Я в гробу видел мнение сплоетов.

только нужен перемещаемый код или fixup-ы. написав свой загрузчик можно и libfoo.a грузить динамически.

И?

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

>> Я в гробу видел

Что ты там делал?!

Не там, а рядом - на мнение сплоетов смотрел.

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

>Поиск по списку (O(N)) в двойном вложенном цикле

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

Как подсчетом ссылок узнать, нужно ли грохнуть объект

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

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

>код просто подбирает первый элемент из односвязного списка.

Я про поиск самого этого списка по размеру блока. C O(N) - это я впал в раж, конечно, но в любом случае эта портянка кода все равно будет медленнее простого сдвига указателя. Запости где-нибудь свой слаб и потестим.

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

Меньше предположений, больше конкретики. Простой же вопрос был, как с помощью счетчика ссылок определить, что объект следует грохнуть? В этом же был смысл твоего поста? Мол, зачем ГЦ, если есть замечательный счетчик. Если не можешь словами ответить, на C++ накидай или хоть как-нибудь.

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

glib не обязателен. С valac --profile=posix получим бинарник, не зависящий ни от glib ни от gio ни от GObject


ты сам-то пробовал? оно not implemented, и по информации от разработчиков никто это не пилит.

а можно взять библиотеку Dova http://live.gnome.org/Dova http://gitorious.org/dova


ее скорее нет, чем она есть. хотя живое, да.

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

Я про поиск самого этого списка по размеру блока

не знаю, как там у вас в жабе, а в slab блок ищется в таблице с индексом size>>n, где n=log2(cacheline_size)+cacheline_size/8 для n>cachesize, или 3 для выделения чего-то менее cache_size, и подхватывается тем же самым кодом из 5 ассемблерных инструкций.

Меньше предположений, больше конкретики.

 
   lock xadd dword [reg1+offset of refcount], -1
   ja 1f
   call delete;reg1 = argument of delete
1:
ckotinko ☆☆☆
()
Ответ на: комментарий от ckotinko

подхватывается тем же самым кодом из 5 ассемблерных инструкций.

Ты можешь эти 5 инструкций оформить в виде void * allocate(size_t), void deallocate( void * ), чтобы от общих набросов к чему-то конкретному перейти можно было?

lock xadd dword [reg1+offset of refcount], -1

Вопрос не в том, как на ассемблере закодить декремент счетчика. Вопрос в том, как правильно использовать счетчик, чтобы он удалял объект. То, о чем ты говоришь, реализует shared_ptr в C++. Например, при выходе из области действия, счетчик обнулится и "-1" удалится:

{ shared_ptr< int > p( new int( -1 ) ); }
А тут удалится сразу список из 2 элементов:
struct node {
  node() { }
  node( node * link ) : link( link ) { }
  shared_ptr< node > link;
};

void test() {
    shared_ptr< node > n( new node( new node ) );
}
А в таких ситуациях счетчик ссылок уничтожит все живое:
void test() {
    shared_ptr< node > n;
    n->link = n;
}

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

Это проблема не языка, а реализации. Хотя язык все одно дрянь. Взяли синтаксис python, pascal, c, java, перемешали в разных пропорциях, добавили странных ненужных фич - нате вам новый язык!

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

> Взяли синтаксис python, java
Хде там от этих языков?

ненужных фич

Не ненужных, а вполне юзабельных и востребованных.

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

> подхватывается тем же самым кодом из 5 ассемблерных инструкций.

х86 хкольник-фанбой detected

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

> а вместо этого пытается впарить мне «технологии».

Тебе предлагают не сравнивать яблоки и ананасы.

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

>Это проблема не языка, а реализации.

Но это же не Хаскель, а довольно низкоуровневый язык. Кто гугл за руки держит и не дает реализовывать.

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

>Не ненужных, а вполне юзабельных и востребованных.

Область видимости функции в зависимости от высоты первой буквы в имени?

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