vak: (Default)
Взамен почившего в бозе vak.ru потихоньку оживляю новый сервер. Вместо набившего оскомину Apache я поставил новомодный Caddy. И даже не ради того, что написан он на Go, хотя тоже приятно. Просто конфигурировать его легче.
vak: (Default)
Утилита Lex была придумана как способ эффективно применять набор регулярных выражений к входному потоку. Когда у нас одно регулярное выражение - используем grep. Но если их несколько, эффективнее будет применить Lex. В документации на Flex есть пример кода, подсчитывающего количество строк, слов и символов во входном потоке, как wc. Вот тот же пример, переписанный для языка Go и утилиты nex:
/\n/ {
lval.nline++ // Количество строк
lval.nchar++
}

/[^ \t\n]+/ {
lval.nword++ // Количество слов
lval.nchar += len(yylex.Text())
}

/./ {
lval.nchar++ // Количество символов
}

//

package main
import (
"fmt"
"os"
)

type yySymType struct { // В этой структуре накапливаем результат
nline int
nchar int
nword int
}

func main() {
var result yySymType
lex := NewLexer(os.Stdin) // Сканируем стандартный ввод
lex.Lex(&result)
fmt.Printf("Lines: %d\n", result.nline)
fmt.Printf("Words: %d\n", result.nword)
fmt.Printf("Chars: %d\n", result.nchar)
}
Первая половина файла, до строчки //, задаёт обработку входного потока. В структуре yySymType обычно возвращается информация о следующей лексеме для Yacc, но здесь мы используем её для накопления информации о входном потоке.

Чаще всего Lex используют в связке с Yacc для построения синтаксических анализаторов, но это вовсе необязательно. Массу пользы можно извлечь из Lex самого по себе.

Nex представляет собой тот же Lex, но переписанный на язык Go. Исходники и описание здесь: https://github.com/blynn/nex. Устанавливается Nex командой:
go get github.com/blynn/nex
Бинарник оказывается в каталоге ~/go/bin/nex

Компилируем и запускаем вышеприведённый код. Утилитой nex обрабатываем входной файл wc.nex, генерится файл с кодом на Go: wc.nn.go. Компилируем его и запускаем:
$ nex wc.nex
$ go build wc.nn.go
$ ./wc.nn < /etc/fstab Lines: 12 Words: 88 Chars: 675
Сравниваем результат со стандартной утилитой wc:
$ wc /etc/fstab
 12  88 675 /etc/fstab
vak: (Default)
Новости в мире операционных систем: один крутой чувак из MIT сваял Юникс на языке Go.

"Biscuit runs significant existing applications such as NGINX and Redis without source modification by exposing a POSIX-subset system call interface. Supported features include multi-core, kernel-supported user threads, futexes, IPC, mmap, copy-on-write fork, vnode and name caches, a logging file system, and TCP/IP sockets. Biscuit implements two significant device drivers in Go: one for AHCI SATA disk controllers and one for Intel 82599-based Ethernet controllers. Biscuit has nearly 28 thousand lines of Go, 1546 lines of assembler, and no C."

Статья: "The benefits and costs of writing a POSIX kernel in a high-level language"

Исходники на Гитхабе: https://github.com/mit-pdos/biscuit
vak: (Default)
Закончил парсер для языка Verilog. Удалось приспособить Yacc-овскую грамматику от проекта Yosys, переписав её на Go. Лексический сканер позаимствовал от самого компилятора Go.

