Re[48]: почему в вебе распространены именно динамические язы
От: WolfHound  
Дата: 22.10.10 17:19
Оценка:
Здравствуйте, netch80, Вы писали:

N>Я утверждаю, что это твоё утверждение "что Go безопасный ложно" некорректно без указания, как именно мы определяем безопасность. И если тебе так хочется — да, я нахожу основание твоей... мнэээ... недоработки — в том, что ты не понимаешь, что такое безопасность, но хаешь чужое.

Почему это я не понимаю?
Прекрасно понимаю.
Безопасный это когда по памяти проехаться нельзя.
А в Go можно.

N>Я не могу упростить реально сложные вещи до "простого списка".

Ну я то смог.
Просто.
Конкретно.
Без всяких философий и километровых описаний предметных областей.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[19]: почему в вебе распространены именно динамические язы
От: vdimas Россия  
Дата: 22.10.10 17:20
Оценка:
Здравствуйте, Воронков Василий, Вы писали:


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


Нельзя. Чтобы их хранить на куче, надо заведомо знать их типы, т.е. в момент генерации нативного кода (в момент сборки самого интерпретатора). Ну или попробуй найти хоть в одном интерпретаторе такое.
Re[20]: почему в вебе распространены именно динамические язы
От: Воронков Василий Россия  
Дата: 22.10.10 18:17
Оценка: +1
Здравствуйте, vdimas, Вы писали:

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

V>Нельзя. Чтобы их хранить на куче, надо заведомо знать их типы, т.е. в момент генерации нативного кода (в момент сборки самого интерпретатора).

Знать тип необязательно. Надо знать *размер*. Почувствуйте разницу, как говорится.

А вообще говоря и размер-то даже компилятору знать не надо. Компилятору, который генерирует байт-код, вообще должно быть до фени, где и как эти объекты хранятся. Его задача — записать Push да Pop, и все. Что там будет происходить во время исполнения этого байт-кода зависит от архитектуры виртуальной машины. То, что это динамика вносит лишь единственную коррективу — вместе со значением нужно хранить дескриптор типа. И это все. Остальное — часть логики декодирования байт-кода. Скажем, первый байт — тип. По нему для всех примитивов однозначно определяется размер. Остальное — дело техники. Упаковывать значения на стек можно аналогичным образом.

V>Ну или попробуй найти хоть в одном интерпретаторе такое.


Ну вот в моем интерпретаторе такое. И что-то мне кажется я Америку не открыл. Правда, есть ограничение — на стеке размещаются объекты размером не более 4х байт. Но это опять же мое индивидуальное ограничение для упрощения и ускорения декодирования байт-кода. Жесткой необходимости в таком нет.
Re[21]: почему в вебе распространены именно динамические язы
От: vdimas Россия  
Дата: 23.10.10 19:46
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Ну вот в моем интерпретаторе такое. И что-то мне кажется я Америку не открыл.


Надо быстродействие замерять, а не Америку открывать. Для целых чисел, например, обычно заводят статический массив ссылок из уже заранее размещенных на стеке боксированных чисел. Т.к. эти объекты-значения иммутабельны, они общие для всех. И парсер поступает примерно так:
IntegerObj BoxIntegerObj(int value) {
    if(value>=-N && value<N)
        return boxCache[value+N];

    return new IntegerObj(value);
}


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

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

ВВ>Правда, есть ограничение — на стеке размещаются объекты размером не более 4х байт. Но это опять же мое индивидуальное ограничение для упрощения и ускорения декодирования байт-кода. Жесткой необходимости в таком нет.


Да есть... ты начни покрывать полностью все сценарии, и увидишь, как много в итоге будет ветвлений в динамике. Опять же, как разместить на стеке целое число для среднестатистического интерпретатора, если это число динамически, в процессе обычного приращения в цикле, может менять внутренний (реальный) тип от байта, до BigInt?
Re[22]: почему в вебе распространены именно динамические язы
От: Воронков Василий Россия  
Дата: 24.10.10 07:19
Оценка:
Здравствуйте, vdimas, Вы писали:

ВВ>>Ну вот в моем интерпретаторе такое. И что-то мне кажется я Америку не открыл.

V>Надо быстродействие замерять, а не Америку открывать. Для целых чисел, например, обычно заводят статический массив ссылок из уже заранее размещенных на стеке боксированных чисел. Т.к. эти объекты-значения иммутабельны, они общие для всех. И парсер поступает примерно так:

