Pull to refresh

Comments 67

UFO landed and left these words here
Кстати, да, надо бы упомянуть что он не работает на Java VM. Только сам транслятор ooc->c использует Java.
Не, парсер самописный, ручками написан, генератор тоже. За это автора можно уважать, а вот сам язык что-то не очень приглянулся, никаких инсайтов.
Ну любителей велосипедов не люблю тем более для такой задачи. Пока автор сидел отлаживал свой парсер которій уже реализировали 20000 раз, он мог добавлять функционал в язык. Хотя нужно смотреть аргументацию автора.
Имея описание граматики для того же ANTLR, bison можна было бы думать о портировании технологии на другие платформы, а так время потраченное впустую.
Угу, наверное поэтому все массово применяемые приложения имеют парсеры написанные вручную.
компилятор actionscript3 тоже на яве, проблем не доставляет
Вот это презентация! После такого даже я тоже отложу все дела на пару дней/недель/месяцев (последнее вряд ли — кушать всё же хочется) и поюзаю это чудо! :)
с одной стороны интересно если из этого что путное выйдет, ибо выглядит очень вкусной.
с другой — есть же OCaml например…
Да вот по мне тоже выглядит очень вкусно. OCaml вроде бы тоже классный язык, да и Scala, кстати. Но синтаксис мне мозги выворачивает. Очень тяжело от императивного к функциональному стилю программирования переходить. А тут как-то все проще.
со Scala сравнивать имхо не совсем корректно, ибо кто хочет компиляции в байткод JVM и всех ява-библиотек — выберет скалу. а для embedded вещей она не подойдет, когда критично время старта, размер, или просто хочется native кода. в остальном же они очень похожи, да. а окамль тоже native-компилируется, я его поэтому вспомнил.

синтаксически мне не очень нравится паскалевское ":=" присваивание, но наверное можно привыкнуть
Я сравниваю больше в плане того, что эти языки сделали более привлекательными базовые языки (Java -> Scala), (ml -> OCaml), (c -> occ).

А вот := тоже как-то не очень. Но ребята не прочь обсуждать даже синтаксис языка на канале (сами пишут — типа предлагайте новшества, будем думать), так что все возможно. :)
хм… если в языке будет меняться даже синтаксис — это вообще страшно. уж на что Scala — ей уже не один год, из них последние года 2 про неё очень много шуму, вышло 5 (если не больше) книг, есть поддержка всеми IDE, и то при использовании в реальных проектах ошибок в базовых библиотеках вылазит слишком много. а в следующей версии 2.8, похоже, изменения будут настолько велики, что старый код перестаёт компилироваться.

так что раньше версии 1.0, бумажной книжки и поддержки в IDE трогать его боязно.
Полностью согласен, это пока что хакинг и ковыряние — язык сырой. Но с другой стороны — синтаксис менять особо не планируют. Недавно вот вместо «import folder.file» сделали «import folder/file», чтобы можно было «import ../file». Но оно не такое уж большой изменение. А так да — для производства продакшн кода это пока совсем не годится )
а для веба у него есть что-нибудь? мини-http-server на нём написанный, FastCGI или веб-фреймворк какой? мне кажется сейчас это очень важно для развития языка, хотя и си считается языком «совсем не для веба», может быть оос сможет опровергнуть данное убеждение?

