Archive for category Ocaml

Функционалы против классов

Товарищ (RedChrom) задал вопрос, что я использую больше при разработке на Окамле. Не особо задумываясь ответил, что фифти-фифти. Потом сделал простой grep на свои исходники, и выяснил, что на 80% всё-таки модули и функторы. Причём, объекты и классы по большей части в очень старых исходниках. Сейчас 100% функторы.

Read the rest of this entry »

, , ,

1 Comment

JavaScript: безопасный код

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

Как известно, JavaScript — язык c динамической (для классов с утиной) типизацией, с очень плохо развитой системой типов. Стандартный интерпретатор даже в браузерах Mozilla с расширениями разработчика отлавливает минимум ошибок. Практически все эти ошибки — синтаксические. В результате, писать надёжный код на JavaScript предельно сложно. Положение усугубляет фактическая невозможность запуска программы без использования браузера, т.е. нет никакой песочницы для тестов.

В этой статье я попытаюсь описать некоторые технологии, которые помогут знакомому с Ocaml человеку существенно сократить время написания безопасного, стабильного и более-менее компактного JS-кода. Впрочем, описываемые техники есть и для некоторых других языков с развитой системой типов (например, Haskell).

Read the rest of this entry »

, , , ,

6 Comments

Решение для решателя Sudoku

Хотел вечерком размять мозг — набросать какой-нибудь особенно красивый решатель Sudoku на Ocaml. Но возникла мысль изучить вражеские аналоги. Итак, решатель Sudoku размером 800 с небольшим байт:

include Set.Make(struct type t = (int * int) * int let compare = compare end)
 
let (@) g f x = g (f x) and id x = x and sw f x y = f y x and zip x y = (x, y)
 
let fold9 f = let rec loop i = if i>8 then id else loop (i+1) @ f i in loop 0
 
let fold81 f = fold9 (fold9 @ (@) f @ zip)
 
let mark ((i,j),x as e) : t -> t =
  add e @ fold9 (fun k -> remove ((i/3*3 + k/3, j/3*3 + k mod 3), x) @
    remove ((i,j),k) @ remove ((i,k),x) @ remove ((k,j),x))
 
let search =
  let g p f s = fold (f @ sw mark s) (filter ((=) p @ fst) s) in
  fold81 g
 
let read () =
  let f p = Scanf.scanf "%d " (fun x -> if x>0 then mark (p,x-1) else id) in
  fold81 f (fold81 (fold9 @ ((@) add @ zip)) empty)
 
let print s () =
  let pr ((i,j),x) = Printf.printf "%d%c" (x+1) (if j=8 then '\n' else ' ') in
  iter pr s; print_newline ();;
 
search print (read ()) ()

Вы посмотрите эту красоту, это же [почти] совершенство! А если учесть, что 272 байта — это чтение задачи с STDIN и вывод результата, размер кода сокращается до менее чем 600 байт.

Read the rest of this entry »

, , , ,

No Comments

Микроязык OpQL

Сделал микроязык запросов для oProxy. Служит, собственно, для управления ею. Что умеет:

  1. Показать всякую текущую статистику (устаревшее show_workers, show_nodes и т.д.)
  2. Управлять списками наблюдения.

Read the rest of this entry »

, , , ,

No Comments

ocaml-epoll

Написал биндинг для работы с epoll(7). Пока бета, но на ней уже ради эксперимента написал успешно работающий маленький веб-сервер :) Скачать можно со страницы Software. epoll является аналогом select() и poll(), но с увеличением количества обрабатываемых сокетов сложность остаётся O(1), что позволяет без особых задержек обрабатывать тысячи параллельных соединений.

, ,

2 Comments

Nginx против oProxy: друг другу сливаем :)

Потестировал производительность проксирования HTTP трафика. Результаты местами получились весьма неожиданными.