Узнал много забавного про константы в Верилоге. Обычный десятичный литерал типа 123 имеет знаковый тип. Если добавить к нему десятичный префикс ('d123), он становится беззнаковым. Чтобы снова превратить его в знаковый, надо добавить буковку s: 'sd123. Разницу можно заметить на примерах:
5 - 10 = -5
'd5 - 10 = 4294967291
'sd5 - 10 = -5
vak: (Default)
В таблице для каждой пары языков X и Y показана активность обсуждения темы "Почему мы мигрировали с языка X на язык Y". Что интересно - побеждает язык Go (16.41%). На втором месте Си (14.26%).

vak: (Default)
Провёл простейшее измерение memory footprint для примера "Hello world" на четырёх языках: C, Go, C++ и D. Размер требуемой памяти и количество прерываний подкачки страниц измерялись утилитой /usr/bin/time. Операционная система Ubuntu Linux.
Language    Resident Size   Page faults
----------------------------------------
C           1324k           61
Go          1064k           120
C++         3052k           126
D           2796k           144 
Как можно видеть, Go требует наименьшего размера памяти: в три раза меньше чем C++ и D, и на 30% меньше чем Си.
vak: (Default)
Тридцать лет назад у меня родился сын, и я проводил много времени, прогуливаясь с детской коляской по живописным окрестностям славного города Долгопрудного. Под мышкой я держал невероятную ценность, доставшуюся мне по удачному стечению обстоятельств: книжку "Язык программирования Си" Кернигана/Ритчи. Присаживался на лавочки и тщательно штудировал мудрость далёкий американских инженеров. Это было еще первое издание, аж 1985 года. Пытался найти обложку в сети - не смог.

Сейчас получаю такое же интеллектуальное удовольствие от книжки "The Go Programming Language" Кернигана/Донована. Великое дело сделали товарищи: сваяли язык 21 века. Не зря он сейчас вытесняет Джаву и прочих из серьёзных проектов.

vak: (Улыбка)
Задачка из математического кружка:

Три фермера продавали куриц на местном рынке. У одного было 10 куриц, у второго — 16, у третьего — 26. Чтобы не конкурировать между собой, они договорились продавать куриц по одной цене. К обеду они решили, что продажи идут не так уж хорошо, поэтому они все одинаково понизили цену. К концу дня они продали всех куриц. Оказалось, что каждый из фермеров за этот день выручил 35 долларов. Какова была цена за курицу до обеда и после обеда?

Програмка на SQL от Vladimir Begun:
SQL> WITH
2 c$ AS (SELECT /*+ MATERIALIZE */ ROWNUM v FROM dual CONNECT BY LEVEL <= 3500)
3 , c1 AS (SELECT /*+ MATERIALIZE */ v - 1 v FROM c$ WHERE v <= 11)
4 , c2 AS (SELECT /*+ MATERIALIZE */ v - 1 v FROM c$ WHERE v <= 17)
5 , c3 AS (SELECT /*+ MATERIALIZE */ v - 1 v FROM c$ WHERE v <= 27)
6 , cr1 AS (
7 SELECT c.v f, (10 - c.v) s, c$1.v x, c$2.v y
8 FROM c$ c$1, c$ c$2, c1 c
9 WHERE c.v * c$1.v + (10 - c.v) * c$2.v = 3500 AND c$1.v >= c$2.v
10 )
11 , cr2 AS (
12 SELECT c.v f, (16 - c.v) s, c$1.v x, c$2.v y
13 FROM c$ c$1, c$ c$2, c2 c
14 WHERE c.v * c$1.v + (16 - c.v) * c$2.v = 3500 AND c$1.v >= c$2.v
15 )
16 , cr3 AS (
17 SELECT c.v f, (26 - c.v) s, c$1.v x, c$2.v y
18 FROM c$ c$1, c$ c$2, c3 c
19 WHERE c.v * c$1.v + (26 - c.v) * c$2.v = 3500 AND c$1.v >= c$2.v
20 )
21 SELECT /*+ USE_HASH(cr1 cr2 cr3) LEADING(cr1 cr2 cr3) */
22 cr1.f c1_f, cr1.s c1_s, cr2.f c2_f, cr2.s c2_s
23 , cr3.f c3_f, cr3.s c3_s, cr1.x / 100 x$, cr1.y / 100 y$
24 FROM cr1, cr2, cr3
25 WHERE cr1.x = cr2.x AND cr1.y = cr2.y AND cr2.x = cr3.x AND cr2.y = cr3.y
26 /
Находит решение за 34 секунды на процессоре 2.7 ГГц.

Есть также варианты на Паскале и Go. Да, я знаю что программу можно лёгким движение ускорить на пару порядков, но тогда она не будет годиться для измерения скорости разных языков и компиляторов.