Beep: первые результаты
От: dmz Россия  
Дата: 28.02.09 06:51
Оценка: 195 (10) :)
Для начала, спасибо всем, кто отвечал на мои вопросы по данной теме. Без вас этот язык... был бы написан, но его писать было бы намного более уныло.
Для тех кто не в курсе, кратко напомню: 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
beep
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.