Какой парсер? Кто заводит массив из ссылок из боксированных чисел?
Таки да, в Джаве, к примеру, есть кэш Integer в определенном диапазоне для ускорения конвертации в них обычных примитивов, вот только какое это имеет отношение к обсуждаемому вопросу? И причем тут *парсер*?

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


Это к чему сказано? Причем тут вообще проверка флагов?

ВВ>>Правда, есть ограничение — на стеке размещаются объекты размером не более 4х байт. Но это опять же мое индивидуальное ограничение для упрощения и ускорения декодирования байт-кода. Жесткой необходимости в таком нет.

V>Да есть... ты начни покрывать полностью все сценарии, и увидишь, как много в итоге будет ветвлений в динамике.

Сценарии покрыты полностью.

V>Опять же, как разместить на стеке целое число для среднестатистического интерпретатора, если это число динамически, в процессе обычного приращения в цикле, может менять внутренний (реальный) тип от байта, до BigInt?


Инкремент означает: Поднялись значение переменной на стек, сняли со стека, увеличили, подняли на стек, записали в переменную. Даже если у нее размер меняется — это абсолютно безразлично.
Re[23]: почему в вебе распространены именно динамические язы
От: vdimas Россия  
Дата: 24.10.10 12:56
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Какой парсер? Кто заводит массив из ссылок из боксированных чисел?

ВВ>Таки да, в Джаве, к примеру, есть кэш Integer в определенном диапазоне для ускорения конвертации в них обычных примитивов, вот только какое это имеет отношение к обсуждаемому вопросу? И причем тут *парсер*?

Ну мы же об интерпретаторе говорим, а там парсер должен для начала как-то текст программы перевести во внутреннее представление. Понятное дело, что такое боксирование происходит не только в процессе парсинга, но и после любых арифметических действий.

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



ВВ>Это к чему сказано? Причем тут вообще проверка флагов?


При том что ты, насколько я понял, хранишь описание типа рядом с данными. Вот я и предположил, как вся схема работает. Ты же размер числа должен проверять как-то? А это очередная лишняя проверка, съедающая все преимущества расположения данных на стеке. Напомню, что это преимущество заключается в отсутствии необходимости выделять память из кучи. В остальном же, память, адресуемая по указателю стека, работает не быстрее любой другой памяти. Ну там если не брать во внимание промахи/попадания кеша, которые одинаково хорошо работают и для упомянутого массива закешированных боксированных значений.


ВВ>Инкремент означает: Поднялись значение переменной на стек, сняли со стека, увеличили, подняли на стек, записали в переменную. Даже если у нее размер меняется — это абсолютно безразлично.


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

В общем, замерять надо сначала, прежде чем на какой-то схеме останавливаться. По результатам моих экспериментов пятилетней давности быстрее всего себя в динамике на большом колв-е числовых типов показали вычисления на "типизации" с помощью двойной диспетчеризации. Таблицы виртуальных ф-ий они ведь тоже при частом использовании неплохо на кеш ложатся.
Re[11]: почему в вебе распространены именно динамические язы
От: vdimas Россия  
Дата: 24.10.10 12:58
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Это не первоклассные функции. Потом, извините, что за фигня? На ООП писать нельзя потому что слишком высокий порог вхождения, в функциональном стиле можно? Там порога вхождения нет что ли? Вы считаете, что ФП для новичков понятнее, чем ООП?


Более плавный переход из процедурного стиля, наверно?
Можно вообще начать писать в процедурном стиле на любом ФЯ, осваивая лямбды постепенно.
Re[24]: почему в вебе распространены именно динамические язы
От: Воронков Василий Россия  
Дата: 24.10.10 13:21
Оценка:
Здравствуйте, vdimas, Вы писали:

ВВ>>Какой парсер? Кто заводит массив из ссылок из боксированных чисел?

ВВ>>Таки да, в Джаве, к примеру, есть кэш Integer в определенном диапазоне для ускорения конвертации в них обычных примитивов, вот только какое это имеет отношение к обсуждаемому вопросу? И причем тут *парсер*?
V>Ну мы же об интерпретаторе говорим, а там парсер должен для начала как-то текст программы перевести во внутреннее представление. Понятное дело, что такое боксирование происходит не только в процессе парсинга, но и после любых арифметических действий.