у скалы, например, есть LiftWeb
Не думаю, в сорцах даже упоминания о сокетах не видел. Точнее видел, но примитивнейшее.
м… что-то пролистав сайт я не нашёл никакой функциональщины. хотя бы передать функцию как аргумент можно, или только на уровне сишных указателей на функции? что там с хвостовой рекурсией (tail recursion), замыканиями (closure)?
Вот «closures» я точно видел в сорцах: ooc\tests\closures\… — там есть передача функции как аргумента (но есть у меня сомнения в рабочести теста). Остального не видел.
Может из-за этого и называют его «функционально(ватый)», а не «функциональный» )
о, в 003-answer-args.ooc как раз передача функции, здорово (исходники — лушая документация, гы), только не совсем понятно зачем там ещё extern signal объявляется, осталось от прошлых версий?
Блин, вроде идея хорошая, но мерзкий паскалевский синтаксис разочаровыает ((
Хотя, я все равно в шоке. Почему никто не придумал этого раньше? Заменить паскалевский синтаксис на сишный/рубиевский, заменить сборщик мусора на что-нибудь более эффективное и научитть генерировать адекватного размера бинарники (ну там убирать неиспользуемые функции, и прочее) — был бы идельный язык по моему, .NET и Java курили бы в сторонке.
Насчет сборщика мусора автор часто раздает какую-то ссылку на тему того, что почитайте ее прежде чем спорить что сборщики не эффективны. К сожалению, не очень интересовался, так что ссылку не сохранил.
Я тоже помню, где-то есть целая статья на англ. про эффективность сборки мусора.

Ну не знаю, как автоматический сборщик мусора, который тупо сканирует всю память в поиске указателей может быть эффективен ( + останавливающий выполнение все программы). Тесты —муть, так как там например тестируется какое-нибудь кодирование видео в течение часа, и неважно, что процес моэжет подвиснуть секунд на 10 — никто не заметит, а в десктопной программе это ой как заметно.

То, же что и с Явой — по тестатм она то ли догоняет, то ли обходит местами Си++, но в реальности, на моем десктопе по крайней мере, явовские программы не мгновенно запускаются, притормаживают, едят память (от чего появляются дополнительгые тормоза, связанные например со свапом).

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

сборщики мусора, не останавливающие мир, есть, сейчас это стабильный CMS и в будущей версии будет G1.

сборщик мусора может ускорить выполнение программы например из-за дефрагментации памяти. при сборке мусора (и только для Server VM) области памяти, ссылающиеся друг на друга, размещаются сборщиком мусора рядом, так что в будущем при обращении к одной области другая с большой вероятностью будет выбрана (prefetch) в кэш.
> сборщик мусора может ускорить выполнение программы например из-за дефрагментации памяти.

Я в шоке. Это когда перемещение кусков памяти (а это одна из самых неэффективных операций, т к скорость работы памяти низкая) что-то ускоряло? Дефрагментация может уменьшить объем потребляемой памяти, но ценой потерь производительности.

> бласти памяти, ссылающиеся друг на друга, размещаются сборщиком мусора рядом, так что в будущем при обращении к одной области другая с большой вероятностью будет выбрана (prefetch) в кэш.

Это будет работать только для крошечных областей, так как префетч не будет память закачивать в кеш килобайтами. Где вы видели в Яве крошечные объекты, я не знаю.

Дело же в самом принципе работы сборщика, принцип дурацкйи и неэффективный, обходить всю память в поисках ссылок, а если объектов тысячи? Десятки тысяч?

И, кстати, хорошие сборщики мусоар, как я понимаю, коммерческие — значит в том же openSource их использвоать не будут, значит оно (опенсурсное software) изначально будет проигрывать коммерческому, так?
1) речь идёт о приложениях, работающих месяцами. там принцип «лучше день потерять а потом за час долететь» работает.
2) многие структуры данных типа связных списков используют крошечные объекты всего с несколькими указателями на другие объекты
3) почитайте принципы работы G1, там для каждой достаточно большой области памяти хранится список её внешних ссылок, поэтому обходятся только они а вовсе не «вся память в поиске ссылок»
4) сановская ява уже достаточно давно как опенсурсна, берите код сборщика из OpenJDK
> 1) речь идёт о приложениях, работающих месяцами. там принцип «лучше день потерять а потом за час долететь» работает.

Так такие приложения меня не интересуют, фоновые многочасовые задачи. Меня интересуют: 1) десктопные приложения — должны работать быстро и не есть память 2) серверные приложения — должны очень быстро откликаться (память есть могут :) )

Кстати, в пользу GC можно еще вспомнить мультитредовость — штуки типа рефкаунтинга требуют блокировок и синхронизаций, который напрочь ломают конвейер в процессоре, но это сложный вопрос.

И вообще все это странно, почему вообще процесор должен тратить больше времени на организацию памяти, чем на полезные вычисления, может нам нужны другие, хорошие процессоры?
как настраивать десктопные приложения чтобы они в несколько раз быстрее запускались писали много, гугл в помощь. серверные приложения как раз и должны работать месяцами без перезагрузок. аппаратные сборщики мусора вроде тоже есть
Вы бы по ссылке текст почитали сначала:

> -XX:+AggressiveHeap
> ...It was originally intended for machines with large amounts of memory and a large number of CPUs, but in the J2SE platform, version 1.4.1 and later it has shown itself to be useful even on four processor machines.

Не знаю как у вас, у меня на 2 процессорном ноутбуке Сишные программы летают, без всяких AggressiveHeap, а тут надо минимум 4 ядра.