Повторю, тестировалось именно проксирование. Известно, что при прямой отдаче и Apache, и Nginx использует ядрёный вызов sendfile(), который отдаёт содержимое файлика в сокет без лишних копирований. Это неинтересно. А вот проксирование — это совсем другое дело. В ядре пока что ещё нет прямых путей для копирования из сокета в сокет (есть полупрямой вариант splice() + pipe(), но как выяснилось он даже не на всех современных ядрах работает).

Итак…

Read the rest of this entry »

, ,

6 Comments

Пора в production? Скоро узнаем.

Готовимся к продакшен тестированию. Надеюсь, завтра запустить всё воедино на тестовых машинах.

Из нового:

  • Балансировка нагрузки. Универсальный модуль для любых видов соединений. Написано кривовато, но работает. Заведует всеми узлами мастер-процесс. Это несколько замедляет процесс (рабочим приходится больше общаться с мастером), зато позволяет контролировать балансировку в одном месте.
  • Файлик: список сайтов. Пока каждый сайт можно только включить/выключить и прописать алиасы. Кроме того, на будущее есть поле “домашняя директория сайта”. В ближайшее время есть планы проксёй отдавать статичные файлы. Не понятно, что делать с .htaccess. Не хочется забивать, как это нынче делается в Nginx.
  • Файлик: список узлов. Представляет из себя IP, мастер-пароль, список ролей.
  • Роли. Что каждая машина умеет/должна делать. От этого зависит поведение балансировщика и некоторых скриптов. Предопределённые роли: worker_http (узел умеет обрабатывать HTTP-запросы), master (узел будет точкой входа, где висит балансировщик) и другие. Всё рассказывать раньше времени не буду :)
  • Мониторинг. Наконец нашёл, где заюзать функционалы. На основе этого функционала (functional) написан мониторинг файлов. Как результат, прокся умеет автоматически подгружать изменённый список сайтов или узлов.
  • Новый параметр у oproxyctl: show_nodes. Показывает известные узлы. Кто в дауне, сколько у каждого активных запросов, сколько всего обработано. Может оказаться полезным для выяснения проблемных узлов.
  • Поддерживаем новый протокол, который я сам выдумал :) Служит для различных сервисных запросов к узлу. Поскольку позволяет совершать совершенно небезопасные вещи, авторизация происходит без передачи открытого пароля по сети.
  • Новая утилита: clusterctl. Умеет 1) запустить на узлах с указанной ролью (или на всех, или на определённом IP) определённую команду и вернуть в STDOUT/STDERR что в итоге получилось 2) рассказывать список ролей текущей ноды 3) рассказывать список узлов, поддерживающих указанную роль. Служит для сервисных скриптов.
  • Прокся умеет выставлять X-Forwarded-For, чтобы в конечном итоге в логи попадал нужный IP.
  • Сервисные скрипты: apachectl (рестарт Апача на всех узлах), repquota и другие.
  • Оптимизация, стабильность.

Допил коньяк. Опять потянуло на философию…

, , ,

No Comments

TCP_NODELAY, Ocaml 3.11

Обнаружил существенный недостаток модуля Unix в Ocaml 3.10. Нет возможности отключить алгоритм Нагла для соединений. Как следствие, приложения с высокой интерактивностью существенно теряют в производительности (меня в данном случае волнует MySQL). Лерой обещал устранить в версии 3.11. Учитывая, что она уже RC, возможно, имеет смысл начать к ней приглядываться. Тем более что там, помимо прочего, появилась поддержка Dynlink’а для нативного кода. Чего тоже сильно не хватало.

2 Comments

oProxy (о прокси, about proxy)

Настроение: подшофе. Первый эксбиционисткий пост, как и положено в б-сферах. Прости меня, г-поди!

Read the rest of this entry »

No Comments

Рыбак рыбака

Иногда проекты на Окамле легко идентифицировать. Вот какие ошибки шлёт один из самых популярных сайт-мониторингов host-tracker.com:

Ошибка HTTP:Http_client.No_reply

Характерное написание исключения вызвало подозрения. И не зря:

$ grep No_reply netclient/http_client.mli
exception No_reply;;

Они бы ещё через маршала давали API к себе — цены бы им не было :)

3 Comments