Боксирование со стороны парсера какая-то отдельная тема совсем. Во-первых, она касается только литералов. Во-вторых, его также можно избежать. Например, в общем случае, если у вас есть литерал для Int64, вы же не будете создавать отдельную инструкцию, которая имеет в качестве аргумента аж 8-ми байтовую структуру? Например, он будет подниматься на стек как два Int32, из которых уже будет собираться Int64. Аналогично, к примеру, в MSIL. Т.е. ни парсеру, ни компилятору этот Int64 вообще не нужен. И то, как они обходятся с примитивами, есть их личное интимное дело, никак не связанное с исполнением кода.

ВВ>>Это к чему сказано? Причем тут вообще проверка флагов?


V>При том что ты, насколько я понял, хранишь описание типа рядом с данными. Вот я и предположил, как вся схема работает. Ты же размер числа должен проверять как-то? А это очередная лишняя проверка, съедающая все преимущества расположения данных на стеке.


Проверка размер числа == проверка флажка типа. Последнюю надо делать в любом случае, независимо от того, как хранится структура. На производительность проверка флажка влияет очень слабо. Если отключить проверки (считать, что все типы данных — это Int32) и запустить какой-нибудь нагрузочный тест типа сортировки пузырьком на 1000 элементов массива из Int32, то разница между версией с проверками и версией без проверки настолько мала, что ее можно списать в погрешность вычисления.

V>Напомню, что это преимущество заключается в отсутствии необходимости выделять память из кучи. В остальном же, память, адресуемая по указателю стека, работает не быстрее любой другой памяти. Ну там если не брать во внимание промахи/попадания кеша, которые одинаково хорошо работают и для упомянутого массива закешированных боксированных значений.


Главное преимущества, что при исполнении кода вида "2 + 2" мы не будет создавать в куче три абсолютно бесполезных временных объекта. Эти объекты я создам на стеке. Все, больше преимуществ нет, есть лишь недостатки (например, копирование).

ВВ>>Инкремент означает: Поднялись значение переменной на стек, сняли со стека, увеличили, подняли на стек, записали в переменную. Даже если у нее размер меняется — это абсолютно безразлично.


V>Так у тебя свой стек что-ли (эмулируемый)? Или допускается изменение указателя стека после вызова ф-ий как в Форте? Тогда, извини, но адрес возврата непонятно где искать, то бишь для возвратов нужен будет другой стек. По любому, один из стеков надо эмулировать, что мы уже проходили. В итоге, ты изменяешь указатель стека — раз, не на константное значение (в отличие от использования ссылочных типов), а на значение, доставаемое по относительному адресу — два, один из стеков эмулируешь — три. В упор не вижу бенефитов, только лишние такты процессора. Хуже всего, если ты эмулируешь стек возвратов как в классике Форта, ибо это съедает все преимущества современной предвыборки инструкций. То бишь, выгоднее эмулировать стек данных.


У меня лично свой стек, но мы начали говорить "в общем". Питон, насколько я знаю, использует стек Си. Смысл "типов по значению" здесь не в том, что они именно хранятся на стеке, это в общем случае неверно даже для языков со статической типизицией, скажем, нет гарантии, что при исполнении кода вида "int x = 1" значение x будет храниться именно на стеке. Смысл в том, что некоторые операции над примитивами становятся дешевле.

V>В общем, замерять надо сначала, прежде чем на какой-то схеме останавливаться. По результатам моих экспериментов пятилетней давности быстрее всего себя в динамике на большом колв-е числовых типов показали вычисления на "типизации" с помощью двойной диспетчеризации. Таблицы виртуальных ф-ий они ведь тоже при частом использовании неплохо на кеш ложатся.


Я замерял. "Все в куче" — медленнее (ок. 10-15%) ну и память соответственно расходуется больше. Вариант с виртуальными функциями реализуем только в случае, если "все в куче". Опять же, я не видел большой разницы в производительности даже без проверок вообще, замерялось в т.ч. и на старой машине, сомневаюсь, что виртуальные функции тут неожиданно взлетят.
Re[12]: почему в вебе распространены именно динамические язы
От: Воронков Василий Россия  
Дата: 24.10.10 13:23
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Более плавный переход из процедурного стиля, наверно?

V>Можно вообще начать писать в процедурном стиле на любом ФЯ, осваивая лямбды постепенно.