Настройками тут ничего не вылечишь, тут дело в принципе работы, Яве не место на десктопе (по крайней мере на моем :) ).

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

Тут можно спорить, я по поводу них писал, что там важно низкое время отклика (то есть сборщик мусора должен запускаться *не* в процессе обработки запроса пользвоателя).
В шоке — от того, насколько неэффективен синтаксии классических языков типа Си, и как он неужобен.
Очень субъективно. Не умеете писать на Си — пишите на %ЯП-name%.
Вас никто не заставляет.
Лол, как можно из критики синтаксиса Си заключить, что критикующий не умеет писать на Си?
Пишите на Malbolge, вполне не классический язык. =)
Кому нужно — пишут на чистых сях и не забывают делать free();
А остальные такое написать не смогут :)
Дык вы попробуйте на своих сях что-нибудь посложнее хелловорлда написать, например дерево DOM (где у каждого узла куча свойств, часть из которых — строки (динамически создаваемые во время работы), часть — ссылки на другие узлы), и где можно динамически удалять и добавлять элементы. Как вы будете писать free()? Тут даже рефкаунтинг вряд ли поможет, из-за циклических ссылок ((

Или простейший пример: функция возвращает результатом строку (очевидно, размещаемую через malloc()). Где и кто будет освобождать память?

char *somefunc(int n) {
static char *buf = NULL;
if(buf) free(buf);
buf = malloc(n);
return buf;
}


А если Вы на «моих сях» не можете писать вменяемый код — это ваши персональные проблемы.
Я на них пишу со школы, вместо бейсика. И ни разу не пожалел.
P.S. DOM я может и не писал, но многоуровневые вложенные структуры с динамическим числом элементов и неограниченной вложеностью — писал. И знаете (!!111) — работает! И памяти жрёт в разы меньше (а сейчас в меня полетят минусы) «этой вашей» явы.
Гм, а если тепрь надо возвращаемую строку присовить какому-нибудь полю объекта, т.е

class c1 {
char* result;

void doSmth(int n)
{
this->result = somefunc(n);
}
}

// Извиняюсь если код кривой, давно не писал ничего на Си

То вы что будете делать? Выделять новый буфер и копировать туда старый (это очень неэффективно, копировать память)? А? Нука? А если метод doSmth() возвращает строку дальше. т.е. в конце стоит return this->result?

p.s Яву сам не люблю, язык для индусов.
1. В нужных местах ставим const.
2. Учим ассемблер и понятие «страница памяти».
Оперируем страницами — mmap() в помощь.
3. Есть такая штука, как inline.
А ещё есть аргумент register.
4. И вообще, классы — это C++. Я лично пишу на чистом ANSI C :)
C++ это всякие new, delete и прочее. Не путайте.
> И вообще, классы — это C++. Я лично пишу на чистом ANSI C :)

Хорошо, результат присваивается полю структуры:

void doSmth(int n, my_struct *ms)
{
ms->result = somefunc(n);
return ms->result;
}

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

И уж тем более никаки игры со страницами памяти не помогут, и засунуть строку в регистр тоже не получится.

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

А ваш вариант — он годится только когда строку. возвращенную из функции сразу же выводят на экран, или например разбирают и отбрасывают.
> void
> return ms->result;
Простите, но может быть Вы сначала разберетесь с базовыми понятиями языка Си? :)
Стандартный пример:
<code>
struct idx {
  uint_32 key;
  uchar_8 *val;
};
int main() {
  uint_32 i = DEF_CONST;
  uint_32 idx_cnt;
  struct idx **ptr = NULL;
  for(idx_cnt = 0;idx_cnt<i;idx_cnt++) {
    ptr = realloc(ptr, sizeof(struct idx *)*(idx_cnt+1));
    ptr[idx_cnt] = malloc(sizeof(struct idx));
    ptr[idx_cnt]->val = strdup("val31337");
  }
  // делаем шото
  for(i=0;i<idx_cnt;i++) {
   free(ptr[i]->val);
   free(ptr[i]);
  }
  free(ptr);
  return 0;
}
</code>

Вложенность не ограничена. Можно писать как через рекурсию, так и через итерацию.
Это — базовый шаблон :)
Хотя иногда проще использовать статичные буфера и макросы для работы с ними.
Ну очевидно, void — копипаста из старого примера :) Имеется в виду char * doSmth.

Ваш код — что-то немного запутанное, но как я понял, вы создаете массив указателей на динамически размещенные строки (т.н. набор строк, доступных по индексу) и что? Как это поможет для моего примера?

