Обновление ObjectScript 1.6.3-dev - улучшение производительности.
ObjectScript - динамический язык, тем не менее компилятор теперь умеет автоматически определять тип переменных.
Как OS определяет тип переменных?
Компилятор смотрит, в каком контексте используется локальная переменная. Если переменной присваиваются только числовые константы и результаты выражений, которые возвращают число, то компилятор OS маркирует тип данной переменной, как числовой.
Как это работает на практике (код компилятора с комментариями, из файла objectscript.cpp):
switch(exp->type){ case EXP_TYPE_CONST_NUMBER: // это числовая константа, определенно результат - числовой тип exp->local_var.type = CVT_NUMBER; break; case EXP_TYPE_GET_LOCAL_VAR: // считываем тип локальной переменной из декларативной области, // компилятор сохраняет туда рассчитанный тип переменной exp->local_var.type = scope->getLocalVar( exp->local_var).type; break; // записываем в локальную переменную значение case EXP_TYPE_SET_LOCAL_VAR: { Expression * exp2 = exp->list[0]; // если ранее компилятор не определил, что тип переменной динамический, // то пытаемся определить тип сейчас if( exp->local_var.type != CVT_DYNAMIC){ ECompiledValueType old_type = exp->local_var.type; // если переменной присваивается числовое значение if( exp2->local_var.type == CVT_NUMBER){ // то маркируем тип переменной, как числовой exp->local_var.type = CVT_NUMBER; }else{ // иначе, переменная имеет динамический тип // т.е. если даже ранее переменной присваивались числовые значения, // то теперь мы понимаем, что переменная все же используется // не только как число exp->local_var.type = CVT_DYNAMIC; } if( old_type != exp->local_var.type){ // сохраняем тип в декларативной области scope->getLocalVar( exp->local_var).type = exp->local_var.type; } } break; } // обрабатываем разные математические операторы case EXP_TYPE_BIT_AND: // & case EXP_TYPE_BIT_OR: // | case EXP_TYPE_BIT_XOR: // ^ case EXP_TYPE_COMPARE: // <=> case EXP_TYPE_ADD: // + case EXP_TYPE_SUB: // - case EXP_TYPE_MUL: // * case EXP_TYPE_DIV: // / case EXP_TYPE_MOD: // % case EXP_TYPE_LSHIFT: // << case EXP_TYPE_RSHIFT: // >> case EXP_TYPE_POW: // ** { Expression * left_exp = exp->list[0]; Expression * right_exp = exp->list[1]; // если аргументы операторов - числовые if( left_exp->local_var.type == CVT_NUMBER && right_exp->local_var.type == CVT_NUMBER){ // то определенно результат будет числовой exp->local_var.type = CVT_NUMBER; }else{ // иначе результат оператора является не известным на момент // компиляции типом exp->local_var.type = CVT_DYNAMIC; } break; }
Далее при генерации команд для виртуальной машины OS, компилятор смотрит, можно ли задействовать более быстрые варианты команд. В виртуальную машину были добавлены новые команды (OP_NUMBER_ADD, OP_NUMBER_SUB и др.) для выполнения математических операторов над числовыми аргументами, которые сразу выполняют математическую операцию без необходимости проверки типа. На этом и строится новая модель виртуальной машины и улучшение производительности.
Основной мой тест производительности - это fannkuch. В этом тесте компилятор соптимизировал всего несколько переменных, но даже это дало выигрыш. Все тестировалось на виндах в win32 версиях всех языков:
OS 1.6.3-dev - 9,79 сек (это на секунду быстрее предыдущей версии)
Lua 5.1 - 10,89 сек
Ruby 2.0 - 18,45 сек
PHP 5.3.22 - 27,87 сек
Чем меньше время, тем лучше.
Тут показано среднее время по 20 итерациям с параметром запуска алгоритма равным 10.
P.S. по такому же принципу можно реализовать автоматическое определение булевых выражений и некоторых др. типов.
Скажи, а ты синтаксис языка нигде не описывал в каком-то кратком виде?
Ну примерно вот что-то такое http://www.lua.org/manual/5.1/manual.html#8
Я вот коротко отвечу вам на вопросы в первом посте. Зачем там запятая, здесь точка, скобка и т.п. Почему программу нужно выделять в Begin/End, подробно описывать переменные до их использования, вместо того что бы целые конструкции заменить парой-тройкой закарючек...
Ответ простой: языки, которые вы осуждаете/упрощаете созданы Программистами и для Программистов, а не быдло-кодерами и прежде всего были рассчитаны на получение удовольствия от программирования и базировались на человекопонятности. При этом находя отличный компромисс между удобством интерпритированием кода машиной и написанием его человеком. Вы же пытаетесь изобрести очередной язык, далёкий от удобности и человеку и машине… Зачем? Куда ещё "круче", чем уже есть?!
Хотите что бы программист после сотой строчки своего кода, уже как баран на новые ворота смотрел на первую?
UnitPoint
Уважаю твой труд. Но все же не могу понять, зачем изобретать велосипед ?
Просто не увидел ничего принципиально нового, кроме очень-очень сомнительного "облегчения синтаксиса" с запятыми.
Меньше кол-во знаков - не значит более читабельный код. По-русски когда пишешь, можно тоже писать все строчными буквами и без знаков препинания. Народ все поймет, но не заценит. Знаки форматирования/препинания - они именно и нужны для облечения восприятия и конкретизации текста. Это не блажь, и не подсказка "тупому компилятору". Они нужны самому программисту.
Маг
> кроме очень-очень сомнительного "облегчения синтаксиса" с запятыми.
+1
Мало какой редактор кода сегодня не умеет дополнять скобки, функции, методы и запятые, а также следить за отступами. Для этого же велосипеда не будет ни одной IDE, а универсальные редакторы просто не разберутся в синтаксисе. Как говорится язык - это пол-дела. Когда он будет мейнстримом - вот в чём вопрос.
Нет, серьёзно, ни один адекватный программист не забросит Си/С++ за сложный синтаксис, а вот отсутствие stdlib и вменяемого редактора...
Информация на первой странице не совсем актуально, надо бы ее обновить. Запятые - must have с версии 1.5-dev от 14 марта 2013.
x
> Скажи, а ты синтаксис языка нигде не описывал в каком-то кратком виде?
Полное описание синтаксиса языка есть на вики Programming in ObjectScript, в кратком виде не описывал.
CMake Error at proj.win32/os/CMakeLists.txt:50 (add_executable):
Cannot find source file:
./../../source/ext-curl/os-curl.hвы каждым релизом ломаете сборку на линуксе)
RPG
> вы каждым релизом ломаете сборку на линуксе)
Да вроде не сломалось, только что проверил, делал так:
git clone git://github.com/unitpoint/objectscript.git cd ./objectscript mkdir build && cd build cmake -DCMAKE_INSTALL_PREFIX=$(pwd)/../ .. make make install
OS использует при компиляции либы cURL (загрузка по протоколу http и др.) и PCRE (регулярные выражения), уже установленые в linux. Правда скомпилится и без них (ругнется немного при сборке), но классы Curl и Regexp тогда будут недоступны. Сейчас в комплекте также идет sqlite3. Примеры использования есть в test.os
запуск тестового скрипта:
../bin/oscript ../examples-os/test.os
P.S. oscript надо бы переименовать в os
UnitPoint
Как хранятся "порядковые" поля объектов?
var o = {}
o[123] = "aaa"
o["key"] = "bbb"
Ну т.е. понятно что числа тоже какой-то хэшмап формируют, но он общий со строковыми ключами или их два разных?
Выполнение операции в хеш-таблице начинается с вычисления хеш-функции от ключа. Получающееся хеш-значение играет роль индекса в массиве H. Затем выполняемая операция (добавление, удаление или поиск) перенаправляется объекту, который хранится в соответствующей ячейке массива . Ситуация, когда для различных ключей получается одно и то же хеш-значение, называется коллизией. Существует несколько способов разрешения коллизий.
ObjectScript использует метод цепочек: каждая ячейка массива H является указателем на связный список (цепочку) пар ключ-значение, соответствующих одному и тому же хеш-значению ключа. Коллизии просто приводят к тому, что появляются цепочки длиной более одного элемента.
В ObjectScript хеш-функция от ключа реализована следующим образом:
int OS::Core::getValueHash(const Value& index)
{
switch(OS_VALUE_TYPE(index)){
case OS_VALUE_TYPE_NULL:
return 0;
case OS_VALUE_TYPE_BOOL:
return OS_VALUE_VARIANT(index).boolean;
case OS_VALUE_TYPE_NUMBER:
{
float d = (float)OS_VALUE_NUMBER(index);
OS_BYTE * buf = (OS_BYTE*)&d;
int hash = OS_STR_HASH_START_VALUE;
OS_ADD_STR_HASH_VALUE; buf++;
OS_ADD_STR_HASH_VALUE; buf++;
OS_ADD_STR_HASH_VALUE; buf++;
OS_ADD_STR_HASH_VALUE;
return hash;
}
case OS_VALUE_TYPE_STRING:
return OS_VALUE_VARIANT(index).string->hash;
}
// all other values share same area with index.v.value so just use it as hash
return OS_PTR_HASH(OS_VALUE_VARIANT(index).value);
}т.е. хеш от строки уже хранится в объекте строки (это позволяет хранить одинаковые строки в одном экземпляре, даже полученные в рантайме), хеш от числа - некая контрольная сумма от бинарного представления числа в виде float (это нужно, чтобы задействовать по возможности все биты хеша примерно одинакого), хеш для булевого значения - само значение, для остальных типов хеш высчитывается на основе указателя аллоцированного объекта.
Для строк легко проверить, что одинаковые строки хранятся в одном экземпляре на следующем примере:
var s1 = "John Smith" print(s1, "id: " .. s1.id) var s2, s3 = "John", "Smith" print(s2, "id: " .. s2.id) print(s3, "id: " .. s3.id) var s4 = s2 .. " " .. s3 print(s4, "id: " .. s4.id)
выведет:
John Smith id: 1031 John id: 1036 Smith id: 1037 John Smith id: 1031
id - внутренний идентификатор объекта в системе сборки мусора, он всегда уникальный. Видно, что константная строка "John Smith" и полученная в рантайме с помощью конкатенации строка "John Smith" получила идентификатор равный 1031. Это резко уменьшает размер используемой памяти в ObjectScript.
Добавил к языку расширение OpenGL и немного примеров, матрица:
полный исходник этого примера
Папка с примерами: https://github.com/unitpoint/objectscript/tree/master/examples-os/opengl
Как выглядит сркрипт:
Т.е. очень похоже на C++, можно на скрипте быстро написать и сразу запустить. Для чего это может использоваться? - скорее всего для обучения OpenGL или чтобы быстро что-то проверить.
P.S. пока не весь функционал OpenGL реализован, компиляция настроена под windows, запускаемый файл bin\os.exe скомпилирован с поддержкой этого расширения
P.P.S. генератор для source/ext-opengl/os-opengl.inc реализован на самом OS в этом файле source/ext-opengl/parse-gl.os
UnitPoint
Верной дорогой идёте, товарищ!
Возможно использовать OS в моих играх в том качестве как Lua?
polyfrag
> Возможно использовать OS в моих играх в том качестве как Lua?
UnitPoint
> Для чего это может использоваться? - скорее всего для обучения OpenGL или чтобы
> быстро что-то проверить.
Lua давно используется вовсю в играх как язык программирования (логики как минимум). Так что если язык до этого дорастёт - почему нет?:)
Нельзя использовать как библиотеку, я так понял.
Тема в архиве.