Я не понимаю, что мешает писать в процедурном стиле на дотнете. Меня вообще слегка заклинило в начале этой дискуссии, как раз ASP.NET-то максимально "scripty". Там даже в процедурном стиле можно не писать, а писать в макаронном. Никаких классов объявлять не нужно, лепите код в <% %> по аналогии с PHP — и все. А VB.NET, кстати, умеет и динамическую типизацию. Да и шарп сейчас тоже.
Re[25]: почему в вебе распространены именно динамические язы
От: vdimas Россия  
Дата: 24.10.10 23:35
Оценка:
Здравствуйте, Воронков Василий, Вы писали:


ВВ>Проверка размер числа == проверка флажка типа. Последнюю надо делать в любом случае, независимо от того, как хранится структура. На производительность проверка флажка влияет очень слабо. Если отключить проверки (считать, что все типы данных — это Int32) и запустить какой-нибудь нагрузочный тест типа сортировки пузырьком на 1000 элементов массива из Int32, то разница между версией с проверками и версией без проверки настолько мала, что ее можно списать в погрешность вычисления.


Это ты или как-то неправильно меряешь, или у тебя всего пару числовых типов, или остальные затраты на исполнение каждого цикла интерпретатора столь велики, что одна проверка этого флага не заметна. Сравни на нативном варианте, там минимум вдвое разница.

ВВ>Главное преимущества, что при исполнении кода вида "2 + 2" мы не будет создавать в куче три абсолютно бесполезных временных объекта. Эти объекты я создам на стеке. Все, больше преимуществ нет, есть лишь недостатки (например, копирование).


Для случая 2+2 ни одного временного объекта создано не будет, по причине наличия того самого иммутабельного кеша.

ВВ>У меня лично свой стек, но мы начали говорить "в общем".


Ну так это стало понятно очень быстро...

ВВ>Питон, насколько я знаю, использует стек Си.


А теперь по русски,если не сложно.

ВВ>Смысл "типов по значению" здесь не в том, что они именно хранятся на стеке, это в общем случае неверно даже для языков со статической типизицией, скажем, нет гарантии, что при исполнении кода вида "int x = 1" значение x будет храниться именно на стеке. Смысл в том, что некоторые операции над примитивами становятся дешевле.


Ты прав, смысл в использовании аллокатора памяти стекового типа, который просто двигает текущую планку на нужное кол-во байт во время выделения/освобождения. К тому же, с гарантией доступа лишь из одного потока. И существуют устойчивые заблуждения насчет эффективности этого аллокатора в чистом виде. Я хочу сказать, что для этой разновидности аллокаторов эмулировать стек в том самом чистом виде — это удорожать операции, ибо такая эмуляция приводит к ограничению/требованию последовательного доступа к своим элементам, что на примере того же Форта или ассемблерных инструкций кривого x86 показывет, как много во время простых вычислений происходит дополнительных операций, связанных лишь с ротацией данных в стеке. Для настоящей дешевизны динамических операций надо "чистый" стековый аллокатор допиливать до паскалевской разновидности, тогда при аналогичных затратах на выделение/освобождение, мы не будем ограниченны навязанной упорядоченностью данных, как в случае стека. И да, условие гарантии однопоточности доступа к операциям выделения/освобождения должны прилагаться, как и для "настоящего" стека.


V>>В общем, замерять надо сначала, прежде чем на какой-то схеме останавливаться. По результатам моих экспериментов пятилетней давности быстрее всего себя в динамике на большом колв-е числовых типов показали вычисления на "типизации" с помощью двойной диспетчеризации. Таблицы виртуальных ф-ий они ведь тоже при частом использовании неплохо на кеш ложатся.


ВВ>Я замерял. "Все в куче" — медленнее (ок. 10-15%) ну и память соответственно расходуется больше. Вариант с виртуальными функциями реализуем только в случае, если "все в куче". Опять же, я не видел большой разницы в производительности даже без проверок вообще, замерялось в т.ч. и на старой машине, сомневаюсь, что виртуальные функции тут неожиданно взлетят.