Проблема в том, что когда мы передаем/сохраняем куда-то char * — мы передаем указатель и никак не можем контроллировать его использование. Будет ли освобождена память по этому адресу? И кто ее освободит? Если функция, выделившая память — есть риск, что этот указатель сохранен в другой перемнной/поле структуры и мы освободим память, на которую ссылается тот указатель. А что. если на эту строку ссылаются несколько указателей? А что. если какая-то функция попытается изменить данные в этой строке?

Надежно копировать строку можно через strdup(), но это слишком дорогой и неэффективный способ, он еще хуже чем использование Явы :).

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

В идеале, надо чтобы был какой-то объект, вроде строк в php или других высокоровневых языках — их можно передавать в функци, возвращать, присваивать, при этом копирование строки — дешевая операция (увеличение счетчика ссылок), и память освобождается, когда больше не нужна.
Подсчет ссылок — это уже дело программиста.
Не поверите — столько всего писал (в основном под *nix), начиная от заглушек на 80 порт и заканчивая счетчиками траффика — и все проблемы решаются «на раз». А strdup кстати — очень быстрая функция.
Горааздо быстрее, чем интерпретация байт-кода Явы.
Другое дело, если программист не знает архитектуры и языка, на котором пишет. Тогда ему просто необходим «умный» компилятор типо VB :)
> Не поверите — столько всего писал (в основном под *nix), начиная от заглушек на 80 порт и заканчивая счетчиками траффика — и все проблемы

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

Не знаю, я вообще например программирования не представляю без объектов, слишком удобно, а решать вопросы типа кто должен освобождать память — не очень интересно.

А если приложение работает с БД, с GUI, содержит кучу объектов, модель, контроллер, и прочее, что сейчас модно? Ваш подход просто не прокатит, все будет слишком сложно и запутанно и приведет к куче ощибок.

> А strdup кстати — очень быстрая функция.

Она очень неэффективная, особенно если строки от несколько килобайт размером. Копирование памяти — зло.

И кстати в коде их предыдущго комментария тоже есть неэффектинвная техника (может, она конечно для простоты там приведена, не знаю), увеличение массива по 1 элементу через realloc()  — очень плохо, потенциально может вызвать постоянное копирование участков памяти.
Главное, что устраивает меня и моего заказчика.
Кстати, на Си как-то написали такую штуку, как Unix. На Си написано почти всё окружение GNU. На Си пишется очень много всего. И никому не приходит в голову добавлять туда сборщик мусора.
А ваше — «не прокатит, все будет слишком сложно и запутанно и приведет к куче ощибок» говорит о том, что вы просто не умеете писать на Си.
Но ведь вас никто не заставляет? :)
Ага, то-то постоянно появляются всякие ядерные эксплойты под Unix, как раз основанные на каком-нибудь переполнении буфера — вот и плата за сложность, когда смотришь на полотно кода и не догадаешься что там закралась ошибка.

И, раз мы уж заговорили про ядро — в нынешней архитектуре имеется очень серьезный барьер — это копирование данных из userspace в ядерное пространство и обратно — который всячески ограничивает скорость межпроцессового взаимодействия и скорость сист. вызовов. Пока передаются маленькие объемы данных, это может и не очень заметно, а вот когда надо перекачивать много информации (например, X-server — X-client) — это все становится жутко неэффективным. А ведь в будущем все больше и больше будут использовться программы, состоящие из многих компонент.

> А ваше — «не прокатит, все будет слишком сложно и запутанно и приведет к куче ощибок» говорит о том, что вы просто не умеете писать на Си.

Не знаю, я программирую на php, всякие штуки, которые у вас пишутся на пару станниц кода (те же массивы/работа с паятью и строками), в php описываются парой строчек. Да, я в курсе, что это намного медленнее — но это понятнее и удобнее.
А почему бы не сделать язык, совмещающий преимщества обеих миров — удобный — но хорошо компилируемый.
>Ага, то-то постоянно появляются всякие ядерные эксплойты под Unix
Под Linux, уважаемый, под Linux они появляются. И всё потому, что слишком много программистов, которым «понятнее и удобнее» писать кривой код и включать его в ядро.
Найдите-ка ошибки в OpenBSD?
Или в vsftpd? В OpenSSH? :)
Да даже если сравнивать Linux (_реально_ эксплуатируемые дыры, а не int-переполнения) и альтернативные ОС, написанные как-раз вашим подходом — выбор будет в пользу Linux.

