Для начала, спасибо всем, кто отвечал на мои вопросы по данной теме. Без вас этот язык... был бы написан, но его писать было бы намного более уныло.
Для тех кто не в курсе, кратко напомню: Beep (
Бип, звук, которым забивают непечатные ругательства в эфире, так как именно их я произнес, когда понял, что мне придется написать этот язык) — это питоно-луа образный язык со статической типизацией и выводом типов, компилируемый в байткод и предназначенный, по замыслу, для скриптования на микроконтроллерах (таких, куда не впихнешь Java и Lua). Является заменой форту. Сейчас он работает на MSP TI430, размер памяти именно на язык определяется размером выделенного хипа и стеков. Сейчас это контроллер с 5K RAM на борту, но будет работать и на 2K — младшие процессоры в линейке.
Сейчас, после переписывания компилятора в человеческий вид и добавления ряда полезных фич, решил, для смеха, сравнить производительность на похожем скрипте с питоном (скрипты в конце поста). Запускалось на PC, естественно, результаты оказались слегка удивительными:
Beep с компиляцией
dmz@x200:~/prj/raccoon/beepvm$ time (./beepc nmea.beep >/dev/null 2>1 && ./beepvm ./nmea.bin >/dev/null)
real 0m1.500s
user 0m1.480s
sys 0m0.004s
Beep, заранее скомпилировано
dmz@x200:~/prj/raccoon/beepvm$ time (./beepvm ./nmea.bin >/dev/null)
real 0m1.386s
user 0m1.352s
sys 0m0.000s
Python
dmz@x200:~/prj/raccoon/beepvm$ time python ./nmea.py >/dev/null
real 0m3.251s
user 0m3.228s
sys 0m0.004s
Начальные условия: питону доступна вся память, сколько раз запускался сборщик мусора (какой бы он у него ни был) — неизвестно.
Бипу доступно 1024 байта хипа и 256 байт (128 16-битных слов) стека. Сборщик мусора запускался 10924 раза.
Если из скрипта на Бипе убрать strdup(...) — которая каждый раз копирует строку в динамическую память, то количество сборок мусора уменьшается до 5568, результат по времени практически такой-же, и я кажется, знаю почему: сборщих халтурит, освобождая за O(текущая глубина стека), а вот что бы его заставить работать по-честному, надо адресами загадить весь стек, пока не знаю как.
Структуры и строки пока иммутабельны, то есть каждое операция со строкой или создание структуры — приводят к честному копированию.
Никаких оптимизаций чего-либо, кроме скорости компиляции, не проводилось; это практически первые реальные запуски (Да, на микроконтроллере оно тоже работает). Конечно не с такими результатами, чуть позже запущу тот же скрипт.
Кому интересно, исходные коды скриптов (да, я знаю что на питоне так не пишут)
Бип:
type nmea_gga { time_utc: string,
lat: string,
lat_semi: string,
lon: string,
lon_semi: string,
fix: string,
sat: string
}
def nmea_parse_gga(s)
{
local c, i = 0, j = 0, comma = 0;
local len = strlen(s);
local utc, lat, lat_s, lon, lon_s, fix, sat;
while i < len {
c = strnth(s, i);
if c == ',' || c == '*' then
{
comma = comma + 1;
if comma == 2 then utc = strsub(s, j, 6);
elif comma == 3 then lat = strsub(s, j, i-j);
elif comma == 4 then lat_s = strsub(s, j, i-j);
elif comma == 5 then lon = strsub(s, j, i-j);
elif comma == 6 then lon_s = strsub(s, j, i-j);
elif comma == 7 then fix = strsub(s, j, i-j);
elif comma == 8 then sat = strsub(s, j, i-j);
j = i+1;
}
i = i + 1;
if i == len || c == '*' then break;
}
ret { time_utc=utc, lat=lat, lat_semi=lat_s,
lon=lon, lon_semi=lon_s,
fix=fix, sat=sat
of nmea_gga
};
}
def main()
{
local s = "$GPGGA,121505,4807.038,N,01131.324,E,1,08,0,9133.4,M,46.9,M,,*42";
local i = 0;
while i < 0xFFFF {
local gga = nmea_parse_gga(s);
putsn(gga.time_utc);
putsn(gga.sat);
putsn(gga.fix);
putsn(gga.lat);
putsn(gga.lat_semi);
putsn(gga.lon);
putsn(gga.lon_semi);
i = i + 1;
}
}
Питон:
class nmea_gga:
def __init__(self, time_utc, lat, lat_semi, lon, lon_semi, fix, sat):
self.time_utc = time_utc
self.lat = lat
self.lat_semi = lat_semi
self.lon = lon
self.lon_semi = lon_semi
self.fix = fix
self.sat = sat
def nmea_parse_gga(s):
(c, i, j, comma) = ('',0,0,0)
ln = len(s)
(utc, lat, lat_s, lon, lon_s, fix, sat) = ('','','','','','','')
while i < ln:
c = s[i]
if c == ',' or c == '*':
comma = comma + 1
if comma == 2: utc = s[j:j+6]
elif comma == 3: lat = s[j:i]
elif comma == 4: lat_s = s[j:i]
elif comma == 5: lon = s[j:i]
elif comma == 6: lon_s = s[j:i]
elif comma == 7: fix = s[j:i]
elif comma == 8: sat = s[j:i]
j = i + 1
i = i + 1
if i == ln or c == '*':
break
return nmea_gga(time_utc=utc, lat=lat, lat_semi=lat_s, lon=lon, lon_semi=lon_s, fix=fix, sat=sat)
if __name__ == "__main__":
s = "$GPGGA,121505,4807.038,N,01131.324,E,1,08,0,9133.4,M,46.9,M,,*42";
i = 0
while i < 0xFFFF:
gga = nmea_parse_gga(s)
print gga.time_utc
print gga.sat
print gga.fix
print gga.lat
print gga.lat_semi
print gga.lon
print gga.lon_semi
i = i + 1