Я не мерял насчет "кучи", т.е. выделение/освобождение не участвовало, замерял только вычисления в случае проверки флагов для 4-х числовых типов и через двойную диспетчеризацию. Для случая проверки фажков там в среднем 5 проверок надо для вывода типа результата, или же 2 вызова виртуальной ф-ии. Опять же, для вызова виртуальных ф-ий наличие объекта на стеке не нужно. Если же ты в качестве "подложки" использовал что-то вроде дотнета (закралось подозрение из-за твоего утверждения насчет кучи и виртуальных ф-ий), то там надо генерить сразу дотнетный байт-код, а не свой. То бишь, мы непонятно что обсуждали.
Re[20]: почему в вебе распространены именно динамические язы
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 25.10.10 05:33
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Что тесты? Они и близко не так эффективны как компилятор.

WH>Ибо компилятор гарантированно заглянет во все уголки кода.

Ты спросил что делать. "не так эффективны" — этим мы платим за гибкость.
Re[26]: почему в вебе распространены именно динамические язы
От: Воронков Василий Россия  
Дата: 25.10.10 06:55
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Это ты или как-то неправильно меряешь, или у тебя всего пару числовых типов, или остальные затраты на исполнение каждого цикла интерпретатора столь велики, что одна проверка этого флага не заметна. Сравни на нативном варианте, там минимум вдвое разница.


Числовых типов не пару, но проверки идут в порядке, так сказать, частоты использования: int, float, long, double. Самыми медленными будут проверки для типов, которые создаются в куче, самыми быстрыми — для стековых. В итоге арифметика с int — это всего одна проверка.
И что есть нативный вариант и как мне с ним сравнивать? Вернее, насколько эти результаты будут показательны? Я одно могу сказать точно, если у нас в каких-то условиях вариант Х оказывается быстрее, чем У, то это не значит, что это воспроизведется и в других условиях.
Простейший вариант — сравнить скорость арифметики для double с и без проверок.

Сравнить — опять же несложно. Такой тест подойдет?

let ITER = 1000*1000;

for (i to ITER) {
  let d = .5d + i :> double; //конвертируем int в double
}


Запускаю на древнем целероне, поэтому цифры страшные:

С проверками: 0.875
Без проверок: 0.859


Double один из самых тяжелых типов при сложении, тяжелее только списки/массивы. Но "тяжелость" double еще объясняется и тем, что любая арифметика с ними — создание объектов на куче.

Скажешь высокие затраты на исполнение цикла? Да, согласен. Но в принципе это естественно, что они высокие. Это интерпретатор. Поэтому я и высказываю сомнение, что от "нативного" теста тут может быть хоть какой-то прок.

Да, "референсный" тест — такой код на JScript:

for (var i = 0; i < 1000*1000; i++) {
  var r = 10 + 20;
}


Выполняется за:

0.843


(А если 1000*1000 кэшировать в переменную, то медленнее ). Это я к тому, что тестовая машина реально медленная. Но здесь я интерпретатор установить не могу сейчас.

ВВ>>Главное преимущества, что при исполнении кода вида "2 + 2" мы не будет создавать в куче три абсолютно бесполезных временных объекта. Эти объекты я создам на стеке. Все, больше преимуществ нет, есть лишь недостатки (например, копирование).

V>Для случая 2+2 ни одного временного объекта создано не будет, по причине наличия того самого иммутабельного кеша.

Ну ради бога, 222+666. Важна суть. Иммутабельный кэш, как ты понимаешь, весьма ограниченного размера. В Джаве AFAIK там значения до 128.

ВВ>>Питон, насколько я знаю, использует стек Си.

V>А теперь по русски,если не сложно.

А что непонятно? Питон не эмулирует стек, использует стек языка, на котором написан.

ВВ>>Смысл "типов по значению" здесь не в том, что они именно хранятся на стеке, это в общем случае неверно даже для языков со статической типизицией, скажем, нет гарантии, что при исполнении кода вида "int x = 1" значение x будет храниться именно на стеке. Смысл в том, что некоторые операции над примитивами становятся дешевле.


V>Ты прав, смысл в использовании аллокатора памяти стекового типа, который просто двигает текущую планку на нужное кол-во байт во время выделения/освобождения. К тому же, с гарантией доступа лишь из одного потока. И существуют устойчивые заблуждения насчет эффективности этого аллокатора в чистом виде. Я хочу сказать, что для этой разновидности аллокаторов эмулировать стек в том самом чистом виде — это удорожать операции, ибо такая эмуляция приводит к ограничению/требованию последовательного доступа к своим элементам, что на примере того же Форта или ассемблерных инструкций кривого x86 показывет, как много во время простых вычислений происходит дополнительных операций, связанных лишь с ротацией данных в стеке. Для настоящей дешевизны динамических операций надо "чистый" стековый аллокатор допиливать до паскалевской разновидности, тогда при аналогичных затратах на выделение/освобождение, мы не будем ограниченны навязанной упорядоченностью данных, как в случае стека. И да, условие гарантии однопоточности доступа к операциям выделения/освобождения должны прилагаться, как и для "настоящего" стека.