>Пока передаются маленькие объемы данных, это может и не очень заметно, а вот когда надо перекачивать много информации (например, X-server — X-client) — это все становится жутко неэффективным.
Это не имеет отношения к Си, это скорее к архитектуре x86.

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

Найдете такой — сообщите ;)
«Где и кто будет освобождать память?»

В objective-c эта проблема решена довольно остроумно. Во-первых, для всех объектов типа NSObject используется подсчет ссылок. Во-вторых, есть autorelease pulls, в которые как раз и попадают возвращаемые объекты. Если возвращенную строку никто к себе не забрал, то она будет удалена при очистке пула. Пулы живут только на одном потоке и могут быть вложенными. В каждом приложении есть основной поток, в котором есть основной RunLoop, который имеет свой пул, очищаемый после обработки каждого события.

Работает так:

NSObject* autoreleasedObject()
{
// autorelease поместит объект в ближайший пул в текущем потоке
return [[[NSObject alloc] init] autorelease];
}

Да, я читал про это. Тут используется тот факт, что в GUI приложениях постоянно происходит обработка событий, и удобно использовать это для удаления ненудных данных. Но приходится извращаться, когда надо протолкнуть данные сквозь пул.

Ну и retain/release надо руками писать — все равно ручное управление памятью.
Управление памятью ручное, но совершенно понятное: кто сделал alloc, copy или retain, тот и делает release. Ни разу не приходилось «извращаться» или что-то проталкивать. Например, properties сами делают retain/release при записи и retain+autorelease при чтении. Так что единственное, что следует делать вручную — присвоить nil всем свойствам в методе dealloc (что автоматизируется благодаря информации о свойствах и их типах доступной в рантайме).

Когда я пишу сайтики и скрипты на руби, производительности интерпретатора и его тупого сборщика мусора мне вполне хватает. В крайнем случае, куплю железа по-мощнее. На десктопе или того хуже — на карманном компьютере я не могу докупить железа. И там как раз всевозможные интерпретаторы и сборщики мусора очень сильно тормозят. Это хорошо заметно при сравнении андроида и айфона.

Иными словами, интересно не то, что правильнее — наличие GC или отсутствие, а среда в которой делается работа. Например, андроидная джава ничем не удобнее и не гибче objective-c. И там и там — статические типы и многословные конструкции. И думать про дизайн и производительность нужно гораздо больше времени, нежели писать [something release].

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

Ну так еще бы компилятор сам ставил release/retain — вообще замечательно бы было :)
Кстати говоря, не только в «GUI» приложениях случаются события. Возьмите любой веб-сервер или CLI (командную строку).

Если же в каком-то месте создается много объектов которые имеет смысл удалить, не дожидаясь окончания обработки текущего события (чтобы не занимать слишком много памяти), то можно создать локальный пул. При этом в данном конкретном месте автору кода будет совершенно очевидно где этот пул должен быть очищен и какие объекты нужно retain-ить перед очисткой.

class Vector3f {
  float x,y,z;
  Vector3f(float x_, float y_, float z_): x(x_), y(y_), z(z_) {};
};
// (да простят меня спецы C++ если тут что-то лишнее).

Вероятно, что перед конструктором ещё public: не помешает :-).
А лишнее — точка с запятой (вторая). То, что она нужна после определения класса — издевательство, конечно, редкостные, но мы ж не будем теперь с перепугу после каждой скобочки их ставить :]
UFO landed and left these words here
смотря на функцию add на меня нахлынули приятные воспоминании о haskell
Хаскель, пайтон, паскаль… Что ещё они намешали туда? Но получилось очень даже ничего.
Там было сказано про сборщик мусора. Как он работает? Т.е. как интерпритируется в С-код? Интересно было бы узнать.
А вообще, Boost ещё бы подключить и вообще была бы конфетка.
Интересно. И у меня были мысли про что-то подобное.
Вот только как отлаживать такую программу? Ладно ещё в простых случаях, где достаточно будет обратных ссылок из сгенерированного сишного файла, но ведь этого не всегда хватит…
Проясните, пожалуйста, а в чем отличия от Objective C? Ну кроме того, что ooc генерирует с-шный исходник.
>поэтому наслждаемся пока что довольно неслабого размера .exe'шниками (gcc от mingw других не делает).
вы просто не умеете их готовить
Sign up to leave a comment.

Articles