<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JL&#039;s blog &#187; Ocaml</title>
	<atom:link href="http://john.5070.info/category/ocaml/feed/" rel="self" type="application/rss+xml" />
	<link>http://john.5070.info</link>
	<description>:-)</description>
	<lastBuildDate>Sun, 06 Dec 2009 17:11:56 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Функционалы против классов</title>
		<link>http://john.5070.info/2009/10/%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%be%d0%bd%d0%b0%d0%bb%d1%8b-%d0%bf%d1%80%d0%be%d1%82%d0%b8%d0%b2-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%be%d0%b2/</link>
		<comments>http://john.5070.info/2009/10/%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%be%d0%bd%d0%b0%d0%bb%d1%8b-%d0%bf%d1%80%d0%be%d1%82%d0%b8%d0%b2-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%be%d0%b2/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 16:57:30 +0000</pubDate>
		<dc:creator>John Lepikhin</dc:creator>
				<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[LWT]]></category>
		<category><![CDATA[функтор]]></category>

		<guid isPermaLink="false">http://john.5070.info/?p=203</guid>
		<description><![CDATA[Товарищ (RedChrom) задал вопрос, что я использую больше при разработке на Окамле. Не особо задумываясь ответил, что фифти-фифти. Потом сделал простой grep на свои исходники, и выяснил, что на 80% всё-таки модули и функторы. Причём, объекты и классы по большей части в очень старых исходниках. Сейчас 100% функторы.
Сейчас развлекаюсь написанием универсального интерфейса к разным хранилищам [...]]]></description>
			<content:encoded><![CDATA[<p>Товарищ (RedChrom) задал вопрос, что я использую больше при разработке на Окамле. Не особо задумываясь ответил, что фифти-фифти. Потом сделал простой grep на свои исходники, и выяснил, что на 80% всё-таки модули и функторы. Причём, объекты и классы по большей части в очень старых исходниках. Сейчас 100% функторы.</p>
<p><span id="more-203"></span>Сейчас развлекаюсь написанием универсального интерфейса к разным хранилищам (в первую очередь, это FS, memcached, memcachedb) с записями вида key+value. В качестве основы, создал универсальный интерфейс:</p>

<div class="wp_syntax"><div class="code"><pre class="ocaml" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">module</span> <span style="color: #06c; font-weight: bold;">type</span> STORAGE <span style="color: #a52a2a;">=</span>
        <span style="color: #06c; font-weight: bold;">sig</span>
                <span style="color: #06c; font-weight: bold;">type</span> t
                <span style="color: #06c; font-weight: bold;">type</span> storage_descr_t
&nbsp;
                <span style="color: #06c; font-weight: bold;">val</span> init<span style="color: #a52a2a;">:</span> storage_descr_t <span style="color: #a52a2a;">-&gt;</span> t init_result
&nbsp;
                <span style="color: #06c; font-weight: bold;">val</span> get<span style="color: #a52a2a;">:</span> t <span style="color: #a52a2a;">-&gt;</span> Key<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span> <span style="color: #a52a2a;">-&gt;</span> get_result Lwt<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span>
                <span style="color: #06c; font-weight: bold;">val</span> get_list<span style="color: #a52a2a;">:</span> t <span style="color: #a52a2a;">-&gt;</span> Key<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span> list <span style="color: #a52a2a;">-&gt;</span> get_result Lwt<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span> list
&nbsp;
                <span style="color: #06c; font-weight: bold;">val</span> delete<span style="color: #a52a2a;">:</span> t <span style="color: #a52a2a;">-&gt;</span> Key<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span> <span style="color: #a52a2a;">-&gt;</span> delete_result Lwt<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span>
&nbsp;
                <span style="color: #06c; font-weight: bold;">val</span> set<span style="color: #a52a2a;">:</span> t <span style="color: #a52a2a;">-&gt;</span> Key<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span> <span style="color: #a52a2a;">-&gt;</span> ?value_size<span style="color: #a52a2a;">:</span>value_size <span style="color: #a52a2a;">-&gt;</span> value <span style="color: #a52a2a;">-&gt;</span> set_result Lwt<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span>
                <span style="color: #06c; font-weight: bold;">val</span> add<span style="color: #a52a2a;">:</span> t <span style="color: #a52a2a;">-&gt;</span> Key<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span> <span style="color: #a52a2a;">-&gt;</span> ?value_size<span style="color: #a52a2a;">:</span>value_size <span style="color: #a52a2a;">-&gt;</span> value <span style="color: #a52a2a;">-&gt;</span> add_result Lwt<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span>
                <span style="color: #06c; font-weight: bold;">val</span> replace<span style="color: #a52a2a;">:</span> t <span style="color: #a52a2a;">-&gt;</span> Key<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span> <span style="color: #a52a2a;">-&gt;</span> ?value_size<span style="color: #a52a2a;">:</span>value_size <span style="color: #a52a2a;">-&gt;</span> value <span style="color: #a52a2a;">-&gt;</span> replace_result Lwt<span style="color: #a52a2a;">.</span><span style="color: #060;">t</span>
        <span style="color: #06c; font-weight: bold;">end</span></pre></div></div>

<p>Написал модуль FileSystem, реализующий такой интерфейс. Поскольку файлы могут быть (условно) бесконечного размера, это стало самой простой реализацией интерфейса. Но не всё в жизни так легко. Например, memcached имеет максимальный размер пары key+value где-то в районе 64KB. А хочется в нём хранить побольше. Да и файловые системы бывают дурные. Напрмер, не позволяют создавать файлы больше 512MB. Поэтому на основе FileSystem (ключевое слово import) был написан маленький модуль FileSystemSized, который помимо value пишет в файлик размер value. Штука, на первый взгляд, бесполезная. Но идём дальше. Создаём функтор Splitted, который принимает модуль с интерфейсом STORAGE и делает модули с тем же уже знакомым нам интерфейсом STORAGE. Этот функтор хитрый: он знает, какого максимум размера value может хранить переданный ему модуль. Если в одну запись не влазит — он бьёт value на кусочки, для каждого кусочка генерит свой уникальный ключ, и таким образом пишет. В первом кусочке он сохраняет реальный размер всего value. Вот зачем нам нужен был модуль FileSystemSized. На основе этого функтора получается чудесный модуль FileSystemSplitted. По образу и подобию можно сделать MemcachedSplitted. Или даже FileSystemSplitted_and_again_Splitted, только я не придумал зачем :)</p>
<p>Мыслим вперёд. Ключ у нас — строчка строгой длины, с равной вероятностью имеющая в первом/втором/третьем/&#8230; байте любое из значений 0..255. На основе первого байта ключа, мы можем раскидать пары key+value на 256 физических хранилищ (ну, или меньше, как захочется). Назовём такой функтор Distributed, и он тоже будет создавать модули с интерфейсом STORAGE. Получается изумительная картинка:</p>

<div class="wp_syntax"><div class="code"><pre class="ocaml" style="font-family:monospace;"><span style="color: #5d478b; font-style: italic;">(* Создаём уже знакомый нам модуль для хранения больших значений
   в маленьких файлах.
*)</span>
<span style="color: #06c; font-weight: bold;">module</span> FileSystemSplitted <span style="color: #a52a2a;">=</span> Splitted<span style="color: #6c6;">&#40;</span>FileSystemSized<span style="color: #6c6;">&#41;</span>
&nbsp;
<span style="color: #5d478b; font-style: italic;">(* Каждое значение хранится в одном файлике, но файлики раскидываются
   по разным директориям.
*)</span>
<span style="color: #06c; font-weight: bold;">module</span> FileSystemDistributed <span style="color: #a52a2a;">=</span> Distributed<span style="color: #6c6;">&#40;</span>FileSystemSized<span style="color: #6c6;">&#41;</span>
&nbsp;
<span style="color: #5d478b; font-style: italic;">(* Каждое значение пилится на части, части раскидываются по разным директориям.
   С remote mount, получаем хранилище бесконечного размера для почти
   бесконечного количества значений.
*)</span>
<span style="color: #06c; font-weight: bold;">module</span> FileSystemDistributedSplitted <span style="color: #a52a2a;">=</span> Splitted<span style="color: #6c6;">&#40;</span>FileSystemDistributed<span style="color: #6c6;">&#41;</span>
&nbsp;
<span style="color: #5d478b; font-style: italic;">(* Каждое значение хранится в одной директории, но там оно пилится на части.
   Директорий для хранения может быть несколько. Хранилище получается тоже
   бесконечным, но наполняется не так равномерно.
 *)</span>
<span style="color: #06c; font-weight: bold;">module</span> FileSystemSplittedDistributed <span style="color: #a52a2a;">=</span> Distributed<span style="color: #6c6;">&#40;</span>FileSystemSplitted<span style="color: #6c6;">&#41;</span></pre></div></div>

<p>Как видите, с помощью фактически одного интерфейса и двух функторов, получаем невероятное, лютое количество вариантов хранилища. Даже круче, чем в GlusterFS или GNU Hurd. А ведь мысль можно продолжить ещё дальше, дописав функторы Raid0 (писать значение в несколько хранилищ), Clustered (создаётся на основе списка хранилищ, умеющих только читать и списка хранилищ, умеющих изменять), Flock (за счёт некоторого performace degradation, делать exclusive lock на записи)&#8230; чем я и занимаюсь :) Замечу, что всё это в функционально чисто, без side-effects (они есть только на уровне хранилища) и безумно типобезопасно.</p>
]]></content:encoded>
			<wfw:commentRss>http://john.5070.info/2009/10/%d1%84%d1%83%d0%bd%d0%ba%d1%86%d0%b8%d0%be%d0%bd%d0%b0%d0%bb%d1%8b-%d0%bf%d1%80%d0%be%d1%82%d0%b8%d0%b2-%d0%ba%d0%bb%d0%b0%d1%81%d1%81%d0%be%d0%b2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JavaScript: безопасный код</title>
		<link>http://john.5070.info/2009/10/javascript-%d0%b1%d0%b5%d0%b7%d0%be%d0%bf%d0%b0%d1%81%d0%bd%d1%8b%d0%b9-%d0%ba%d0%be%d0%b4/</link>
		<comments>http://john.5070.info/2009/10/javascript-%d0%b1%d0%b5%d0%b7%d0%be%d0%bf%d0%b0%d1%81%d0%bd%d1%8b%d0%b9-%d0%ba%d0%be%d0%b4/#comments</comments>
		<pubDate>Wed, 07 Oct 2009 03:00:56 +0000</pubDate>
		<dc:creator>John Lepikhin</dc:creator>
				<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[O'Browser]]></category>
		<category><![CDATA[ocamljs]]></category>

		<guid isPermaLink="false">http://john.5070.info/?p=193</guid>
		<description><![CDATA[Давно собирался написать нечто подобное, да всё руки не доходили. Толчком послужил краткий пост на аналогичную тему у моего знакомого.
Как известно, JavaScript — язык c динамической (для классов с утиной) типизацией, с очень плохо развитой системой типов. Стандартный интерпретатор даже в браузерах Mozilla с расширениями разработчика отлавливает минимум ошибок. Практически все эти ошибки — синтаксические. [...]]]></description>
			<content:encoded><![CDATA[<p>Давно собирался написать нечто подобное, да всё руки не доходили. Толчком послужил краткий пост на аналогичную тему у моего знакомого.</p>
<p>Как известно, JavaScript — язык c динамической (для классов с утиной) типизацией, с очень плохо развитой системой типов. Стандартный интерпретатор даже в браузерах Mozilla с расширениями разработчика отлавливает минимум ошибок. Практически все эти ошибки — синтаксические. В результате, писать надёжный код на JavaScript предельно сложно. Положение усугубляет фактическая невозможность запуска программы без использования браузера, т.е. нет никакой песочницы для тестов.</p>
<p>В этой статье я попытаюсь описать некоторые технологии, которые помогут знакомому с Ocaml человеку существенно сократить время написания безопасного, стабильного и более-менее компактного JS-кода. Впрочем, описываемые техники есть и для некоторых других языков с развитой системой типов (например, Haskell).</p>
<p><span id="more-193"></span></p>
<h1>Ocamljs: компилятор Ocaml ⇒ JavaScript</h1>
<p>Скачать: <a href="http://code.google.com/p/ocamljs/">http://code.google.com/p/ocamljs/</a></p>
<p>Всё просто: вы пишете client-side код вашего сайта на Ocaml, а с помощью этого компилятора получаете готовый для использования в браузере JavaScript. Для обеспечения работы, непосредственно к вашему скрипту дописывается около 40KB дополнительного кода. Например. Ни к чему не обязывающий код:</p>

<div class="wp_syntax"><div class="code"><pre class="ocaml" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">type</span> tree <span style="color: #a52a2a;">=</span>
	<span style="color: #a52a2a;">|</span> Leaf <span style="color: #06c; font-weight: bold;">of</span> int
	<span style="color: #a52a2a;">|</span> Node <span style="color: #06c; font-weight: bold;">of</span> tree list
&nbsp;
<span style="color: #06c; font-weight: bold;">let</span> l <span style="color: #a52a2a;">:</span> tree list <span style="color: #a52a2a;">=</span> <span style="color: #6c6;">&#91;</span><span style="color: #6c6;">&#93;</span>
&nbsp;
<span style="color: #06c; font-weight: bold;">let</span> _ <span style="color: #a52a2a;">=</span>
	<span style="color: #06c; font-weight: bold;">match</span> l <span style="color: #06c; font-weight: bold;">with</span>
	<span style="color: #a52a2a;">|</span> <span style="color: #6c6;">&#91;</span><span style="color: #6c6;">&#93;</span> <span style="color: #a52a2a;">-&gt;</span> Dom<span style="color: #a52a2a;">.</span><span style="color: #060;">window</span><span style="color: #a52a2a;">#</span>alert <span style="color: #3cb371;">&quot;empty list&quot;</span>
	<span style="color: #a52a2a;">|</span> a <span style="color: #a52a2a;">::</span> <span style="color: #6c6;">&#91;</span><span style="color: #6c6;">&#93;</span> <span style="color: #a52a2a;">-&gt;</span> <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#41;</span>
	<span style="color: #a52a2a;">|</span> a <span style="color: #a52a2a;">::</span> b <span style="color: #a52a2a;">::</span> <span style="color: #6c6;">&#91;</span><span style="color: #6c6;">&#93;</span> <span style="color: #a52a2a;">-&gt;</span> <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#41;</span>
	<span style="color: #a52a2a;">|</span> _ <span style="color: #a52a2a;">-&gt;</span> Dom<span style="color: #a52a2a;">.</span><span style="color: #060;">window</span><span style="color: #a52a2a;">#</span>alert <span style="color: #3cb371;">&quot;unexpected list&quot;</span></pre></div></div>

<p>Компилируем:</p>
<pre>ocamljs -o test.js -I /usr/local/lib/ocaml/3.10.2/dom/ dom.cmjsa test.ml</pre>
<p>Получаем вот такой код:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// .....</span>
<span style="color: #003366; font-weight: bold;">var</span> oc$Dom$ <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #003366; font-weight: bold;">var</span> window$<span style="color: #CC0000;">717</span> <span style="color: #339933;">=</span> window<span style="color: #339933;">;</span>
                            <span style="color: #003366; font-weight: bold;">var</span> document$<span style="color: #CC0000;">718</span> <span style="color: #339933;">=</span> document<span style="color: #339933;">;</span>
                            <span style="color: #000066; font-weight: bold;">return</span> $<span style="color: #009900;">&#40;</span>window$<span style="color: #CC0000;">717</span><span style="color: #339933;">,</span> document$<span style="color: #CC0000;">718</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> oc$<span style="color: #CC0000;">1</span>$ <span style="color: #339933;">=</span>
  <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #003366; font-weight: bold;">var</span> l$<span style="color: #CC0000;">63</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>l$<span style="color: #CC0000;">63</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #003366; font-weight: bold;">var</span> match$<span style="color: #CC0000;">71</span> <span style="color: #339933;">=</span> l$<span style="color: #CC0000;">63</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>match$<span style="color: #CC0000;">71</span><span style="color: #009900;">&#41;</span>
      <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>match$<span style="color: #CC0000;">71</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #003366; font-weight: bold;">var</span> v$<span style="color: #CC0000;">74</span> <span style="color: #339933;">=</span> oc$Dom$<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
                                      <span style="color: #000066; font-weight: bold;">return</span> _m<span style="color: #009900;">&#40;</span>v$74.<span style="color: #000066;">alert</span><span style="color: #339933;">,</span> v$<span style="color: #CC0000;">74</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;unexpected list&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #339933;">;</span>
      <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #003366; font-weight: bold;">var</span> v$<span style="color: #CC0000;">73</span> <span style="color: #339933;">=</span> oc$Dom$<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
                        <span style="color: #000066; font-weight: bold;">return</span> _m<span style="color: #009900;">&#40;</span>v$73.<span style="color: #000066;">alert</span><span style="color: #339933;">,</span> v$<span style="color: #CC0000;">73</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;empty list&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066; font-weight: bold;">return</span> $<span style="color: #009900;">&#40;</span>l$<span style="color: #CC0000;">63</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> oc$Std_exit$ <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>_<span style="color: #009900;">&#40;</span>oc$Pervasives$<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">80</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> $<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">return</span> caml_named_value<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h2>JavaScript compressor</h2>
<p>Как я уже сказал, код получается достаточно объёмным. Частично эту проблему решает gzip (при условии, что и сервер, и браузер имеют его поддержку). Однако, код можно существенно сократить за счёт оптимизации по размеру. Для этого есть ряд готовых online-утилит. Используемые техники:</p>
<ul>
<li>Удаление комментариев</li>
<li>Удаление не несущих синтаксической нагрузки пробелов и переносов строк</li>
<li>Назначение локальным переменным функций более коротких имён</li>
<li>Вынесение длинных повторяющихся констант в переменную с коротким именем</li>
</ul>
<p>Наилучшие результаты показывает Packer (<a href="http://dean.edwards.name/packer/">http://dean.edwards.name/packer/</a>), однако ocamljs компилирует не полностью корректный код — иногда забывает точки с запятой — поэтому Packer генерирует не работающий код. С учётом некорректности оригинального кода, наилучший результат показал Dojo ShrinkSafe (<a href="http://www.dojotoolkit.org/docs/shrinksafe">http://www.dojotoolkit.org/docs/shrinksafe</a>). Рекомендую прогнать код через валидатор (<a href="http://jslint.com/">http://jslint.com/</a>), это в любом случае неплохая идея. Пример кода, получающегося с помощью Dojo ShrinkSafe:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #006600; font-style: italic;">// .....</span>
<span style="color: #003366; font-weight: bold;">var</span> _213<span style="color: #339933;">=</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #003366; font-weight: bold;">var</span> l$<span style="color: #CC0000;">63</span><span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>l$<span style="color: #CC0000;">63</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #003366; font-weight: bold;">var</span> _215<span style="color: #339933;">=</span>l$<span style="color: #CC0000;">63</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>_215<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span>_215<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #003366; font-weight: bold;">var</span> v$<span style="color: #CC0000;">74</span><span style="color: #339933;">=</span>_210<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">return</span> _m<span style="color: #009900;">&#40;</span>v$74.<span style="color: #000066;">alert</span><span style="color: #339933;">,</span>v$<span style="color: #CC0000;">74</span><span style="color: #339933;">,</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;unexpected list&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #000066; font-weight: bold;">else</span><span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #000066; font-weight: bold;">else</span><span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span><span style="color: #000066; font-weight: bold;">else</span><span style="color: #009900;">&#123;</span>
<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
<span style="color: #003366; font-weight: bold;">var</span> v$<span style="color: #CC0000;">73</span><span style="color: #339933;">=</span>_210<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">return</span> _m<span style="color: #009900;">&#40;</span>v$73.<span style="color: #000066;">alert</span><span style="color: #339933;">,</span>v$<span style="color: #CC0000;">73</span><span style="color: #339933;">,</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">&quot;empty list&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000066; font-weight: bold;">return</span> $<span style="color: #009900;">&#40;</span>l$<span style="color: #CC0000;">63</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> _218<span style="color: #339933;">=</span><span style="color: #009900;">&#40;</span>_<span style="color: #009900;">&#40;</span>_106<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">80</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>$<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">return</span> _9d<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Код получается практически не читаемым, зато размер сокращается в 2-4 раза.</p>
<p>Быстро сравнить различные компрессоры можно на сайте: <a href="http://compressorrater.thruhere.net/">http://compressorrater.thruhere.net/</a></p>
<h1>O&#8217;Browser: виртуальная машина на JavaScript</h1>
<p>Скачать: <a href="http://ocsigen.org/obrowser/">http://ocsigen.org/obrowser/</a></p>
<p>Ваш код будет скомпилирован в байт-код, закодированный в UUE. Для вызова кода, достаточно вызвать его в виртуальной машине:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">&lt;script src=&quot;vm.js&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
<span style="color: #339933;">&lt;</span>script type<span style="color: #339933;">=</span><span style="color: #3366CC;">&quot;text/javascript&quot;</span><span style="color: #339933;">&gt;</span>
  <span style="color: #009966; font-style: italic;">/* &lt;![CDATA[ */</span>
    window.<span style="color: #000066;">onload</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      exec_caml <span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;tutorial.exe.uue&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009966; font-style: italic;">/* ]]&gt; */</span>
<span style="color: #339933;">&lt;/</span>script<span style="color: #339933;">&gt;</span></pre></div></div>

<p>Байт-код получается достаточно объёмным, да и сжатию поддаётся только за счёт слоя gzip. Впрочем, код самой виртуальной машины вполне поддаётся обработке JavaScript компрессоров. Валидность кода получается даже выше, чем у ocamljs. Декомпиляция байт-кода в нормальный JavaScript становится нерешаемой проблемой :)</p>
]]></content:encoded>
			<wfw:commentRss>http://john.5070.info/2009/10/javascript-%d0%b1%d0%b5%d0%b7%d0%be%d0%bf%d0%b0%d1%81%d0%bd%d1%8b%d0%b9-%d0%ba%d0%be%d0%b4/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Решение для решателя Sudoku</title>
		<link>http://john.5070.info/2009/06/%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%bb%d1%8f-%d1%80%d0%b5%d1%88%d0%b0%d1%82%d0%b5%d0%bb%d1%8f-sudoku/</link>
		<comments>http://john.5070.info/2009/06/%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%bb%d1%8f-%d1%80%d0%b5%d1%88%d0%b0%d1%82%d0%b5%d0%bb%d1%8f-sudoku/#comments</comments>
		<pubDate>Wed, 10 Jun 2009 14:54:30 +0000</pubDate>
		<dc:creator>John Lepikhin</dc:creator>
				<category><![CDATA[Blogroll]]></category>
		<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Sudoku]]></category>

		<guid isPermaLink="false">http://john.5070.info/?p=126</guid>
		<description><![CDATA[Хотел вечерком размять мозг — набросать какой-нибудь особенно красивый решатель Sudoku на Ocaml. Но возникла мысль изучить вражеские аналоги. Итак, решатель Sudoku размером 800 с небольшим байт:

include Set.Make&#40;struct type t = &#40;int * int&#41; * int let compare = compare end&#41;
&#160;
let &#40;@&#41; g f x = g &#40;f x&#41; and id x = x and [...]]]></description>
			<content:encoded><![CDATA[<p>Хотел вечерком размять мозг — набросать какой-нибудь особенно красивый решатель Sudoku на Ocaml. Но возникла мысль изучить вражеские аналоги. Итак, решатель Sudoku размером 800 с небольшим байт:</p>

<div class="wp_syntax"><div class="code"><pre class="ocaml" style="font-family:monospace;"><span style="color: #06c; font-weight: bold;">include</span> <span style="color: #06c; font-weight: bold;">Set</span><span style="color: #a52a2a;">.</span><span style="color: #060;">Make</span><span style="color: #6c6;">&#40;</span><span style="color: #06c; font-weight: bold;">struct</span> <span style="color: #06c; font-weight: bold;">type</span> t <span style="color: #a52a2a;">=</span> <span style="color: #6c6;">&#40;</span>int <span style="color: #a52a2a;">*</span> int<span style="color: #6c6;">&#41;</span> <span style="color: #a52a2a;">*</span> int <span style="color: #06c; font-weight: bold;">let</span> <span style="color: #06c; font-weight: bold;">compare</span> <span style="color: #a52a2a;">=</span> <span style="color: #06c; font-weight: bold;">compare</span> <span style="color: #06c; font-weight: bold;">end</span><span style="color: #6c6;">&#41;</span>
&nbsp;
<span style="color: #06c; font-weight: bold;">let</span> <span style="color: #6c6;">&#40;</span>@<span style="color: #6c6;">&#41;</span> g f x <span style="color: #a52a2a;">=</span> g <span style="color: #6c6;">&#40;</span>f x<span style="color: #6c6;">&#41;</span> <span style="color: #06c; font-weight: bold;">and</span> id x <span style="color: #a52a2a;">=</span> x <span style="color: #06c; font-weight: bold;">and</span> sw f x y <span style="color: #a52a2a;">=</span> f y x <span style="color: #06c; font-weight: bold;">and</span> zip x y <span style="color: #a52a2a;">=</span> <span style="color: #6c6;">&#40;</span>x, y<span style="color: #6c6;">&#41;</span>
&nbsp;
<span style="color: #06c; font-weight: bold;">let</span> fold9 f <span style="color: #a52a2a;">=</span> <span style="color: #06c; font-weight: bold;">let</span> <span style="color: #06c; font-weight: bold;">rec</span> loop i <span style="color: #a52a2a;">=</span> <span style="color: #06c; font-weight: bold;">if</span> i<span style="color: #a52a2a;">&gt;</span><span style="color: #c6c;">8</span> <span style="color: #06c; font-weight: bold;">then</span> id <span style="color: #06c; font-weight: bold;">else</span> loop <span style="color: #6c6;">&#40;</span>i<span style="color: #a52a2a;">+</span><span style="color: #c6c;">1</span><span style="color: #6c6;">&#41;</span> @ f i <span style="color: #06c; font-weight: bold;">in</span> loop <span style="color: #c6c;">0</span>
&nbsp;
<span style="color: #06c; font-weight: bold;">let</span> fold81 f <span style="color: #a52a2a;">=</span> fold9 <span style="color: #6c6;">&#40;</span>fold9 @ <span style="color: #6c6;">&#40;</span>@<span style="color: #6c6;">&#41;</span> f @ zip<span style="color: #6c6;">&#41;</span>
&nbsp;
<span style="color: #06c; font-weight: bold;">let</span> mark <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#40;</span>i,j<span style="color: #6c6;">&#41;</span>,x <span style="color: #06c; font-weight: bold;">as</span> e<span style="color: #6c6;">&#41;</span> <span style="color: #a52a2a;">:</span> t <span style="color: #a52a2a;">-&gt;</span> t <span style="color: #a52a2a;">=</span>
  add e @ fold9 <span style="color: #6c6;">&#40;</span><span style="color: #06c; font-weight: bold;">fun</span> k <span style="color: #a52a2a;">-&gt;</span> remove <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#40;</span>i<span style="color: #a52a2a;">/</span><span style="color: #c6c;">3</span><span style="color: #a52a2a;">*</span><span style="color: #c6c;">3</span> <span style="color: #a52a2a;">+</span> k<span style="color: #a52a2a;">/</span><span style="color: #c6c;">3</span>, j<span style="color: #a52a2a;">/</span><span style="color: #c6c;">3</span><span style="color: #a52a2a;">*</span><span style="color: #c6c;">3</span> <span style="color: #a52a2a;">+</span> k <span style="color: #06c; font-weight: bold;">mod</span> <span style="color: #c6c;">3</span><span style="color: #6c6;">&#41;</span>, x<span style="color: #6c6;">&#41;</span> @
    remove <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#40;</span>i,j<span style="color: #6c6;">&#41;</span>,k<span style="color: #6c6;">&#41;</span> @ remove <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#40;</span>i,k<span style="color: #6c6;">&#41;</span>,x<span style="color: #6c6;">&#41;</span> @ remove <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#40;</span>k,j<span style="color: #6c6;">&#41;</span>,x<span style="color: #6c6;">&#41;</span><span style="color: #6c6;">&#41;</span>
&nbsp;
<span style="color: #06c; font-weight: bold;">let</span> search <span style="color: #a52a2a;">=</span>
  <span style="color: #06c; font-weight: bold;">let</span> g p f s <span style="color: #a52a2a;">=</span> fold <span style="color: #6c6;">&#40;</span>f @ sw mark s<span style="color: #6c6;">&#41;</span> <span style="color: #6c6;">&#40;</span>filter <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#40;</span><span style="color: #a52a2a;">=</span><span style="color: #6c6;">&#41;</span> p @ <span style="color: #06c; font-weight: bold;">fst</span><span style="color: #6c6;">&#41;</span> s<span style="color: #6c6;">&#41;</span> <span style="color: #06c; font-weight: bold;">in</span>
  fold81 g
&nbsp;
<span style="color: #06c; font-weight: bold;">let</span> read <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#41;</span> <span style="color: #a52a2a;">=</span>
  <span style="color: #06c; font-weight: bold;">let</span> f p <span style="color: #a52a2a;">=</span> <span style="color: #06c; font-weight: bold;">Scanf</span><span style="color: #a52a2a;">.</span><span style="color: #060;">scanf</span> <span style="color: #3cb371;">&quot;%d &quot;</span> <span style="color: #6c6;">&#40;</span><span style="color: #06c; font-weight: bold;">fun</span> x <span style="color: #a52a2a;">-&gt;</span> <span style="color: #06c; font-weight: bold;">if</span> x<span style="color: #a52a2a;">&gt;</span><span style="color: #c6c;">0</span> <span style="color: #06c; font-weight: bold;">then</span> mark <span style="color: #6c6;">&#40;</span>p,x<span style="color: #a52a2a;">-</span><span style="color: #c6c;">1</span><span style="color: #6c6;">&#41;</span> <span style="color: #06c; font-weight: bold;">else</span> id<span style="color: #6c6;">&#41;</span> <span style="color: #06c; font-weight: bold;">in</span>
  fold81 f <span style="color: #6c6;">&#40;</span>fold81 <span style="color: #6c6;">&#40;</span>fold9 @ <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#40;</span>@<span style="color: #6c6;">&#41;</span> add @ zip<span style="color: #6c6;">&#41;</span><span style="color: #6c6;">&#41;</span> empty<span style="color: #6c6;">&#41;</span>
&nbsp;
<span style="color: #06c; font-weight: bold;">let</span> print s <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#41;</span> <span style="color: #a52a2a;">=</span>
  <span style="color: #06c; font-weight: bold;">let</span> pr <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#40;</span>i,j<span style="color: #6c6;">&#41;</span>,x<span style="color: #6c6;">&#41;</span> <span style="color: #a52a2a;">=</span> <span style="color: #06c; font-weight: bold;">Printf</span><span style="color: #a52a2a;">.</span><span style="color: #060;">printf</span> <span style="color: #3cb371;">&quot;%d%c&quot;</span> <span style="color: #6c6;">&#40;</span>x<span style="color: #a52a2a;">+</span><span style="color: #c6c;">1</span><span style="color: #6c6;">&#41;</span> <span style="color: #6c6;">&#40;</span><span style="color: #06c; font-weight: bold;">if</span> j<span style="color: #a52a2a;">=</span><span style="color: #c6c;">8</span> <span style="color: #06c; font-weight: bold;">then</span> <span style="color: #a52a2a;">'</span>\n<span style="color: #a52a2a;">'</span> <span style="color: #06c; font-weight: bold;">else</span> <span style="color: #a52a2a;">'</span> <span style="color: #a52a2a;">'</span><span style="color: #6c6;">&#41;</span> <span style="color: #06c; font-weight: bold;">in</span>
  iter pr s<span style="color: #a52a2a;">;</span> <span style="color: #06c; font-weight: bold;">print_newline</span> <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#41;</span><span style="color: #a52a2a;">;;</span>
&nbsp;
search print <span style="color: #6c6;">&#40;</span>read <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#41;</span><span style="color: #6c6;">&#41;</span> <span style="color: #6c6;">&#40;</span><span style="color: #6c6;">&#41;</span></pre></div></div>

<p>Вы посмотрите эту красоту, это же [почти] совершенство! А если учесть, что 272 байта — это чтение задачи с STDIN и вывод результата, размер кода сокращается до менее чем 600 байт.</p>
<p><span id="more-126"></span>Впрочем, Perl традиционно отличился своей минималистической магической мешаниной:</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">use</span> integer<span style="color: #339933;">;</span><span style="color: #0000ff;">@A</span><span style="color: #339933;">=</span><span style="color: #000066;">split</span><span style="color: #339933;">//,&lt;&gt;;</span>sub R<span style="color: #009900;">&#123;</span><span style="color: #b1b100;">for</span><span style="color: #0000ff;">$i</span><span style="color: #009900;">&#40;</span>0<span style="color: #339933;">..</span>80<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><span style="color: #b1b100;">next</span> <span style="color: #b1b100;">if</span><span style="color: #0000ff;">$A</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>my<span style="color: #0000ff;">%t</span><span style="color: #339933;">=</span><span style="color: #000066;">map</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">$_</span><span style="color: #339933;">/</span><span style="color: #cc66cc;">9</span>
<span style="color: #339933;">==</span><span style="color: #0000ff;">$i</span><span style="color: #339933;">/</span><span style="color: #cc66cc;">9</span><span style="color: #339933;">||</span><span style="color: #0000ff;">$_</span><span style="color: #339933;">%</span>9<span style="color: #339933;">==</span><span style="color: #0000ff;">$i</span><span style="color: #339933;">%</span>9<span style="color: #339933;">||</span><span style="color: #0000ff;">$_</span><span style="color: #339933;">/</span><span style="color: #cc66cc;">27</span><span style="color: #339933;">==</span><span style="color: #0000ff;">$i</span><span style="color: #339933;">/</span><span style="color: #cc66cc;">27</span><span style="color: #339933;">&amp;&amp;</span><span style="color: #0000ff;">$_</span><span style="color: #339933;">%</span>9<span style="color: #339933;">/</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">==</span><span style="color: #0000ff;">$i</span><span style="color: #339933;">%</span>9<span style="color: #339933;">/</span><span style="color: #cc66cc;">3</span><span style="color: #339933;">?</span><span style="color: #0000ff;">$A</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">:</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">=&gt;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#125;</span>0<span style="color: #339933;">..</span>80<span style="color: #339933;">;</span>R<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$A</span><span style="color: #009900;">&#91;</span>
<span style="color: #0000ff;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#41;</span><span style="color: #b1b100;">for</span> <span style="color: #000066;">grep</span><span style="color: #009900;">&#123;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$t</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#125;</span>1<span style="color: #339933;">..</span>9<span style="color: #339933;">;</span>return<span style="color: #0000ff;">$A</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#125;</span><span style="color: #000066;">die</span><span style="color: #0000ff;">@A</span><span style="color: #009900;">&#125;</span>R</pre></div></div>

<p>Ну и специалисты по PHP тоже выразились: <a href="http://www.weberdev.com/get_example-4243.html">http://www.weberdev.com/get_example-4243.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://john.5070.info/2009/06/%d1%80%d0%b5%d1%88%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b4%d0%bb%d1%8f-%d1%80%d0%b5%d1%88%d0%b0%d1%82%d0%b5%d0%bb%d1%8f-sudoku/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Микроязык OpQL</title>
		<link>http://john.5070.info/2009/06/%d0%bc%d0%b8%d0%ba%d1%80%d0%be%d1%8f%d0%b7%d1%8b%d0%ba-opql/</link>
		<comments>http://john.5070.info/2009/06/%d0%bc%d0%b8%d0%ba%d1%80%d0%be%d1%8f%d0%b7%d1%8b%d0%ba-opql/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 13:36:58 +0000</pubDate>
		<dc:creator>John Lepikhin</dc:creator>
				<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[OpQL]]></category>
		<category><![CDATA[oProxy]]></category>
		<category><![CDATA[хостинг]]></category>

		<guid isPermaLink="false">http://john.5070.info/?p=115</guid>
		<description><![CDATA[Сделал микроязык запросов для oProxy. Служит, собственно, для управления ею. Что умеет:

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

Второй пункт интереснее. Немного предыстории. Часто бывает, что у клиентов на shared-хостинге случился перерасход ресурсов и они хотят знать, откуда эта нагрузка растёт. Резонное желание. Но беда в том, что ни я, &#8220;заведующий всем&#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>Сделал микроязык запросов для oProxy. Служит, собственно, для управления ею. Что умеет:</p>
<ol>
<li>Показать всякую текущую статистику (устаревшее show_workers, show_nodes и т.д.)</li>
<li>Управлять списками наблюдения.</li>
</ol>
<p><span id="more-115"></span>Второй пункт интереснее. Немного предыстории. Часто бывает, что у клиентов на shared-хостинге случился перерасход ресурсов и они хотят знать, откуда эта нагрузка растёт. Резонное желание. Но беда в том, что ни я, &#8220;заведующий всем&#8221; © на хостинге, ни тем более техподдержка не может точно ответить на такой вопрос. Просто неоткуда брать данные. Чтобы разрешить эту проблему и были созданы списки наблюдения. Допустим, по MySQL-пользователю evlampiy случилось превышение нагрузки на MySQL. Пишем:</p>
<blockquote><p>start save time, sent, query from mysql where user = &#8220;evlampiy&#8221; into file &#8220;/home/evlampiy/mysql_load.txt&#8221;</p></blockquote>
<p>Всё, с этого момента прокся начнёт сохранять в указанный файлик все запросы к MySQL, пришедшие от пользователя evlampiy. Будет записано время выполнения запроса, количество посланных клиенту байт и сам запрос. Как только выяснили происхождение нагрузок, пишем:</p>
<blockquote><p>stop save time, sent, query from mysql where user = &#8220;evlampiy&#8221; into file &#8220;/home/evlampiy/mysql_load.txt&#8221;</p></blockquote>
<p>Запись прекратилась. Можно и понавороченней:</p>
<blockquote><p>start save current_time, time/60, sent/1024/1024, host, uri from http where host = &#8220;john.5070.info&#8221; and ((uri = &#8220;/&#8221; and time &lt; 0.5) or (uri = &#8220;/news/&#8221; and time &gt; 0.01)) into file &#8220;/tmp/crazy_requests.txt&#8221;; stop save host from http into file &#8220;/tmp/all_http.txt&#8221;</p></blockquote>
<p>Разумеется, можно посмотреть текущий список наблюдения:</p>
<blockquote><p>show queries</p></blockquote>
<p>На моей машине оверхед на один запрос со списком наблюдения длиной 5 получился 70 микросекунд, что примерно соответствует 2.3% на одно наблюдение при отдаче напрямую и 1.7% при проксировании.</p>
]]></content:encoded>
			<wfw:commentRss>http://john.5070.info/2009/06/%d0%bc%d0%b8%d0%ba%d1%80%d0%be%d1%8f%d0%b7%d1%8b%d0%ba-opql/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ocaml-epoll</title>
		<link>http://john.5070.info/2009/05/ocaml-epoll/</link>
		<comments>http://john.5070.info/2009/05/ocaml-epoll/#comments</comments>
		<pubDate>Fri, 29 May 2009 06:49:27 +0000</pubDate>
		<dc:creator>John Lepikhin</dc:creator>
				<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[epoll]]></category>

		<guid isPermaLink="false">http://john.5070.info/?p=112</guid>
		<description><![CDATA[Написал биндинг для работы с epoll(7). Пока бета, но на ней уже ради эксперимента написал успешно работающий маленький веб-сервер :) Скачать можно со страницы Software. epoll является аналогом select() и poll(), но с увеличением количества обрабатываемых сокетов сложность остаётся O(1), что позволяет без особых задержек обрабатывать тысячи параллельных соединений.
]]></description>
			<content:encoded><![CDATA[<p>Написал биндинг для работы с epoll(7). Пока бета, но на ней уже ради эксперимента написал успешно работающий маленький веб-сервер :) Скачать можно со страницы <a title="Мой софт" href="http://john.5070.info/software/">Software</a>. epoll является аналогом select() и poll(), но с увеличением количества обрабатываемых сокетов сложность остаётся O(1), что позволяет без особых задержек обрабатывать тысячи параллельных соединений.</p>
]]></content:encoded>
			<wfw:commentRss>http://john.5070.info/2009/05/ocaml-epoll/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Nginx против oProxy: друг другу сливаем :)</title>
		<link>http://john.5070.info/2009/02/nginx-%d0%bf%d1%80%d0%be%d1%82%d0%b8%d0%b2-oproxy-%d0%b4%d1%80%d1%83%d0%b3-%d0%b4%d1%80%d1%83%d0%b3%d1%83-%d1%81%d0%bb%d0%b8%d0%b2%d0%b0%d0%b5%d0%bc/</link>
		<comments>http://john.5070.info/2009/02/nginx-%d0%bf%d1%80%d0%be%d1%82%d0%b8%d0%b2-oproxy-%d0%b4%d1%80%d1%83%d0%b3-%d0%b4%d1%80%d1%83%d0%b3%d1%83-%d1%81%d0%bb%d0%b8%d0%b2%d0%b0%d0%b5%d0%bc/#comments</comments>
		<pubDate>Sun, 01 Feb 2009 15:19:55 +0000</pubDate>
		<dc:creator>John Lepikhin</dc:creator>
				<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[oProxy]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[profiling]]></category>

		<guid isPermaLink="false">http://john.5070.info/?p=69</guid>
		<description><![CDATA[Потестировал производительность проксирования HTTP трафика. Результаты местами получились весьма неожиданными.
Повторю, тестировалось именно проксирование. Известно, что при прямой отдаче и Apache, и Nginx использует ядрёный вызов sendfile(), который отдаёт содержимое файлика в сокет без лишних копирований. Это неинтересно. А вот проксирование — это совсем другое дело. В ядре пока что ещё нет прямых путей для копирования [...]]]></description>
			<content:encoded><![CDATA[<p>Потестировал производительность проксирования HTTP трафика. Результаты местами получились весьма неожиданными.</p>
<p>Повторю, тестировалось именно проксирование. Известно, что при прямой отдаче и Apache, и Nginx использует ядрёный вызов sendfile(), который отдаёт содержимое файлика в сокет без лишних копирований. Это неинтересно. А вот проксирование — это совсем другое дело. В ядре пока что ещё нет прямых путей для копирования из сокета в сокет (есть полупрямой вариант splice() + pipe(), но как выяснилось он даже не на всех современных ядрах работает).</p>
<p>Итак…</p>
<p><span id="more-69"></span>На порту 8080 живёт Apache 2 ITK. У него в VirtualHost лежит bigfile размером ровно 20MB.</p>
<p>На порту 8081 живёт Nginx, который проксирует в Apache. Его конфиг:</p>
<p>worker_processes  16;</p>
<p>error_log  /var/log/nginx/error.log;<br />
pid        /var/run/nginx.pid;</p>
<p>events {<br />
worker_connections  1024;<br />
}</p>
<p>http {<br />
sendfile        on;<br />
tcp_nodelay        on;<br />
gzip  off;</p>
<p>server {<br />
listen 12.34.56.78:8081;<br />
server_name test1.com www.test1.com;<br />
location / {<br />
proxy_pass http://12.34.56.78:8080;<br />
proxy_redirect http://test1.com:8080/ /;<br />
proxy_set_header Host $host;<br />
}<br />
}<br />
}</p>
<p>Результаты siege для Nginx:</p>
<p>debian2:~# siege -t30s -b -c 10 http://test1.com:8081/bigfile &gt;/dev/null<br />
** SIEGE 2.66<br />
** Preparing 10 concurrent users for battle.<br />
The server is now under siege&#8230;</p>
<p>Lifting the server siege&#8230;      done.<br />
Transactions:                 372 hits<br />
Availability:              100.00 %<br />
Elapsed time:               29.66 secs<br />
Data transferred:         6773.34 MB<br />
Response time:                0.78 secs<br />
Transaction rate:           12.54 trans/sec<br />
Throughput:              228.37 MB/sec<br />
Concurrency:                9.82<br />
Successful transactions:         372<br />
Failed transactions:               0<br />
Longest transaction:            4.09<br />
Shortest transaction:            0.07</p>
<p>228MB в секунду. Конкурентность 9.82. Доступность 100%. Самый медленный ответ: через 4 секунды.</p>
<p>Результаты oProxy (тоже 16 рабочих, чтобы было абсолютно честно):</p>
<p>debian2:~# siege -t30s -b -c 10 http://test1.com/bigfile &gt;/dev/null<br />
** SIEGE 2.66<br />
** Preparing 10 concurrent users for battle.<br />
The server is now under siege&#8230;</p>
<p>Lifting the server siege&#8230;      done.<br />
Transactions:                 691 hits<br />
Availability:              100.00 %<br />
Elapsed time:               29.71 secs<br />
Data transferred:        13820.00 MB<br />
Response time:                0.38 secs<br />
Transaction rate:           23.26 trans/sec<br />
Throughput:              465.16 MB/sec<br />
Concurrency:                8.94<br />
Successful transactions:         691<br />
Failed transactions:               0<br />
Longest transaction:            9.18<br />
Shortest transaction:            0.05</p>
<p>465MB в секунду (лучше более, чем в 2 раза). Конкурентность 9.18. Доступность 100%. Самый медленный ответ: через 9 секунд (хуже более, чем в 2 раза). Почувствуйте разницу ©</p>
<p>Мерим на маленьком файле. smallfile имеет размер 5 байт. Эмулируем атаку яростных 10 пользователей. Прочая конфигурация такая же. Результаты в Nginx:</p>
<p>debian2:~# siege -t30s -b -c 10 http://test1.com:8081/smallfile &gt;/dev/null<br />
** SIEGE 2.66<br />
** Preparing 10 concurrent users for battle.<br />
The server is now under siege&#8230;</p>
<p>Lifting the server siege&#8230;      done.<br />
Transactions:               16952 hits<br />
Availability:              100.00 %<br />
Elapsed time:               30.47 secs<br />
Data transferred:            0.08 MB<br />
Response time:                0.02 secs<br />
Transaction rate:          556.35 trans/sec<br />
Throughput:                0.00 MB/sec<br />
Concurrency:                9.97<br />
Successful transactions:       16952<br />
Failed transactions:               0<br />
Longest transaction:            0.20<br />
Shortest transaction:            0.00</p>
<p>Результаты в oProxy:</p>
<p>debian2:~# siege -t30s -b -c 10 http://test1.com/smallfile &gt;/dev/null<br />
** SIEGE 2.66<br />
** Preparing 10 concurrent users for battle.<br />
The server is now under siege&#8230;</p>
<p>Lifting the server siege&#8230;      done.<br />
Transactions:                8718 hits<br />
Availability:              100.00 %<br />
Elapsed time:               29.57 secs<br />
Data transferred:            0.04 MB<br />
Response time:                0.03 secs<br />
Transaction rate:          294.83 trans/sec<br />
Throughput:                0.00 MB/sec<br />
Concurrency:                9.27<br />
Successful transactions:        8718<br />
Failed transactions:               0<br />
Longest transaction:            9.00<br />
Shortest transaction:            0.00</p>
<p>А вот тут сливаем, почти в 2 раза. Аналогичная картина при увеличении конкурентных запросов. Но прокся при этом начинает показывать ещё более худшие результаты в Longext transaction. Буду над этим работать.</p>
<p>Update: нашёл в чём причина. В <span style="text-decoration: line-through;">генах</span> архитектуре. Завтра найду время, и перееду с socket passing на shared accept() и, возможно, epoll. Правда, при этом не совсем понятно, что делать с шедулингом нагрузки по рабочим. Рычаг теряю. Судя по логам, accept() на каждое соединение в среднем 3 миллисекунды тратит. Отсюда и цифра — 300 транзакций в секунду.</p>
]]></content:encoded>
			<wfw:commentRss>http://john.5070.info/2009/02/nginx-%d0%bf%d1%80%d0%be%d1%82%d0%b8%d0%b2-oproxy-%d0%b4%d1%80%d1%83%d0%b3-%d0%b4%d1%80%d1%83%d0%b3%d1%83-%d1%81%d0%bb%d0%b8%d0%b2%d0%b0%d0%b5%d0%bc/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Пора в production? Скоро узнаем.</title>
		<link>http://john.5070.info/2009/01/%d0%bf%d0%be%d1%80%d0%b0-%d0%b2-production-%d1%81%d0%ba%d0%be%d1%80%d0%be-%d1%83%d0%b7%d0%bd%d0%b0%d0%b5%d0%bc/</link>
		<comments>http://john.5070.info/2009/01/%d0%bf%d0%be%d1%80%d0%b0-%d0%b2-production-%d1%81%d0%ba%d0%be%d1%80%d0%be-%d1%83%d0%b7%d0%bd%d0%b0%d0%b5%d0%bc/#comments</comments>
		<pubDate>Thu, 29 Jan 2009 18:46:40 +0000</pubDate>
		<dc:creator>John Lepikhin</dc:creator>
				<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[oProxy]]></category>
		<category><![CDATA[программирование]]></category>
		<category><![CDATA[cluster]]></category>
		<category><![CDATA[хостинг]]></category>

		<guid isPermaLink="false">http://john.5070.info/?p=67</guid>
		<description><![CDATA[Готовимся к продакшен тестированию. Надеюсь, завтра запустить всё воедино на тестовых машинах.
Из нового:

Балансировка нагрузки. Универсальный модуль для любых видов соединений. Написано кривовато, но работает. Заведует всеми узлами мастер-процесс. Это несколько замедляет процесс (рабочим приходится больше общаться с мастером), зато позволяет контролировать балансировку в одном месте.
Файлик: список сайтов. Пока каждый сайт можно только включить/выключить и прописать [...]]]></description>
			<content:encoded><![CDATA[<p>Готовимся к продакшен тестированию. Надеюсь, завтра запустить всё воедино на тестовых машинах.</p>
<p>Из нового:</p>
<ul>
<li>Балансировка нагрузки. Универсальный модуль для любых видов соединений. Написано кривовато, но работает. Заведует всеми узлами мастер-процесс. Это несколько замедляет процесс (рабочим приходится больше общаться с мастером), зато позволяет контролировать балансировку в одном месте.</li>
<li>Файлик: список сайтов. Пока каждый сайт можно только включить/выключить и прописать алиасы. Кроме того, на будущее есть поле &#8220;домашняя директория сайта&#8221;. В ближайшее время есть планы проксёй отдавать статичные файлы. Не понятно, что делать с .htaccess. Не хочется забивать, как это нынче делается в Nginx.</li>
<li>Файлик: список узлов. Представляет из себя IP, мастер-пароль, список ролей.</li>
<li>Роли. Что каждая машина умеет/должна делать. От этого зависит поведение балансировщика и некоторых скриптов. Предопределённые роли: worker_http (узел умеет обрабатывать HTTP-запросы), master (узел будет точкой входа, где висит балансировщик) и другие. Всё рассказывать раньше времени не буду :)</li>
<li>Мониторинг. Наконец нашёл, где заюзать функционалы. На основе этого функционала (functional) написан мониторинг файлов. Как результат, прокся умеет автоматически подгружать изменённый список сайтов или узлов.</li>
<li>Новый параметр у oproxyctl: show_nodes. Показывает известные узлы. Кто в дауне, сколько у каждого активных запросов, сколько всего обработано. Может оказаться полезным для выяснения проблемных узлов.</li>
<li>Поддерживаем новый протокол, который я сам выдумал :) Служит для различных сервисных запросов к узлу. Поскольку позволяет совершать совершенно небезопасные вещи, авторизация происходит без передачи открытого пароля по сети.</li>
<li>Новая утилита: clusterctl. Умеет 1) запустить на узлах с указанной ролью (или на всех, или на определённом IP) определённую команду и вернуть в STDOUT/STDERR что в итоге получилось 2) рассказывать список ролей текущей ноды 3) рассказывать список узлов, поддерживающих указанную роль. Служит для сервисных скриптов.</li>
<li>Прокся умеет выставлять X-Forwarded-For, чтобы в конечном итоге в логи попадал нужный IP.</li>
<li>Сервисные скрипты: apachectl (рестарт Апача на всех узлах), repquota и другие.</li>
<li>Оптимизация, стабильность.</li>
</ul>
<p>Допил коньяк. Опять потянуло на философию…</p>
]]></content:encoded>
			<wfw:commentRss>http://john.5070.info/2009/01/%d0%bf%d0%be%d1%80%d0%b0-%d0%b2-production-%d1%81%d0%ba%d0%be%d1%80%d0%be-%d1%83%d0%b7%d0%bd%d0%b0%d0%b5%d0%bc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TCP_NODELAY, Ocaml 3.11</title>
		<link>http://john.5070.info/2008/11/tcp_nodelay-ocaml-311/</link>
		<comments>http://john.5070.info/2008/11/tcp_nodelay-ocaml-311/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 19:20:17 +0000</pubDate>
		<dc:creator>John Lepikhin</dc:creator>
				<category><![CDATA[Ocaml]]></category>

		<guid isPermaLink="false">http://john.5070.info/?p=46</guid>
		<description><![CDATA[Обнаружил существенный недостаток модуля Unix в Ocaml 3.10. Нет возможности отключить алгоритм Нагла для соединений. Как следствие, приложения с высокой интерактивностью существенно теряют в производительности (меня в данном случае волнует MySQL). Лерой обещал устранить в версии 3.11. Учитывая, что она уже RC, возможно, имеет смысл начать к ней приглядываться. Тем более что там, помимо прочего, [...]]]></description>
			<content:encoded><![CDATA[<p>Обнаружил существенный недостаток модуля Unix в Ocaml 3.10. Нет возможности отключить алгоритм Нагла для соединений. Как следствие, приложения с высокой интерактивностью существенно теряют в производительности (меня в данном случае волнует MySQL). Лерой обещал устранить в версии 3.11. Учитывая, что она уже RC, возможно, имеет смысл начать к ней приглядываться. Тем более что там, помимо прочего, появилась поддержка Dynlink&#8217;а для нативного кода. Чего тоже сильно не хватало.</p>
]]></content:encoded>
			<wfw:commentRss>http://john.5070.info/2008/11/tcp_nodelay-ocaml-311/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>oProxy (о прокси, about proxy)</title>
		<link>http://john.5070.info/2008/11/oproxy/</link>
		<comments>http://john.5070.info/2008/11/oproxy/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 17:51:04 +0000</pubDate>
		<dc:creator>John Lepikhin</dc:creator>
				<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[программирование]]></category>

		<guid isPermaLink="false">http://john.5070.info/?p=38</guid>
		<description><![CDATA[Настроение: подшофе. Первый эксбиционисткий пост, как и положено в б-сферах. Прости меня, г-поди!
Написал версию 0.02 проекта с рабочим названием oProxy. В этой версии всё переписано с нуля + умеет считать трафик и прочую статистику :) На моём ноуте умеет обрабатывать ~2500 соединений в секунду. Соединения обрабатываются рабочими. При этом, 80% тормозов происходит на принятии соединения [...]]]></description>
			<content:encoded><![CDATA[<p>Настроение: подшофе. Первый эксбиционисткий пост, как и положено в б-сферах. Прости меня, г-поди!</p>
<p><span id="more-38"></span>Написал версию 0.02 проекта с рабочим названием oProxy. В этой версии всё переписано с нуля + умеет считать трафик и прочую статистику :) На моём ноуте умеет обрабатывать ~2500 соединений в секунду. Соединения обрабатываются рабочими. При этом, 80% тормозов происходит на принятии соединения мастером, около 10% в мутексах для сбора статистики внутри рабочих, и около 10% уходит непосредственно на саму обработку (парсинг заголовков HTTP-запроса, обработка ошибок протокола и т.д.). Рабочие CPU почти не едят, в отличие от атакующего siege&#8217;а (~0.4% против 35%). То есть, запас роста есть. Памяти жрёт 1.7Mb на одного рабочего.</p>
<p>За пятничный вечер сделал дома больше, чем за всю рабочую неделю в офисе. Там становится невозможно работать. И причины не совсем ясны. Даже старое средство — наушники с музыкой — уже не помогает. Надо что-то придумывать. Послушать Шурика, и приходить на работу к 07:00?.. [не канает: ответственнен за некоторые машины, которые почему-то любят падать в период 23:00..03:00].</p>
<p>Полтора года тащился от Ocaml. Полтора года прищуренным глазом посматривал на вакансии. С вакансиями ситуация такая: за полтора года в России их было 2 штуки, обе уровня &#8220;мы тут пишем крутую фигню, но зарплата фиг знает когда будет&#8221;. За рубежом ситуация чуть лучше, но Ocaml-программистов хотят там всякие университеты и на соответствующие должности. И тут получил официальное одобрение разрабатывать заданный проект на чём сам пожелаю. Если так пойдёт и дальше — через полгодика я сам смогу торговать окамлевыми вакансиями! А ведь ещё не прошло и года с момента увольнения Стаса, который буквально позавчера должен уехать в СПб на вакансию Lisp-программиста.</p>
]]></content:encoded>
			<wfw:commentRss>http://john.5070.info/2008/11/oproxy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Рыбак рыбака</title>
		<link>http://john.5070.info/2008/07/%d1%80%d1%8b%d0%b1%d0%b0%d0%ba-%d1%80%d1%8b%d0%b1%d0%b0%d0%ba%d0%b0/</link>
		<comments>http://john.5070.info/2008/07/%d1%80%d1%8b%d0%b1%d0%b0%d0%ba-%d1%80%d1%8b%d0%b1%d0%b0%d0%ba%d0%b0/#comments</comments>
		<pubDate>Wed, 02 Jul 2008 01:16:58 +0000</pubDate>
		<dc:creator>John Lepikhin</dc:creator>
				<category><![CDATA[Ocaml]]></category>

		<guid isPermaLink="false">http://john.5070.info/?p=31</guid>
		<description><![CDATA[Иногда проекты на Окамле легко идентифицировать. Вот какие ошибки шлёт один из самых популярных сайт-мониторингов host-tracker.com:
Ошибка HTTP:Http_client.No_reply
Характерное написание исключения вызвало подозрения. И не зря:
$ grep No_reply netclient/http_client.mli
exception No_reply;;
Они бы ещё через маршала давали API к себе — цены бы им не было :)
]]></description>
			<content:encoded><![CDATA[<p>Иногда проекты на Окамле легко идентифицировать. Вот какие ошибки шлёт один из самых популярных сайт-мониторингов host-tracker.com:</p>
<p>Ошибка HTTP:Http_client.No_reply</p>
<p>Характерное написание исключения вызвало подозрения. И не зря:</p>
<p>$ grep No_reply netclient/http_client.mli<br />
exception No_reply;;</p>
<p>Они бы ещё через маршала давали API к себе — цены бы им не было :)</p>
]]></content:encoded>
			<wfw:commentRss>http://john.5070.info/2008/07/%d1%80%d1%8b%d0%b1%d0%b0%d0%ba-%d1%80%d1%8b%d0%b1%d0%b0%d0%ba%d0%b0/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