Я уже что-то запутался. Можно поподробнее что есть "паскалевая" разновидность аллокатора?
А эмуляция стека хороша хотя бы безопасностью — если интерператор вылетит, то хосту не сорвет крышу.
По поводу многопоточностью тоже не все ясно — у каждого потока должен быть свой отдельный стек, как и в случае с "настоящим" стеком.


V>>>В общем, замерять надо сначала, прежде чем на какой-то схеме останавливаться. По результатам моих экспериментов пятилетней давности быстрее всего себя в динамике на большом колв-е числовых типов показали вычисления на "типизации" с помощью двойной диспетчеризации. Таблицы виртуальных ф-ий они ведь тоже при частом использовании неплохо на кеш ложатся.


ВВ>>Я замерял. "Все в куче" — медленнее (ок. 10-15%) ну и память соответственно расходуется больше. Вариант с виртуальными функциями реализуем только в случае, если "все в куче". Опять же, я не видел большой разницы в производительности даже без проверок вообще, замерялось в т.ч. и на старой машине, сомневаюсь, что виртуальные функции тут неожиданно взлетят.


V>Я не мерял насчет "кучи", т.е. выделение/освобождение не участвовало, замерял только вычисления в случае проверки флагов для 4-х числовых типов и через двойную диспетчеризацию. Для случая проверки фажков там в среднем 5 проверок надо для вывода типа результата, или же 2 вызова виртуальной ф-ии. Опять же, для вызова виртуальных ф-ий наличие объекта на стеке не нужно. Если же ты в качестве "подложки" использовал что-то вроде дотнета (закралось подозрение из-за твоего утверждения насчет кучи и виртуальных ф-ий), то там надо генерить сразу дотнетный байт-код, а не свой. То бишь, мы непонятно что обсуждали.


Мы обсуждали возможность/невозможность создание переменных на стеке в динамике. В общем случае — такая возможность есть. Разница со статикой в следующем:
— необходимость иметь дескриптор типа
— ограниченные возможности расчету стека компилятором (но они есть, если действовать по моей модели — либо значение до 4 байт размером, либо указатель), то все вообще очень просто.
Re[34]: почему в вебе распространены именно динамические язы
От: Klapaucius  
Дата: 25.10.10 08:36
Оценка: +1
Здравствуйте, Mamut, Вы писали:

M>Ну то же самое можно и в C# сделать


Дело не в том, что в C# можно сделать то же самое. Дело в том, что в C# можно сделать иначе. Да и в Яве можно сделать иначе.

M>Особо других мейнстримных и не осталось


А что, в мейнстриме есть динамические языки кроме PHP? Ну, разве что, можно, с некоторой натяжкой, Питон посчитать.

M>Ага. То есть в случае с C# все ранво перекладывается на плечи программиста. Чтобы не забыл реализовать Maybe, чтобы не забыл его вернуть и т.п. То есть чуда по любому нет


Реализация, разумеется, перекладывается на плечи программиста. С помощью статической типизации можно только напомнить о переложении на плечи и, в какой-то степени, это переложение форсировать.
Предположим, что у нас есть функция Foo, которая может вернуть что-то, например элемент из коллекции, если он в ней есть, или не вернуть ничего, например, если искомого элемента в коллекции нет. У программиста, который написал Foo проблема: дать гарантию того, что он всегда вернет результат он не может. Другой программист, использующий Foo в своем коде, должен проверить, вернула ли она что-то или нет. Как первый программист может делегировать эту ответственность второму? В случае динамической типизации только описать ситуацию в документации. В случае статической типизации программист-1 может использовать Maybe и компилятор напомнит программисту-2, что нужно проверить возвращаемый результат.
Как сделать так, чтобы компилятор напомнил программисту-1 о том, чтоб он не забыл вернуть Maybe? Для этого в стат языках есть другие чудеса. В C# такое чудо называется "интерфейс". Программист-3 может написать
public interface IBar<T>
{
    Maybe<T> Foo();
}

И теперь компилятор напомнит программисту-2, пишущему реализацию Foo, о том, что нужно вернуть Maybe.
Как тут поможет динамика?

M>Зачем же всеми средствами


Вот и я удивляюсь: зачем?

M>Почти во всех — это каких?


Мне перечислить все языки с параметрическим полиморфизмом? На самом деле, все это можно сделать в языках и без него, но решение получится слишком тяжеловесным, никто им пользоваться не будет.
Динамическая типизация потому и появилась, что на заре развития языков программирования полиморфный код мог быть только динамическим. И весь прогресс статической типизации — это возможность писать все более полиморфный код, который при этом статически проверяется.

M>Ну мы то прекрасно знаем, что аналогии всегда неверны


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

M>Что предлагает язык, то и использую.


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

M>Скажет incompatible types


Правильно скажет. А вы говорили — компилятор молчит.
... << RSDN@Home 1.2.0 alpha 4 rev. 1476>>
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[26]: почему в вебе распространены именно динамические язы
От: Воронков Василий Россия  
Дата: 25.10.10 08:58
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Для случая проверки фажков там в среднем 5 проверок надо для вывода типа результата, или же 2 вызова виртуальной ф-ии. Опять же, для вызова виртуальных ф-ий наличие объекта на стеке не нужно.


А слона-то я не увидел У меня вывод типа результата осуществляется через специальную таблицу "соответствия типов". А потом уже идет проверка флажка, который вернулся из этой таблицы. Т.е. не тип проверяется. Выглядит это так:

private static int[,] opAffinity = 
{
 //ERR  UNI  INT  REA  BYT  CHR  LNG  DBL  STR  LST  ARR  TUP  REC  FUN  OBJ  LAZ  SEQ  MOD
 { ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___ }, //ERR
 { ___, UNI, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___ }, //UNI
 { ___, ___, INT, REA, ___, ___, LNG, DBL, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___ }, //INT
 { ___, ___, REA, REA, ___, ___, ___, DBL, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___ }, //REA
 { ___, ___, ___, ___, BYT, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___ }, //BYT
 { ___, ___, ___, ___, ___, CHR, ___, ___, STR, ___, ___, ___, ___, ___, ___, ___, ___, ___ }, //CHR
 { ___, ___, LNG, ___, ___, ___, LNG, DBL, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___ }, //LNG
 { ___, ___, DBL, DBL, ___, ___, DBL, DBL, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___ }, //DBL
 { ___, ___, ___, ___, ___, STR, ___, ___, STR, ___, ___, ___, ___, ___, ___, ___, ___, ___ }, //STR
 { ___, ___, ___, ___, ___, ___, ___, ___, ___, LST, ___, ___, ___, ___, ___, ___, ___, ___ }, //LST
 { ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ARR, ___, ___, ___, ___, ___, ___, ___ }, //ARR
 { ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, TUP, ___, ___, ___, ___, ___, ___ }, //TUP
 { ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, REC, ___, ___, ___, ___, ___ }, //REC
 { ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, FUN, ___, ___, ___, ___ }, //FUN
 { ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, OBJ, ___, ___, ___ }, //OBJ
 { ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, LAZ, ___, ___ }, //LAZ
 { ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, SEQ, ___ }, //SEQ
 { ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, ___, MOD }, //MOD
};


Соответственно, нужно узнать вывести тип (да и проверить допустимость операции):

var aff = opAffinity[left.Type, right.Type];

if (aff.Type == INT) {
  ...
}
...


Т.е. для int делается всего одна проверка, а не 5.
Re[21]: почему в вебе распространены именно динамические язы
От: WolfHound  
Дата: 25.10.10 13:41
Оценка:
Здравствуйте, lomeo, Вы писали:

L>Ты спросил что делать. "не так эффективны" — этим мы платим за гибкость.

Осталось понять в каком там месте гибкость.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[47]: почему в вебе распространены именно динамические язы
От: vdimas Россия  
Дата: 25.10.10 16:08
Оценка:
Здравствуйте, WolfHound, Вы писали:


V>>А чем вирус принципиально отличается, скажем, от драйвера?

WH>Тем что драйвер не устанавливается через дыру в парсере JPEG.

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

Например, для win7 народ часто включает флажок, чтобы винда не дергала каждый раз, когда нужны админские права для некоего действия, а у пользователя эти права уже есть. То бишь, если включен популярный вот этот режим для юзверей из админской группы, то только проблемы с подписью сертификата могут помочь увидеть попытку установки левого драйвера. С другой стороны, обязательное требование подписи дров к win7 x64 делает невозможным использование ряда ранее полезных бесплатных утилит.

В общем, вопрос открыт и у меня пока нет мнения. Дело ведь не обязательно в дыре парсера JPEG.. например, руткиты сегодня зачастую втюхиваются в нагрузку к полезным бесплатным программам (не только в нагрузку ко всяким варезным keygen). Похоже, только высокая цена сертификатов да ужесточение преследования за распространение вирусов и шпионов могут хоть как-то повлиять, но оба способа — болезненная палка о двух концах.

Даже вот эти по-умолчанию всплывающие окна с требованием подтвержденпия на каждый чих в win7 — по-сути роспись в беспомощности. Средний юзер всё-равно особо не всматривается, т.к. не шарит, и давит "yes" по привычке.
Re[35]: почему в вебе распространены именно динамические язы
От: FR  
Дата: 25.10.10 16:09
Оценка:
Здравствуйте, Klapaucius, Вы писали:

K>А что, в мейнстриме есть динамические языки кроме PHP? Ну, разве что, можно, с некоторой натяжкой, Питон посчитать.


С некоторой натяжкой и руби можно посчитать.
Раньше были кучи бейсиков, потом VB и Smalltalk.

K>Как сделать так, чтобы компилятор напомнил программисту-1 о том, чтоб он не забыл вернуть Maybe? Для этого в стат языках есть другие чудеса. В C# такое чудо называется "интерфейс". Программист-3 может написать


Интерфейсы ничем динамике ни противоречат, вот в питон недавно ввели http://www.python.org/dev/peps/pep-3119/ с другой стороны в статике вполне живет безинтерфейсная структурная типизация (записи и объекты OCаml).
Re[22]: почему в вебе распространены именно динамические язы
От: FR  
Дата: 25.10.10 16:23
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Осталось понять в каком там месте гибкость.


Тотальная полиморфность.
Упрощение и ускорение прототипирования за счет отказа от фиксированных типов данных.
Возможность горячей перезагрузки даже небольших кусков кода.
Гораздо большая гибкость в кодогенерации, возможность делать ее сразу в целевом языке или высокоуровневом AST
Более гибкое метапрограммирование (lisp) позволяющее писать код который пишет код который ...
Доступность блоков компилятора и интерпретатора в рантайме позволяющее делать управляемую кастомную интерпретацию.
Ну и конечно самомодифицирующийся код
Re[31]: почему в вебе распространены именно динамические язы
От: vdimas Россия  
Дата: 25.10.10 16:33
Оценка:
Здравствуйте, Klapaucius, Вы писали:

С одной стороны Maybe удобен, с другой стороны, позволит протаскивать null достаточно далеко, чтобы потерять место, где он возник. ИМХО, чем раньше будет проверка результата, тем лучше.

Можно использовать некий хелпер NotNull:
public class NotNull<T> where T : class 
{
    T _value;

    private NotNull(T value) {
        if(value == null)
            throw new ArgumentNullException();

        _value = value;
    }

    public static implicit operator T(NotNull<T> notNullValue) {...}
    public static implicit operator NotNull<T>(value) {...}
}


public interface IBar<T>
{
    NotNull<T> Foo();
}


Одно неприятно: из-за дефолтного конструктора value-типов надежная реализация может быть лишь на ref-типах.
Re[23]: почему в вебе распространены именно динамические язы
От: WolfHound  
Дата: 25.10.10 16:44
Оценка:
Здравствуйте, FR, Вы писали:

FR>Тотальная полиморфность.

Зачем?

FR>Упрощение и ускорение прототипирования за счет отказа от фиксированных типов данных.

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

FR>Возможность горячей перезагрузки даже небольших кусков кода.

Ну это я и статику так скомпилировать могу.
Накладных расходов один jmp на вызов функции.

FR>Гораздо большая гибкость в кодогенерации, возможность делать ее сразу в целевом языке или высокоуровневом AST

Немерле.

FR>Более гибкое метапрограммирование (lisp) позволяющее писать код который пишет код который ...

Ты блин не поверишь...

FR>Доступность блоков компилятора и интерпретатора в рантайме позволяющее делать управляемую кастомную интерпретацию.

И снова немерле.

FR>Ну и конечно самомодифицирующийся код

Зачем?
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.