<?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>Rest Term</title>
	<atom:link href="http://rest-term.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://rest-term.com</link>
	<description>Web関連技術や雑記など</description>
	<lastBuildDate>Mon, 30 Aug 2010 15:59:16 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>JAM Session2</title>
		<link>http://rest-term.com/archives/2807/</link>
		<comments>http://rest-term.com/archives/2807/#comments</comments>
		<pubDate>Mon, 30 Aug 2010 14:43:31 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2807</guid>
		<description><![CDATA[2010年8月7日から始まったJAM &#8211; HTML5 and FlashのSession2。 お題は「MediaRSSをフィードとするフォトビューアをつくってください」 OrganizerはGoogleさん。 あのGoogleのお題にしてはシンプルだなぁと思った人も多いかもしれませんが、 このテーマの裏にさらに壮大なテーマを含んでいることがわかります。 この MediaRSS(mRSS) というのは、 Yahoo!が開発したマルチメディアベースのRSS配信における規格です。 mRSSが生まれた背景にはお金の見え隠れする話もあったと思いますが、 1つはコンテンツホルダーの権利を大切にするという目的が含まれています。 (mRSSの仕様をよく読んでみると分かると思います) これをGoogleがテーマに挙げてくるということは、自身がモットーとしている 「Don&#8217;t be Evil (悪をなさない)」 を示しているのではないでしょうか。 また、この間グーグルとヤフーの提携の話がありましたが、 ヤフーは検索エンジンを使わせてもらう代わりに、サービスのデータをグーグルにフィードします。 もう既にmRSSの形でグーグルにデータを提供しているサービスもあると思いますが、 画像検索や動画配信などのマルチメディア領域のサービスにG/Y!双方が力を入れていく上で、 必要不可欠な要素の1つがMedia RSSであると。 JAM Session2のお題からそんな事を伺い知ることができます。 HTML5とFlash、さらにその後ろでGとY!のJAM。 結果が楽しみです。 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; こんな事を書きつつ、僕自身JAMには参加していないのですが、 「RubyKaigiが終わるまでプライベートではRuby以外書かない」 という自分ルールを愚直に守っていた為、参加できませんでした。。 さすがに今からじゃ間に合わない>]]></description>
			<content:encoded><![CDATA[<p>2010年8月7日から始まった<a href="http://jsdo.it/event/jam/">JAM &#8211; HTML5 and Flash</a>のSession2。<br />
お題は「MediaRSSをフィードとするフォトビューアをつくってください」<br />
OrganizerはGoogleさん。<br />
あのGoogleのお題にしてはシンプルだなぁと思った人も多いかもしれませんが、<br />
このテーマの裏にさらに壮大なテーマを含んでいることがわかります。<br />
この <a href="http://video.search.yahoo.com/mrss">MediaRSS(mRSS)</a> というのは、<br />
Yahoo!が開発したマルチメディアベースのRSS配信における規格です。<br />
mRSSが生まれた背景にはお金の見え隠れする話もあったと思いますが、<br />
1つはコンテンツホルダーの権利を大切にするという目的が含まれています。<br />
(mRSSの仕様をよく読んでみると分かると思います)<br />
これをGoogleがテーマに挙げてくるということは、自身がモットーとしている<br />
「Don&#8217;t be Evil (悪をなさない)」<br />
を示しているのではないでしょうか。<br />
また、この間グーグルとヤフーの提携の話がありましたが、<br />
ヤフーは検索エンジンを使わせてもらう代わりに、サービスのデータをグーグルにフィードします。<br />
もう既にmRSSの形でグーグルにデータを提供しているサービスもあると思いますが、<br />
画像検索や動画配信などのマルチメディア領域のサービスにG/Y!双方が力を入れていく上で、<br />
必要不可欠な要素の1つがMedia RSSであると。<br />
JAM Session2のお題からそんな事を伺い知ることができます。<br />
HTML5とFlash、さらにその後ろでGとY!のJAM。<br />
結果が楽しみです。</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
こんな事を書きつつ、僕自身JAMには参加していないのですが、<br />
「RubyKaigiが終わるまでプライベートではRuby以外書かない」<br />
という自分ルールを愚直に守っていた為、参加できませんでした。。<br />
さすがに今からじゃ間に合わない><<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2807/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>wonderfl API Rubyクライアント</title>
		<link>http://rest-term.com/archives/2806/</link>
		<comments>http://rest-term.com/archives/2806/#comments</comments>
		<pubDate>Mon, 16 Aug 2010 11:44:17 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[webapi]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2806</guid>
		<description><![CDATA[wonderfl APIをRubyから簡単に利用するためのライブラリを作りました。 Rubygemsに公開されています。 wonderfl &#124; RubyGems.org &#124; your community gem host ・RDoc ドキュメント (Wonderfl::Client の所を見れば使い方は分かります) File: README.rdoc [RDoc Documentation] wonderfl APIの現在の仕様として、、リソースが存在しなくても、認証に失敗しても、全てHTTPステータスコード 200を返却してくるまずい仕様なので(せっかくリソース指向になってるのに；)、異常系処理を書いてる時に困った人も多いかと思います。このライブラリではAPIのエラー内容に応じた例外を投げるようにしています。それ以外は薄いラッパーなのでキャッシュ機能などは備えておらず、JSONレスポンスを解析する程度しか内部では行っていません。 導入方法 gemを利用してインストールできます。 $ gem install wonderfl また、このライブラリを利用するにはapi keyが必要です。 wonderfl build flash onlineにて作成しておきます。 使い方 詳細はRubygemsのページから辿れます。RDocも適宜参照してください。 基本的に Wonderfl::Client クラスの各メソッドを呼ぶだけです。 Wonderfl::Client get_user(&#8216;user name&#8217;) get_user_codes(&#8216;user name&#8217;) get_code(&#8216;code id&#8217;) get_code_forks(&#8216;code id&#8217;) [ruby] #!/usr/bin/ruby require &#8216;rubygems&#8217; require &#8216;wonderfl&#8217; begin [...]]]></description>
			<content:encoded><![CDATA[<p>wonderfl APIをRubyから簡単に利用するためのライブラリを作りました。<br />
Rubygemsに公開されています。<br />
<a href="http://rubygems.org/gems/wonderfl" title="wonderfl | RubyGems.org | your community gem host">wonderfl | RubyGems.org | your community gem host</a><br />
・RDoc ドキュメント<br />
(Wonderfl::Client の所を見れば使い方は分かります)<br />
<a href="http://rest-term.com/contents/doc/wonderfl/README.rdoc.html" title="File: README.rdoc [RDoc Documentation]">File: README.rdoc [RDoc Documentation]</a></p>
<p>wonderfl APIの現在の仕様として、、リソースが存在しなくても、認証に失敗しても、全てHTTPステータスコード 200を返却してくるまずい仕様なので(せっかくリソース指向になってるのに；)、異常系処理を書いてる時に困った人も多いかと思います。このライブラリではAPIのエラー内容に応じた例外を投げるようにしています。それ以外は薄いラッパーなのでキャッシュ機能などは備えておらず、JSONレスポンスを解析する程度しか内部では行っていません。</p>
<h2 class="term">導入方法</h2>
<p>gemを利用してインストールできます。</p>
<pre>
$ gem install wonderfl
</pre>
<p>また、このライブラリを利用するにはapi keyが必要です。<br />
<a href="http://wonderfl.net/account/api_keys/create" title="wonderfl build flash online">wonderfl build flash online</a>にて作成しておきます。</p>
<h2 class="term">使い方</h2>
<p>詳細はRubygemsのページから辿れます。RDocも適宜参照してください。<br />
基本的に Wonderfl::Client クラスの各メソッドを呼ぶだけです。</p>
<dl>
<dt>Wonderfl::Client</dt>
<dd>get_user(&#8216;user name&#8217;)</dd>
<dd>get_user_codes(&#8216;user name&#8217;)</dd>
<dd>get_code(&#8216;code id&#8217;)</dd>
<dd>get_code_forks(&#8216;code id&#8217;)</dd>
</dl>
<p>[ruby]<br />
#!/usr/bin/ruby</p>
<p>require &#8216;rubygems&#8217;<br />
require &#8216;wonderfl&#8217;</p>
<p>begin<br />
# Wonderfl::Client オブジェクトを生成、引数にapi key<br />
  client = Wonderfl::Client.new(&#8216;your api key&#8217;)<br />
  client.api_key = &#8216;your api key&#8217;  # 後でapi keyを設定することも可能</p>
<p># ユーザー情報を取得、引数にユーザー名<br />
  user = client.get_user(&#8216;wellflat&#8217;)  #=> Wonderfl::User</p>
<p># 各ユーザー情報を参照<br />
  puts user.icon  #=> &#8220;http://wonderfl.net/img/comon/~.gif&#8221;<br />
  puts user.external_url  #=> &#8220;http://rest-term.com/&#8221;<br />
  puts user.name  #=> &#8220;wellflat&#8221;<br />
  puts user.description  #=> &#8220;web engineer&#8221;</p>
<p># 作品情報を取得、引数にコードID<br />
  code = client.get_code(&#8216;code id&#8217;)  #=> Wonderfl::Code</p>
<p># 作品の各情報を参照<br />
  puts code.thumbnail  #=> 作品のサムネイルURL<br />
  puts code.forked_count  #=> forkされた数<br />
  puts code.favorite_count  #=> favoriteされた数<br />
  puts code.title  #=> 作品のタイトル<br />
  puts code.as3  #=> 作品のAS3.0コード (巨大なコードもあるので注意)<br />
&#8230; # 他にもいろいろな情報を取得できます</p>
<p># ユーザーの投稿した作品情報を取得<br />
  user_codes = client.get_user_codes(&#8216;user name&#8217;)  #=> Wonderfl::UserCodes</p>
<p># ユーザーの投稿した作品数<br />
  puts user_codes.count</p>
<p># 作品のタイトルを列挙<br />
  user_codes.each do |code|<br />
    puts code.title  #=> title 以外でももちろんOK<br />
  end</p>
<p># forkされた作品情報を取得<br />
  code_forks = client.get_code_forks(&#8216;code id&#8217;)  #=> Wonderfl::CodeForks</p>
<p># forkされた作品数<br />
  puts code_forks.count</p>
<p># forkしたユーザーの名前を列挙<br />
  code_forks.each do |code|<br />
    puts code.user_name<br />
  end</p>
<p>rescue Wonderfl::BadRequest => e<br />
# 各メソッドの引数が不正な場合</p>
<p>rescue Wonderfl::Unauthorized => e<br />
# 認証に失敗した場合 (api keyが不正)</p>
<p>rescue Wonderfl::NotFound => e<br />
# 指定したユーザーや作品が存在しない場合</p>
<p>rescue Wonderfl::InternalServerError => e<br />
# wonderfl APIがレスポンスを正しく返却できない場合<br />
# (APIの仕様変更などによりJSONレスポンスが解析不可の場合も)</p>
<p>end<br />
[/ruby]<br />
コードを見てもらえば分かるように、各エラー内容に応じた例外が発生するようになっているのでそれぞれに対応した異常系処理を書くことが簡単になります。また、取得した情報が数値なら(forked_count 等) Integer 型、日付なら(created_date 等) Time 型に内部で変換しています。</p>
<p>また、現在取得できるユーザー/作品情報について載せておきます。</p>
<p>・<strong>ユーザー情報</strong>  (Wonderfl::User)</p>
<ul>
<li>icon</li>
<li>external_url</li>
<li>name</li>
<li>description</li>
</ul>
<p>・<strong>作品情報</strong>  (Wonderfl::Code)</p>
<ul>
<li>thumbnail</li>
<li>as3 (get_user 利用時のみ参照可)</li>
<li>parent</li>
<li>modified_date (get_user 利用時のみ参照可)</li>
<li>compile_ok</li>
<li>created_date</li>
<li>forked_count (get_user 利用時のみ参照可)</li>
<li>license</li>
<li>swf</li>
<li>diff (get_user 利用時のみ参照可)</li>
<li>user_icon (get_user_codes, get_code_forks 利用時に参照可)</li>
<li>user_name (get_user_codes, get_code_forks 利用時に参照可)</li>
<li>title</li>
<li>id</li>
<li>favorite_count (get_user 利用時のみ参照可)</li>
</ul>
<h2 class="term">注意事項</h2>
<p>BANされないように、取得結果をキャッシュしつつ利用するといいです（このライブラリにキャッシュ機能を付けることも考えています）。あと、要望や不具合などがあったらお知らせください。</p>
<hr />
実は、このライブラリはけっこう昔に作ったものなので、スコアAPIのクライアントは備えていません（要望があれば追加します）。APIの仕様が運良くまだ変わってないようなので今も動作しているだけだったりします。。（不具合があれば修正します）</p>
<p>gemのライブラリを作った個人的な目的としては、gitに慣れることとRSpecの書き方を学ぶことの2つがありました。会社ではバージョン管理にsubversionを使っていてgitを使う機会がなかったので。RSpecについては、振る舞い駆動開発というものを体験しておく必要性を感じたからです。どちらもある程度理解することはできたので目的は達成したかなと思います。rakeの使い方にも慣れるという嬉しい副産物も(^^</p>
<p>また、Flash使いの人はサーバサイドの言語にPHPを選択する人がほとんどだと思いますが、Rubyが使えるとRailsアプリケーションと連携したりと作品の幅が広がるのでオススメです。</p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2806/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascriptでカラーヒストグラム</title>
		<link>http://rest-term.com/archives/2803/</link>
		<comments>http://rest-term.com/archives/2803/#comments</comments>
		<pubDate>Sun, 01 Aug 2010 11:48:08 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[cv/im]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2803</guid>
		<description><![CDATA[画像のカラーヒストグラムをJavascriptで。 jsdo.it：Color Histogram using Web Workers &#8211; jsdo.it サイト内：HTML5 Color Histogram using Web Workers Web Workers を利用しています。 Workerプロセスに画像データを渡し、Worker内部で各チャンネル毎にヒストグラムを計算して返却。 通常のWorkerでは、Workerインスタンスとバックグラウンドプロセスが1対1で対応しているため、 並列処理を行うといっても特に難しいことを考える必要はありません。 (pthreadを扱うような難しさはなし、SharedWorkerを利用する場合は多少注意が必要) また、IE以外の主要ブラウザでは、Workerに単純なObjectが渡せるようになっており、 この対応のおかげでWeb Workersの利用用途が増え、自由度が上がりました。 ただし、Web Workersを利用する時は少しだけ気を付けることがあって、 例えば、Worker内部からはDOMオブジェクトにアクセスできません。 これはビューとビジネスロジックの分離を強制させてくれるので良い設計に繋がります。 制作寄りの方々はこの制限を不便なものだと最初は捉えるかと思いますが、 今後、HTML5が普及してJavascriptの重要性が高まり、大規模なプロジェクトが増えるはずです。 そういった時に設計から任せられるデザイナは重宝されると思います。 個人的にHTML5関連で興味があるのはストレージ周りなので、 Indexed Database APIの情報/実装が揃ってきたら、そちらの方の調査をしていく予定です。]]></description>
			<content:encoded><![CDATA[<p>画像のカラーヒストグラムをJavascriptで。<br />
<img src="http://rest-term.com/wp-content/uploads/2010/08/histogram.jpg" alt="" title="histogram" width="398" height="199" class="alignnone size-full wp-image-2804" /><br />
jsdo.it：<a href="http://jsdo.it/wellflat/prjR" title="Color Histogram using Web Workers - jsdo.it">Color Histogram using Web Workers &#8211; jsdo.it</a><br />
サイト内：<a href="http://rest-term.com/contents/other/html5/histogram.html" title="HTML5 Color Histogram using Web Workers">HTML5 Color Histogram using Web Workers</a></p>
<p><a href="http://www.whatwg.org/specs/web-workers/current-work/">Web Workers</a> を利用しています。<br />
Workerプロセスに画像データを渡し、Worker内部で各チャンネル毎にヒストグラムを計算して返却。<br />
通常のWorkerでは、Workerインスタンスとバックグラウンドプロセスが1対1で対応しているため、<br />
並列処理を行うといっても特に難しいことを考える必要はありません。<br />
(pthreadを扱うような難しさはなし、SharedWorkerを利用する場合は多少注意が必要)</p>
<p>また、IE以外の主要ブラウザでは、Workerに単純なObjectが渡せるようになっており、<br />
この対応のおかげでWeb Workersの利用用途が増え、自由度が上がりました。<br />
ただし、Web Workersを利用する時は少しだけ気を付けることがあって、<br />
例えば、Worker内部からはDOMオブジェクトにアクセスできません。<br />
これはビューとビジネスロジックの分離を強制させてくれるので良い設計に繋がります。<br />
制作寄りの方々はこの制限を不便なものだと最初は捉えるかと思いますが、<br />
今後、HTML5が普及してJavascriptの重要性が高まり、大規模なプロジェクトが増えるはずです。<br />
そういった時に設計から任せられるデザイナは重宝されると思います。</p>
<p>個人的にHTML5関連で興味があるのはストレージ周りなので、<br />
Indexed Database APIの情報/実装が揃ってきたら、そちらの方の調査をしていく予定です。</p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2803/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascriptで3D入門</title>
		<link>http://rest-term.com/archives/2799/</link>
		<comments>http://rest-term.com/archives/2799/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 08:47:44 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2799</guid>
		<description><![CDATA[>> My 3D Library Test &#8211; jsdo.it 3D表現にはあまり詳しくないのですが、Javascriptの勉強ということで3Dライブラリを書いてます。 jsdo.itの文化に合わせてビジュアル的な要素を持ったサンプルで試していこうと。 Actionscript3.0ネイティブとPapervision3DライブラリのAPIを両方参考にして書いたので、 クラス設計も曖昧で試行錯誤中ですが、そこも含めて少しずつブラッシュアップしていこうと思います。 以前、jsdo.itに投稿した Heart Surface &#8211; jsdo.it Möbius Strip &#8211; jsdo.it の2つは、座標計算や描画処理を全て1つのオブジェクトに詰め込んだ使い捨てのコードでした。 ライブラリを書くとなると、座標計算周りはただ計算するだけでいいので悩む所はないのですが、 FlashでいうところのDisplayObject(?に当たるものまで自前で書かないといけないので大変； 計算と描画を綺麗に分けて書くのが難しいです。 その点、Actionscriptは強力なクラスライブラリ/API群が備わっているので羨ましい限り。 あと話は変わって、jsdo.itのJavascript/HTML/CSSの書き分けとして、 Javascript/CSSは別の作品から読み込むことができるので、HTMLと密結合してない方がいいです。 （例えば、タグのid/class名が直接Javascriptのエリアに入り込んでしまう等） Web Workersを利用したコードも結局DOMと切り離した書き方をすることになりますから。 引き続き、HTML5の勉強を進めていきたいと思います。]]></description>
			<content:encoded><![CDATA[<p><a href="http://jsdo.it/wellflat/zmko" title="My 3D Library Test - jsdo.it"><img src="http://rest-term.com/wp-content/uploads/2010/07/my3dlib.jpg" alt="" title="my3dlib" width="328" height="378" class="alignnone size-full wp-image-2802" /><br />
>> My 3D Library Test &#8211; jsdo.it</a><br />
3D表現にはあまり詳しくないのですが、Javascriptの勉強ということで3Dライブラリを書いてます。<br />
jsdo.itの文化に合わせてビジュアル的な要素を持ったサンプルで試していこうと。<br />
Actionscript3.0ネイティブとPapervision3DライブラリのAPIを両方参考にして書いたので、<br />
クラス設計も曖昧で試行錯誤中ですが、そこも含めて少しずつブラッシュアップしていこうと思います。</p>
<p>以前、jsdo.itに投稿した<br />
<a href="http://jsdo.it/wellflat/qRfA" title="Heart Surface">Heart Surface &#8211; jsdo.it</a><br />
<a href="http://jsdo.it/wellflat/7oEc" title="Möbius Strip">Möbius Strip &#8211; jsdo.it</a><br />
の2つは、座標計算や描画処理を全て1つのオブジェクトに詰め込んだ使い捨てのコードでした。<br />
ライブラリを書くとなると、座標計算周りはただ計算するだけでいいので悩む所はないのですが、<br />
FlashでいうところのDisplayObject(?に当たるものまで自前で書かないといけないので大変；<br />
計算と描画を綺麗に分けて書くのが難しいです。<br />
その点、Actionscriptは強力なクラスライブラリ/API群が備わっているので羨ましい限り。</p>
<p>あと話は変わって、jsdo.itのJavascript/HTML/CSSの書き分けとして、<br />
Javascript/CSSは別の作品から読み込むことができるので、HTMLと密結合してない方がいいです。<br />
（例えば、タグのid/class名が直接Javascriptのエリアに入り込んでしまう等）<br />
Web Workersを利用したコードも結局DOMと切り離した書き方をすることになりますから。</p>
<p>引き続き、HTML5の勉強を進めていきたいと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2799/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQLパラメータチューニングメモ</title>
		<link>http://rest-term.com/archives/2797/</link>
		<comments>http://rest-term.com/archives/2797/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 15:01:55 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[database]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2797</guid>
		<description><![CDATA[MySQL関連のメモ。一応、本業はインフラ屋なので。 実際に業務で見ている主にメモリ周りのパラメータについて。 特別なノウハウ等は入っていない基礎知識程度です。 MySQLのバッファには以下の2種類のタイプがある。 パラメータチューニングの際にはこの2つのタイプの違いを意識しないといけない。 * グローバルバッファ (mysqld内部で1つだけ確保される) * スレッドバッファ (スレッド毎に確保される) スレッドバッファに多くのメモリを割り当てすぎるとコネクションが増えた途端すぐにメモリ不足に。 物理メモリ以上のサイズを割り当ててしまうと、スワップが発生して逆にパフォーマンスが落ちる。 innodb_buffer_pool_size (グローバル) InnoDBのデータやインデックスを保持するために使用するメモリバッファのサイズ。グローバルなのでたくさん割り当てると良い。 innodb_additional_mem_pool_size (グローバル) InnoDBの内部データなどを保持するために使用するメモリプールのサイズ。エラーログに警告が出たら増やせばいい程度。 innodb_log_buffer_size (グローバル) InnoDBの更新ログを記録するために使用するメモリバッファのサイズ。大きなトランザクションがある場合はこれを大きくするとディスクI/Oを減らせるが実際はそんなに必要ない。 sort_buffer_size (スレッド) ORDER BYやGROUP BYの時に使用されるメモリバッファのサイズ。スレッドバッファなので大きくしすぎてメモリ不足にならないように。 read_rnd_buffer_size (スレッド) ソート後にレコードを読むときに使用されるメモリバッファのサイズ。これもORDER BYやGROPY BYを行う場合のパフォーマンスに影響する。 join_buffer_size (スレッド) インデックスを用いないテーブル結合時に使用されるメモリバッファのサイズ。 read_buffer_size (スレッド) インデックスを用いないテーブルスキャン時に使用されるメモリバッファのサイズ。 key_buffer_size (グローバル) MyISAMのキー(インデックス)を保持するために使用するメモリバッファのサイズ。グローバルなのでたくさん割り当てると良い。ただし、MyISAMを利用してない場合は他のパラメータにメモリを回す。 myisam_sort_buffer_size (スレッド) MyISAMでソート時(REPAIR TABLE, CREATE INDEX, ALTER INDEX)に使用するメモリバッファのサイズ。ORDER BYやGROUP BYを行う場合のパフォーマンスに影響する。 * その他 innodb_log_file_size InnoDBの更新ログを記録するディスク上のファイルサイズ。 [...]]]></description>
			<content:encoded><![CDATA[<p>MySQL関連のメモ。一応、本業はインフラ屋なので。</p>
<p>実際に業務で見ている主にメモリ周りのパラメータについて。<br />
特別なノウハウ等は入っていない基礎知識程度です。</p>
<p>MySQLのバッファには以下の2種類のタイプがある。<br />
パラメータチューニングの際にはこの2つのタイプの違いを意識しないといけない。</p>
<p>* <strong>グローバルバッファ</strong> (mysqld内部で1つだけ確保される)<br />
* <strong>スレッドバッファ</strong> (スレッド毎に確保される)</p>
<p>スレッドバッファに多くのメモリを割り当てすぎるとコネクションが増えた途端すぐにメモリ不足に。<br />
物理メモリ以上のサイズを割り当ててしまうと、スワップが発生して逆にパフォーマンスが落ちる。</p>
<table class="entry">
<tr>
<th>innodb_buffer_pool_size (グローバル)</th>
</tr>
<tr>
<td>InnoDBのデータやインデックスを保持するために使用するメモリバッファのサイズ。グローバルなのでたくさん割り当てると良い。</td>
</tr>
<tr>
<th>innodb_additional_mem_pool_size (グローバル)</th>
</tr>
<tr>
<td>InnoDBの内部データなどを保持するために使用するメモリプールのサイズ。エラーログに警告が出たら増やせばいい程度。</td>
</tr>
<tr>
<th>innodb_log_buffer_size (グローバル)</th>
</tr>
<tr>
<td>InnoDBの更新ログを記録するために使用するメモリバッファのサイズ。大きなトランザクションがある場合はこれを大きくするとディスクI/Oを減らせるが実際はそんなに必要ない。</td>
</tr>
<tr>
<th>sort_buffer_size (スレッド)</th>
</tr>
<tr>
<td>ORDER BYやGROUP BYの時に使用されるメモリバッファのサイズ。スレッドバッファなので大きくしすぎてメモリ不足にならないように。</td>
</tr>
<tr>
<th>read_rnd_buffer_size (スレッド)</th>
</tr>
<tr>
<td>ソート後にレコードを読むときに使用されるメモリバッファのサイズ。これもORDER BYやGROPY BYを行う場合のパフォーマンスに影響する。</td>
</tr>
<tr>
<th>join_buffer_size (スレッド)</th>
</tr>
<tr>
<td>インデックスを用いないテーブル結合時に使用されるメモリバッファのサイズ。</td>
</tr>
<tr>
<th>read_buffer_size (スレッド)</th>
</tr>
<tr>
<td>インデックスを用いないテーブルスキャン時に使用されるメモリバッファのサイズ。</td>
</tr>
<tr>
<th>key_buffer_size (グローバル)</th>
</tr>
<tr>
<td>MyISAMのキー(インデックス)を保持するために使用するメモリバッファのサイズ。グローバルなのでたくさん割り当てると良い。ただし、MyISAMを利用してない場合は他のパラメータにメモリを回す。</td>
</tr>
<tr>
<th>myisam_sort_buffer_size (スレッド)</th>
</tr>
<tr>
<td>MyISAMでソート時(REPAIR TABLE, CREATE INDEX, ALTER INDEX)に使用するメモリバッファのサイズ。ORDER BYやGROUP BYを行う場合のパフォーマンスに影響する。</td>
</tr>
</table>
<p>* その他</p>
<table class="entry">
<tr>
<th>innodb_log_file_size</th>
</tr>
<tr>
<td>InnoDBの更新ログを記録するディスク上のファイルサイズ。</td>
</tr>
<tr>
<td>1MB～innodb_buffer_pool_size/innodb_log_files_in_groupの間で設定する。</td>
</tr>
</table>
<p>MySQLには他にもたくさんパラメータはありますが、とりあえず見ておくべき項目を挙げました。<br />
最近はInnoDBばかり使っているので、MyISAM関連はあまりわかりません；<br />
ちなみに、MySQL 5.5ではデフォルトストレージエンジンはInnoDBらしいですね。<br />
ただ、業務で5.5導入するのは当分先になりそうです。。</p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2797/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jsdo.itで遊ぶ</title>
		<link>http://rest-term.com/archives/2793/</link>
		<comments>http://rest-term.com/archives/2793/#comments</comments>
		<pubDate>Sun, 27 Jun 2010 13:45:55 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2793</guid>
		<description><![CDATA[jsdo.it &#8211; share JavaScript, HTML5 and CSS wonderflのHTML5版、おもしろいですね。 JavascriptだけでなくHTMLやCSSも編集できるので、制作さんのマークアップの練習にも利用できます。 wonderflとの一番の違いは、その利用者層の広さだと思っています。 前述のように制作さんでもHTML+CSSのプレイグラウンドとして利用できるし、 デベロッパのJavascriptの書き方も人それぞれで幅広く、見ていて飽きません。 手続き型で情熱的に勢いよく書きまくっている人。 関数オブジェクト、prototype等を効果的に使って緻密に書いている人。 Actionscript3.0な世界よりも広大に見えます。 潜在的な開発者数はFlashよりも多いのでそれは当然のことなのかもしれません。 2003,4年頃(? でしょうか。 AS1.0のonClipEvent()から少しずつprototypeをいじり倒すようになり、そしてAS2.0のclassへ。 jsdo.itでもそれに似た成長過程をたくさんのコードの中で目にするようになるんじゃないかと思います。 とても楽しみです。 Möbius Strip &#8211; jsdo.it]]></description>
			<content:encoded><![CDATA[<p><a href="http://jsdo.it/" title="jsdo.it - share JavaScript, HTML5 and CSS">jsdo.it &#8211; share JavaScript, HTML5 and CSS</a><br />
wonderflのHTML5版、おもしろいですね。<br />
JavascriptだけでなくHTMLやCSSも編集できるので、制作さんのマークアップの練習にも利用できます。</p>
<p>wonderflとの一番の違いは、その利用者層の広さだと思っています。<br />
前述のように制作さんでもHTML+CSSのプレイグラウンドとして利用できるし、<br />
デベロッパのJavascriptの書き方も人それぞれで幅広く、見ていて飽きません。<br />
手続き型で情熱的に勢いよく書きまくっている人。<br />
関数オブジェクト、prototype等を効果的に使って緻密に書いている人。<br />
Actionscript3.0な世界よりも広大に見えます。<br />
潜在的な開発者数はFlashよりも多いのでそれは当然のことなのかもしれません。</p>
<p>2003,4年頃(? でしょうか。<br />
AS1.0のonClipEvent()から少しずつprototypeをいじり倒すようになり、そしてAS2.0のclassへ。<br />
jsdo.itでもそれに似た成長過程をたくさんのコードの中で目にするようになるんじゃないかと思います。<br />
とても楽しみです。</p>
<p><a href="http://jsdo.it/wellflat/7oEc" title="Möbius Strip - jsdo.it"><img src="http://rest-term.com/wp-content/uploads/2010/06/mobius_strip.png" alt="" title="mobius_strip" width="400" height="367" class="alignnone size-full wp-image-2796" /><br />
Möbius Strip &#8211; jsdo.it</a></p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2793/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ActionScriptでSuffix Array</title>
		<link>http://rest-term.com/archives/2791/</link>
		<comments>http://rest-term.com/archives/2791/#comments</comments>
		<pubDate>Sun, 16 May 2010 14:02:18 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[actionscript]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2791</guid>
		<description><![CDATA[今回は画像処理ではなく文字列処理について。Suffix Arrayというデータ構造を扱います。 Suffix Array (接尾辞配列)は、もともと生物情報学の分野でゲノムデータベースの解析などに用いられてきたらしいのですが、そこからテキスト圧縮/検索などの自然言語文書を索引対象とした応用が広がり、全文検索エンジンの文字列索引(インデックス)としても利用されているデータ構造です。 Suffix(接尾辞)とは、索引対象となる文字列T内の任意の位置からTの末尾までの範囲の文字列のことで、Tの長さがNであればN個のSuffixが定義されインデックスが付与されます。Tの各Suffixは辞書順にソートされ、そのインデックスを配列にしたのがSuffix Arrayです。Suffixは辞書順にソートされているため、検索対象文字列をSuffix Array内で二分探索することにより、大規模テキストに対する高速な検索を可能にします。 詳細については以下のサイトにて詳しく解説されています。 suffix array Suffix ArrayのActionScriptでのコード例を示します。 1: &#8220;abracadabra&#8221; という文字列データが入ったファイルを読み込み、そのデータでSuffix Arrayを構築(クイックソート使用) 2: Suffix Array構築完了後、&#8221;ac&#8221; という部分文字列を探索(二分探索)して出現位置を返却 [as] package { import flash.display.Sprite; import flash.events.*; import flash.net.URLLoader; import flash.net.URLRequest; public class Test extends Sprite { private var sa:SuffixArray; private var urlLoader:URLLoader; public function Test() { urlLoader = new URLLoader(); urlLoader.addEventListener(Event.COMPLETE, completeHandler, false, [...]]]></description>
			<content:encoded><![CDATA[<p>今回は画像処理ではなく文字列処理について。<strong>Suffix Array</strong>というデータ構造を扱います。</p>
<p><a href="http://ja.wikipedia.org/wiki/%E6%8E%A5%E5%B0%BE%E8%BE%9E%E9%85%8D%E5%88%97">Suffix Array (接尾辞配列)</a>は、もともと生物情報学の分野でゲノムデータベースの解析などに用いられてきたらしいのですが、そこからテキスト圧縮/検索などの自然言語文書を索引対象とした応用が広がり、全文検索エンジンの文字列索引(インデックス)としても利用されているデータ構造です。</p>
<p>Suffix(接尾辞)とは、索引対象となる文字列T内の任意の位置からTの末尾までの範囲の文字列のことで、Tの長さがNであればN個のSuffixが定義されインデックスが付与されます。Tの各Suffixは辞書順にソートされ、そのインデックスを配列にしたのがSuffix Arrayです。Suffixは辞書順にソートされているため、検索対象文字列をSuffix Array内で二分探索することにより、大規模テキストに対する高速な検索を可能にします。</p>
<p>詳細については以下のサイトにて詳しく解説されています。<br />
<a href="http://homepage3.nifty.com/DO/suffix_array.htm">suffix array</a></p>
<p>Suffix ArrayのActionScriptでのコード例を示します。<br />
1: &#8220;abracadabra&#8221; という文字列データが入ったファイルを読み込み、そのデータでSuffix Arrayを構築(クイックソート使用)<br />
2: Suffix Array構築完了後、&#8221;ac&#8221; という部分文字列を探索(二分探索)して出現位置を返却</p>
<pre>[as]
package {
  import flash.display.Sprite;
  import flash.events.*;
  import flash.net.URLLoader;
  import flash.net.URLRequest;

  public class Test extends Sprite {
    private var sa:SuffixArray;
    private var urlLoader:URLLoader;

    public function Test() {
      urlLoader = new URLLoader();
      urlLoader.addEventListener(Event.COMPLETE, completeHandler, false, 0, true);
      urlLoader.addEventListener(IOErrorEvent.IO_ERROR, errorHandler, false, 0, true);
      urlLoader.load(new URLRequest("data.txt")); // abracadabra
    }
    private function completeHandler(e:Event):void {
      sa = new SuffixArray();
      var substring:String = "ac";
      sa.addEventListener(SuffixArray.BUILD_COMPLETE, function():void {
        trace(sa);
        trace("\nindex: " + sa.search(substring));
      }, false, 0, true);
      sa.build(e.target.data, SuffixArray.QUICK_SORT);
    }
    private function errorHandler(e:IOErrorEvent):void {
      trace(e);
    }
  }
}

import __AS3__.vec.Vector;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.utils.getTimer;

class SuffixArray extends EventDispatcher {
  public static const BUILD_COMPLETE:String = "build_complete";
  public static const QUICK_SORT:String = "quicksort";
  private var suffixes:Vector.<String>;
  private var len:int;
  private var _time:Number;

  public override function toString():String {
    return suffixes.join("\n");
  }
  /**
   * search substring, using binary search O(mlogn)
   */
  public function search(substring:String):int {
    if(len == 0) return substring.length == 0 ? 0 : -1;
    var low:int = 0, high:int = suffixes.length - 1;
    while(low < high) {
      var middle:int = low + (high - low)/2;
      if(suffixes[middle] >= substring) high = middle;
      else low = middle + 1;
    }
    if(suffixes[high].indexOf(substring, 0) == 0) {
      return len - suffixes[high].length;
    }
    return -1;
  }
  /**
   * build Suffix Array, O(n^2logn)
   */
  public function build(str:String, sortFunc:String = null):void {
    try {
      _time = getTimer();
      len = str.length;
      suffixes = new Vector.<String>(len, true);
      for(var i:int = 0; i < len; i++) {
        suffixes[i] = str.substring(i);
      }
      this[sortFunc]();
      _time = getTimer() - _time;
      dispatchEvent(new Event(BUILD_COMPLETE));
    }catch(e:ReferenceError) {
      suffixes.sort(
        function(x:String, y:String):int {
          return x > y ? 1 : x < y ? -1 : 0;
        }
      );
      _time = getTimer() - _time;
      dispatchEvent(new Event(BUILD_COMPLETE));
    }
  }
  public function get time():Number {
    return _time;
  }
  /**
   * apply Quick Sort
   */
  private function quicksort():void {
    _quicksort(suffixes, 0, suffixes.length - 1);
  }
  private function _quicksort(data:Vector.<String>, low:int, high:int):void {
    if(low > high) return;
    var i:int = low + 1, p:int = low, c:int = int((low + high)/2), pivot:String = data[c];
    data[c] = data[low];
    while(i <= high) {
      if(data[i] < pivot) {
        var tmp:String = data[++p];
        data[p] = data[i];
        data[i] = tmp;
      }
      i++;
    }
    data[low] = data[p];
    data[p] = pivot;
    _quicksort(data, low, p - 1);
    _quicksort(data, p + 1, high);
  }
}
[/as]</pre>
<p>• 実行結果</p>
<pre>
a
abra
abracadabra
acadabra
adabra
bra
bracadabra
cadabra
dabra
ra
racadabra

index: 3
</pre>
<p>ここで、テキスト圧縮技術の評価によく用いられる<a href="http://corpus.canterbury.ac.nz/index.html">Calgary/Canterburyコーパス</a>(書籍、ニュース、プログラムソースコード、ゲノム列(E.coli)などが含まれる)を用いてSuffix Arrayの構築時間を測ってみました。組み込みソート(Vector.sort())、クイックソート、<a href="http://www.cs.princeton.edu/~rs/strings/">マルチキークイックソート(Ternary Search Tree)</a>での処理時間は以下の通りです(5回の計測時間の平均)。</p>
<p>• 環境：<br />
Mac OSX 10.6.2: 2.26GHz / 2GB RAM<br />
Flash Player: 10.0.45 (Debug)<br />
Flex SDK: 4.0.0.14159</p>
<table class="entry" style="text-align:right">
<caption>sorting time on texts (sec)</caption>
<tr>
<th>data</th>
<th>size(byte)</th>
<th>Vector.sort()</th>
<th>QuickSort</th>
<th>Multikey QuickSort</th>
</tr>
<tr>
<td>progc</td>
<td>39611</td>
<td>0.407</td>
<td>0.341</td>
<td>0.100</td>
</tr>
<tr>
<td>news</td>
<td>377109</td>
<td>5.022</td>
<td>4.285</td>
<td>1.323</td>
</tr>
<tr>
<td>book1</td>
<td>768771</td>
<td>10.819</td>
<td>9.958</td>
<td>3.144</td>
</tr>
<tr>
<td>world192</td>
<td>2473400</td>
<td>39.781</td>
<td>35.322</td>
<td>15.366</td>
</tr>
<tr>
<td>E.coli</td>
<td>4638690</td>
<td>Error #1502</td>
<td>Error #1502</td>
<td>29.258</td>
</tr>
</table>
<p>4MB程度のデータ(E.coli)でも効率の悪いソート法だとFlash Playerがギブアップしてしまいます。。Suffix Arrayの欠点は構築に多くの時間がかかる点です。この問題を解決するためにマルチキークイックソートやMSD radix sort (基数ソート法, O(nlogn))、Two-Stage sort (二段階ソート法, O(n)) など数々の手法が提案されています。機会があればTwo-Stage sortあたりは一度書いてみたいなと思います。まぁでもFlashで大規模データは扱わないですよね。</p>
<p>Suffix Arrayは、整列(ソート)や探索、データ構造などをまとめて勉強できる教材として新人のC言語研修などに利用できるという話を聞きました。文字列配列を扱うのでポインタの勉強にも効果的かと。僕の所属部署では課題としては出ませんでしたが、検索事業などを持ってる部署ではN-gramと併せて課題の一つになってるみたいです。</p>
<p>あと、Suffix Arrayの構造を理解する為の小さなコードをwonderflに投稿しておきましたのでもし興味があれば。<br />
<a href="http://wonderfl.net/c/lIGa">Suffix Array | wonderfl build flash online</a></p>
<p>• 参考<br />
<a href="http://ci.nii.ac.jp/naid/110002725334">CiNii 論文 -  Suffix arrayの効率的な構築法</a><br />
<a href="http://homepage3.nifty.com/DO/suffix_array.htm">suffix array</a><br />
<a href="http://www.cs.princeton.edu/~rs/strings/">Sorting and Searching Strings</a></p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2791/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CassandraのMemtableについて</title>
		<link>http://rest-term.com/archives/2788/</link>
		<comments>http://rest-term.com/archives/2788/#comments</comments>
		<pubDate>Fri, 07 May 2010 21:14:32 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[database]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2788</guid>
		<description><![CDATA[引き続きCassandraについて調査中で、今回はCassandraの内部構造のひとつ、Memtableについて。 Cassandraでの書き込み操作はまずディスク上のCommitLog(書き込み操作のログ)に対して行われ、それからメモリ上のMemtableと呼ばれる構造体に対して書き込まれます。Memtableの構造は以下のようになっていて、ColumnFamily毎に保持されています。Key の列の Token は書き込み要求時にデータを保持するノードを決める際に計算されるものです。 Memtable関連の設定について conf/storage-conf.xml にMemtable関連の設定項目があります。これらはMemtableがディスクにフラッシュされる(ディスク上のSSTableに非同期で書き込まれる)までの種々のしきい値を設定しています。 ・ MemtableThroughputInMB 総データ操作量のしきい値 デフォルトは64(MB)、ColumnFamily単位で設定される ・ MemtableOperationsInMillions 保持されるカラム数のしきい値 デフォルトは0.3(Millionsなので300,000個)、ColumnFamily単位で設定される ・ MemtableFlushAfterMinutes 時間のしきい値 ここで設定した時間が経ってもまだフラッシュされてない場合は強制的にフラッシュされる デフォルトは60(分)、プロダクション環境では1440などの大きな値の設定が推奨されている(storage-conf.xmlでのコメントより) メモリ不足でノードが落ちてしまわないように、ColumnFamilyの数とそれぞれのColumnFamilyのカラム数などからきちんとこれらのしきい値を設定しておく必要があります。 分散ストレージ周りは個人で検証環境を用意するのは大変なので、会社のデータセンターを使わせてもらって検証しています。社内導入も真剣に考えていきたいなと思っていますがなかなか難しそうです； ・関連記事 Cassandra Java Client Cassandra Thrift APIのConsistencyLevel Cassandraについて]]></description>
			<content:encoded><![CDATA[<p>引き続きCassandraについて調査中で、今回はCassandraの内部構造のひとつ、Memtableについて。</p>
<p>Cassandraでの書き込み操作はまずディスク上のCommitLog(書き込み操作のログ)に対して行われ、それからメモリ上のMemtableと呼ばれる構造体に対して書き込まれます。Memtableの構造は以下のようになっていて、ColumnFamily毎に保持されています。Key の列の Token は書き込み要求時にデータを保持するノードを決める際に計算されるものです。</p>
<p><a href="http://rest-term.com/wp-content/uploads/2010/05/memtable.png"><img src="http://rest-term.com/wp-content/uploads/2010/05/memtable.png" alt="" title="memtable" width="567" height="269" class="alignnone size-full wp-image-2789" /></a></p>
<h2 class="term">Memtable関連の設定について</h2>
<p>conf/storage-conf.xml にMemtable関連の設定項目があります。これらはMemtableがディスクにフラッシュされる(ディスク上のSSTableに非同期で書き込まれる)までの種々のしきい値を設定しています。</p>
<p>・ <strong>MemtableThroughputInMB</strong><br />
総データ操作量のしきい値<br />
デフォルトは64(MB)、ColumnFamily単位で設定される</p>
<p>・ <strong>MemtableOperationsInMillions</strong><br />
保持されるカラム数のしきい値<br />
デフォルトは0.3(Millionsなので300,000個)、ColumnFamily単位で設定される</p>
<p>・ <strong>MemtableFlushAfterMinutes</strong><br />
時間のしきい値<br />
ここで設定した時間が経ってもまだフラッシュされてない場合は強制的にフラッシュされる<br />
デフォルトは60(分)、プロダクション環境では1440などの大きな値の設定が推奨されている(storage-conf.xmlでのコメントより)</p>
<p>メモリ不足でノードが落ちてしまわないように、ColumnFamilyの数とそれぞれのColumnFamilyのカラム数などからきちんとこれらのしきい値を設定しておく必要があります。</p>
<p>分散ストレージ周りは個人で検証環境を用意するのは大変なので、会社のデータセンターを使わせてもらって検証しています。社内導入も真剣に考えていきたいなと思っていますがなかなか難しそうです；</p>
<p>・関連記事<br />
<a href="http://rest-term.com/archives/2784/" title=" Cassandra Java Client "> Cassandra Java Client </a><br />
<a href="http://rest-term.com/archives/2782/" title=" Cassandra Thrift APIのConsistencyLevel "> Cassandra Thrift APIのConsistencyLevel </a><br />
<a href="http://rest-term.com/archives/2775/" title=" Cassandraについて "> Cassandraについて </a></p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2788/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CSSの解釈について</title>
		<link>http://rest-term.com/archives/2786/</link>
		<comments>http://rest-term.com/archives/2786/#comments</comments>
		<pubDate>Wed, 05 May 2010 14:16:58 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2786</guid>
		<description><![CDATA[業務の合間に制作部の社内勉強会にちょこちょこ参加していろいろ学んだのでメモ。 ここではCSSの最適化について。 * ブラウザはCSSをどう解釈している？ ルールを照合するとき、右端のセレクタから調べ始めて、順に左のセレクタを調べていく。 ということは、 [css] #contents > li { font-weight: bold; } [/css] のようなルールの場合「contents という id を持つ要素を探して、その直接の子要素が li 要素かどうかを調べる」ではなく「すべての li 要素について、その直接の親要素が contents という id を持つかを調べる」となり高コストです。子孫セレクタの場合はさらに高くつき、 [css] #contents a { color: #0099ff; } [/css] のようなルールの場合「すべての a 要素について、contents という id を持つ祖先要素をツリー構造をさかのぼって探す」ということになります。子供セレクタであれば1つ上の階層のノードだけ調べれば済みますが、子孫セレクタの場合はさらにさかのぼって探索しなければなりません。Win IE6対応を無視してもいいなら、子孫セレクタから子供セレクタに置き換えた方がいいです。ただ、その子供セレクタも高コストには違いないので、それを1つの class に置き換えます。 [css] #contents > li > a { font-weight: bold; } [/css] [...]]]></description>
			<content:encoded><![CDATA[<p>業務の合間に制作部の社内勉強会にちょこちょこ参加していろいろ学んだのでメモ。<br />
ここではCSSの最適化について。</p>
<p>* <strong>ブラウザはCSSをどう解釈している？</strong><br />
ルールを照合するとき、右端のセレクタから調べ始めて、順に左のセレクタを調べていく。</p>
<p>ということは、<br />
[css]<br />
#contents > li { font-weight: bold; }<br />
[/css]<br />
のようなルールの場合「contents という id を持つ要素を探して、その直接の子要素が li 要素かどうかを調べる」ではなく「すべての li 要素について、その直接の親要素が contents という id を持つかを調べる」となり高コストです。子孫セレクタの場合はさらに高くつき、<br />
[css]<br />
#contents a { color: #0099ff; }<br />
[/css]<br />
のようなルールの場合「すべての a 要素について、contents という id を持つ祖先要素をツリー構造をさかのぼって探す」ということになります。子供セレクタであれば1つ上の階層のノードだけ調べれば済みますが、子孫セレクタの場合はさらにさかのぼって探索しなければなりません。Win IE6対応を無視してもいいなら、子孫セレクタから子供セレクタに置き換えた方がいいです。ただ、その子供セレクタも高コストには違いないので、それを1つの class に置き換えます。<br />
[css]<br />
#contents > li > a { font-weight: bold; }<br />
[/css]<br />
ではなく<br />
[css]<br />
.list-anchor { font-weight: bold; }<br />
[/css]<br />
のように要素と関連づけた名前で class を作ってスタイルを適用させることで、探索時間をさらに短くすることができます。</p>
<p>* <strong>ユニバーサルセレクタについて</strong><br />
[css]<br />
* { margin: 0; padding: 0; }<br />
[/css]<br />
一時期よく使われていたユニバーサルセレクタは最近では見かけなくなりました。社内の制作さんは、「パフォーマンスが悪くなる」という点よりも「ブラウザのデフォルトのスタイルを活かす」という点の方を重視しているみたいでしたが、ここまで述べてきた内容からパフォーマンスも相当悪くなるのは明らかです。その点について stevesouders.com さんが検証していました。<br />
<a href="http://stevesouders.com/efws/css-selectors/universal.php" title="CSS Selectors: Universal">CSS Selectors: Universal</a><br />
上述の子供セレクタや子孫セレクタによる読み込み時間の違いは小さなものですが、ユニバーサルセレクタを使用した場合はケタ違いに読み込みが遅くなっています。</p>
<p>* <strong>リフロー時間について</strong><br />
ブラウザがスタイルを適用し要素をレイアウトするのにかかる時間をリフロー時間と呼ぶそうです。スタイルの適用はページの読み込み時のみとは限りません。というのは、最近のWebサイトはJavascriptを多用していて、リッチな表現を行うためにDOM要素の style プロパティを頻繁に書き換えている例が多く見られます。<br />
[javascript]<br />
document.getElementById(&#8220;id&#8221;).style.property=&#8221;value&#8221;<br />
// 例<br />
document.getElementById(&#8220;contents&#8221;).style.fontSize = &#8220;larger&#8221;;</p>
<p>// 実際は上記のような処理がラップされたjQueryなどのライブラリを利用している場合が多い<br />
// 制作工数とパフォーマンスのバランスを考えて使う<br />
$(&#8220;#contents&#8221;).css(&#8220;border&#8221;, &#8220;1px solid #333333&#8243;);<br />
[/javascript]<br />
style プロパティを書き換えるとブラウザはその度にルールを照合しなおしています。もし、DOM要素が body などの多くの子孫を持つ要素の場合、効率の悪いセレクタがあるとページの反応が遅くなってしまいます。ページの読み込み時だけでなくWebアプリケーションがユーザと情報をやりとりしている間の動作に及ぶ影響にも注意することが重要です。</p>
<p>参加したのは新卒向けの勉強会だったので得られたのはこの程度の内容ですが、通常業務でも制作さんといっしょに仕事する機会ができたので、もう少し深い部分も聞いてみたいと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2786/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cassandra Java Client</title>
		<link>http://rest-term.com/archives/2784/</link>
		<comments>http://rest-term.com/archives/2784/#comments</comments>
		<pubDate>Mon, 03 May 2010 12:29:57 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2784</guid>
		<description><![CDATA[前回 Cassandra Thrift APIのConsistencyLevel と内容的に前後してしまいますが、Cassandra APIのテストコードを一応載せておきます。データ操作(取得/登録/削除)に関するAPIはひととおり使用してあるので、コードを見ればだいたいの使い方は理解できると思います。また、各APIのシグネチャはCassandraのホームディレクトリにjavadocディレクトリがあるのでそこで確認できます。 (org.apache.cassandra.thrift.CassandraServer を参照) 以下のコードは、例としてブログ記事をデータとして扱っています。 ・ColumnFamily は Entry ・entry* という key は title、category、tag の３つをcolumnを持つ [java] import java.util.*; import java.io.UnsupportedEncodingException; import org.apache.cassandra.thrift.*; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; import org.apache.thrift.TException; import org.apache.thrift.transport.TTransportException; public class TestClient { private static final String KEYSPACE = "Keyspace1"; private static final String COLUMN_FAMILY = "Entry"; [...]]]></description>
			<content:encoded><![CDATA[<p>前回 <a href="http://rest-term.com/archives/2782/" title=" Cassandra Thrift APIのConsistencyLevel "> Cassandra Thrift APIのConsistencyLevel </a>と内容的に前後してしまいますが、Cassandra APIのテストコードを一応載せておきます。データ操作(取得/登録/削除)に関するAPIはひととおり使用してあるので、コードを見ればだいたいの使い方は理解できると思います。また、各APIのシグネチャはCassandraのホームディレクトリにjavadocディレクトリがあるのでそこで確認できます。<br />
(<strong>org.apache.cassandra.thrift.CassandraServer</strong> を参照)</p>
<p>以下のコードは、例としてブログ記事をデータとして扱っています。<br />
・ColumnFamily は Entry<br />
・entry* という key は title、category、tag の３つをcolumnを持つ</p>
<pre>
[java]
import java.util.*;
import java.io.UnsupportedEncodingException;
import org.apache.cassandra.thrift.*;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.TException;
import org.apache.thrift.transport.TTransportException;

public class TestClient {
  private static final String KEYSPACE = "Keyspace1";
  private static final String COLUMN_FAMILY = "Entry";
  private TTransport transport = null;
  private Cassandra.Client client = null;
  TestClient() {
    client = getConnection();
  }
  private Cassandra.Client getConnection() {
    try {
      transport = new TSocket("localhost", 9160);
      TProtocol protocol = new TBinaryProtocol(transport);
      Cassandra.Client client = new Cassandra.Client(protocol);
      transport.open();
      return client;
    }catch(TTransportException e) {
      e.printStackTrace();
    }
    return null;
  }
  private void closeConnection() {
    try {
      transport.flush();
      transport.close();
    }catch(TTransportException e) {
      e.printStackTrace();
    }
  }
  private void selectEntry(String key) {
    try {
      SlicePredicate slicePredicate = new SlicePredicate();
      SliceRange sliceRange = new SliceRange();
      sliceRange.setStart(new byte[] {});
      sliceRange.setFinish(new byte[] {});
      slicePredicate.setSlice_range(sliceRange);
      ColumnParent columnParent = new ColumnParent(COLUMN_FAMILY);
      List<ColumnOrSuperColumn> results = client.get_slice(KEYSPACE, key, columnParent, slicePredicate, ConsistencyLevel.ONE);
      printData(key, results);
    }catch(Exception e) {
      e.printStackTrace();
    }
  }
  private void selectAllEntry() {
    try {
      KeyRange keyRange = new KeyRange();
      keyRange.setStart_key("");
      keyRange.setEnd_key("");
      SliceRange sliceRange = new SliceRange();
      sliceRange.setStart(new byte[] {});
      sliceRange.setFinish(new byte[] {});
      SlicePredicate slicePredicate = new SlicePredicate();
      slicePredicate.setSlice_range(sliceRange);
      ColumnParent columnParent = new ColumnParent(COLUMN_FAMILY);
      List<KeySlice> keySlices = client.get_range_slices(KEYSPACE, columnParent, slicePredicate, keyRange, ConsistencyLevel.ONE);
      for(KeySlice keySlice : keySlices) {
        printData(keySlice.getKey(), keySlice.getColumns());
      }
    }catch(Exception e) {
      e.printStackTrace();
    }
  }
  private void insertEntry(String key, Map<String, String> data) {
    try {
      Map<String, List<ColumnOrSuperColumn>> cfmap = new HashMap<String, List<ColumnOrSuperColumn>>();
      List<ColumnOrSuperColumn> columns = new ArrayList<ColumnOrSuperColumn>();
      Column column;
      ColumnOrSuperColumn columnOrSuperColumn;
      long timestamp = System.currentTimeMillis();
      for(Map.Entry<String, String> e : data.entrySet()) {
        column = new Column(e.getKey().getBytes("utf-8"), e.getValue().getBytes("utf-8"), timestamp);
        columnOrSuperColumn = new ColumnOrSuperColumn();
        columnOrSuperColumn.setColumn(column);
        columns.add(columnOrSuperColumn);
      }
      cfmap.put(COLUMN_FAMILY, columns);
      client.batch_insert(KEYSPACE, key, cfmap, ConsistencyLevel.ALL);
    }catch(Exception e) {
      e.printStackTrace();
    }
  }
  private void deleteEntry(String key) {
    try {
      ColumnPath columnPath = new ColumnPath(COLUMN_FAMILY);
      client.remove(KEYSPACE, key, columnPath, System.currentTimeMillis(), ConsistencyLevel.ALL);
    }catch(Exception e) {
      e.printStackTrace();
    }
  }
  private void updateEntry(String key, Map<String, String> data) {
    try {
      Map<String, Map<String, List<Mutation>>> mutationMap = new HashMap<String, Map<String, List<Mutation>>>();
      List<Mutation> mutations = new ArrayList<Mutation>();
      Column column;
      ColumnOrSuperColumn columnOrSuperColumn;
      Mutation mutation;
      long timestamp = System.currentTimeMillis();
      for(Map.Entry<String, String> e : data.entrySet()) {
        column = new Column(e.getKey().getBytes("utf-8"), e.getValue().getBytes("utf-8"), timestamp);
        columnOrSuperColumn = new ColumnOrSuperColumn();
        columnOrSuperColumn.setColumn(column);
        mutation = new Mutation();
        mutation.setColumn_or_supercolumn(columnOrSuperColumn);
        mutations.add(mutation);
      }
      Map<String, List<Mutation>> mutationsForColumnFamily = new HashMap<String, List<Mutation>>();
      mutationsForColumnFamily.put(COLUMN_FAMILY, mutations);
      mutationMap.put(key, mutationsForColumnFamily);
      client.batch_mutate(KEYSPACE, mutationMap, ConsistencyLevel.ALL);
    }catch(Exception e) {
      e.printStackTrace();
    }
  }
  private void printData(String key, List<ColumnOrSuperColumn> results) {
    try {
      System.out.println("Key: '" + key + "'");
      for(ColumnOrSuperColumn c : results) {
        if(c.getColumn() != null) {
          String name = new String(c.getColumn().getName(), "utf-8");
          String value = new String(c.getColumn().getValue(), "utf-8");
          long timestamp = c.getColumn().getTimestamp();
          System.out.println("  name: '" + name + "', value: '" + value + "', timestamp: " + timestamp);
        }
      }
    }catch(UnsupportedEncodingException e) {
      e.printStackTrace();
    }
  }
  /**
   * test cassandra api.
   */
  public static void main(String args[]) {
    TestClient c = new TestClient();
    // insert entry1
    Map<String, String> data = new HashMap<String, String>();
    data.put("title", "Cassandra Java Client");
    data.put("category", "tech/study");
    data.put("tag", "database");
    c.insertEntry("entry1", data);
    // insert entry2
    data = new HashMap<String, String>();
    data.put("title", "OpenCV 2.1 is out!");
    data.put("category", "tech/study");
    data.put("tag", "cv/im");
    c.insertEntry("entry2", data);
    // select entries
    System.out.println("select entries, using selectEntry()");
    c.selectEntry("entry1");
    c.selectEntry("entry2");
    // delete entry2
    System.out.println("delete entry2");
    c.deleteEntry("entry2");
    System.out.println("select entries, using selectEntry()");
    c.selectEntry("entry1");
    c.selectEntry("entry2");
    // update entry1
    System.out.println("update entry1: title, category");
    Map<String, String> updateData = new HashMap<String, String>();
    updateData.put("title", "change title");
    updateData.put("category", "change category");
    c.updateEntry("entry1", updateData);
    System.out.println("select entry1, using selectEntry()");
    c.selectEntry("entry1");
    // insert entry3
    c.insertEntry("entry3", data);
    // select all entries
    System.out.println("select all entries from Entry, using selectAllEntry()");
    c.selectAllEntry();
    c.closeConnection();
  }
}
[/java]
</pre>
<p>データ登録では <strong>Cassandra.Client.batch_insert</strong> を使って複数のcolumnを一度にwriteしてますが、<strong>Cassandra.Client.insert</strong> という単一のcolumnをwriteするメソッドもあります。writeするcolumnが複数ある場合、その数だけ insert を呼ぶより batch_insert で一度にwriteした方が高速です。 ただし、&#8221;Deprecated in 0.6 &#8211; use batch_mutate  instead&#8221;  とAPIリファレンスに書いてあるように、データ登録時も <strong>Cassandra.Client.batch_mutate</strong> の利用が推奨されているようです。</p>
<p>CassandraのクライアントはThriftを利用しているので多言語対応していますが、やはり個人的にはJavaから操作するのがいいかなと思います。プロトタイピングでは <a href="http://search.cpan.org/dist/Net-Cassandra/lib/Net/Cassandra.pm" title="Net::Cassandra">Net::Cassandra</a>(Perlの場合)などでさっと作って検証してから、Javaでじっくり書き直す感じになるでしょうか。</p>
<p>・関連記事<br />
<a href="http://rest-term.com/archives/2782/" title=" Cassandra Thrift APIのConsistencyLevel "> Cassandra Thrift APIのConsistencyLevel </a><br />
<a href="http://rest-term.com/archives/2775/" title=" Cassandraについて "> Cassandraについて </a></p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2784/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cassandra Thrift APIのConsistencyLevel</title>
		<link>http://rest-term.com/archives/2782/</link>
		<comments>http://rest-term.com/archives/2782/#comments</comments>
		<pubDate>Wed, 28 Apr 2010 13:08:07 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[database]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2782</guid>
		<description><![CDATA[前回に引き続きCassandraについて調査継続中で、今回はThrift APIの ConsistencyLevel について。以下のサイトの該当項目をざっくりと意訳した程度のメモです。 API06 &#8211; Cassandra Wiki Cassandra Thrift APIにおける ConsistencyLevel は、 storage-conf.xml で設定した &#60;ReplicationFactor&#62; (データの複製を保存するノード数)に基づいてread/writeの振る舞いを制御します。以下の条件が成り立つ場合は強い一貫性が得られ、常に最新データを参照できます。 if W + R &#62; ReplicationFactor (W: 更新操作を完了する前に更新通知を受け取る必要のあるレプリカの数、R: 読み込み操作でデータオブジェクトにアクセスしたとき, 取りにいく必要のあるレプリカの数) 一貫性よりも速度(遅延時間)の方が重要な場合は、上記の条件を満たさないような低いレベルを使えます。 Write Level Behavior ZERO 保証しない。バックグラウンドで非同期にwriteされる。 ANY 少なくともどこか一つのノードにwriteされたことを保証する。 ONE クライアントにレスポンスを返す前に、一つのノードのCommitLogとMemtableにwriteされたことを保証する。 QUORUM クライアントにレスポンスを返す前に、&#60;ReplicationFactor&#62; / 2 + 1 つのノード群にwriteされたことを保証する。 ALL クライアントにレスポンスを返す前に、&#60;ReplicationFactor&#62;つのノード群にwriteされたことを保証する。 Read Level Behavior ZERO サポートしない。 ANY サポートしない。 ONE 最初にレスポンスを返せるノードからレコードを返す。一貫性チェックはバックグラウンドのスレッドで常に行われている。これは最初のreadで古い値を取得したとしても、その後のreadでは正しい値を取得できることを意味する。(これは [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://rest-term.com/archives/2775/">前回</a>に引き続きCassandraについて調査継続中で、今回はThrift APIの <strong>ConsistencyLevel</strong> について。以下のサイトの該当項目をざっくりと意訳した程度のメモです。<br />
<a href="http://wiki.apache.org/cassandra/API06">API06 &#8211; Cassandra Wiki</a></p>
<p>Cassandra Thrift APIにおける ConsistencyLevel は、 <strong>storage-conf.xml</strong> で設定した <strong>&lt;ReplicationFactor&gt;</strong> (データの複製を保存するノード数)に基づいてread/writeの振る舞いを制御します。以下の条件が成り立つ場合は強い一貫性が得られ、常に最新データを参照できます。</p>
<pre>
if W + R &gt; ReplicationFactor
</pre>
<p>(W: 更新操作を完了する前に更新通知を受け取る必要のあるレプリカの数、R: 読み込み操作でデータオブジェクトにアクセスしたとき, 取りにいく必要のあるレプリカの数)<br />
一貫性よりも速度(遅延時間)の方が重要な場合は、上記の条件を満たさないような低いレベルを使えます。</p>
<p><strong>Write</strong></p>
<table class="entry">
<tr>
<td><strong>Level</strong></td>
<td><strong>Behavior</strong></td>
</tr>
<tr>
<td>ZERO</td>
<td>保証しない。バックグラウンドで非同期にwriteされる。</td>
</tr>
<tr>
<td>ANY</td>
<td>少なくともどこか一つのノードにwriteされたことを保証する。</td>
</tr>
<tr>
<td>ONE</td>
<td>クライアントにレスポンスを返す前に、一つのノードのCommitLogとMemtableにwriteされたことを保証する。</td>
</tr>
<tr>
<td>QUORUM</td>
<td>クライアントにレスポンスを返す前に、<strong>&lt;ReplicationFactor&gt; / 2 + 1 </strong>つのノード群にwriteされたことを保証する。</td>
</tr>
<tr>
<td>ALL</td>
<td>クライアントにレスポンスを返す前に、<strong>&lt;ReplicationFactor&gt;</strong>つのノード群にwriteされたことを保証する。</td>
</tr>
</table>
<p><strong>Read</strong></p>
<table class="entry">
<tr>
<td><strong>Level</strong></td>
<td><strong>Behavior</strong></td>
</tr>
<tr>
<td>ZERO</td>
<td>サポートしない。</td>
</tr>
<tr>
<td>ANY</td>
<td>サポートしない。</td>
</tr>
<tr>
<td>ONE</td>
<td>最初にレスポンスを返せるノードからレコードを返す。一貫性チェックはバックグラウンドのスレッドで常に行われている。これは最初のreadで古い値を取得したとしても、その後のreadでは正しい値を取得できることを意味する。(これは read repair と呼ばれる)</td>
</tr>
<tr>
<td>QUORUM</td>
<td>全ノードを探索し、過半数のレプリカからレスポンスを得た時点で最も新しいタイムスタンプのレコードを返す。残りのレプリカの一貫性チェックはバックグラウンドで行われる。</td>
</tr>
<tr>
<td>ALL</td>
<td>全ノードを探索し、全ノードからレスポンスを得た時点で最も新しいタイムスタンプのレコードを返す。</td>
</tr>
</table>
<p>この一貫性の設定はデフォルト値に頼らず、明示的にConsistencyLevelを指定するようにした方がいいです。</p>
<p>• 関連記事<br />
<a href="http://rest-term.com/archives/2775/"> Cassandraについて </a><br />
<a href="http://www.hyuki.com/yukiwiki/wiki.cgi?EventuallyConsistent" title="EventuallyConsistent - 結果整合性">EventuallyConsistent &#8211; 結果整合性</a></p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2782/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>perlのithreads</title>
		<link>http://rest-term.com/archives/2778/</link>
		<comments>http://rest-term.com/archives/2778/#comments</comments>
		<pubDate>Sun, 25 Apr 2010 09:37:37 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2778</guid>
		<description><![CDATA[業務とは離れたことをほんとは書きたいのですが、半日つぶしちゃったのでせっかくなのでメモ。 perlのスレッド(ithreads)について。 ithreadsはスレッド生成時にすべての変数をコピーし、Copy on Write※は行われません (C/C++から使えるpthreadsだとスタック以外のメモリ領域は暗黙的に共有され、コピーは行われない)。変数をスレッド間で共有したい場合は、宣言時にthreads::sharedのshared属性を明示的に付ける必要があります。ちなみに、C/C++でOpenMPを使う場合、共有したい変数にshared指示節を付けますが、これを省略すると変数は暗黙的に共有されます。 ※ Copy on Write 共有しているメモリ空間に更新が発生するときに初めてコピーが行われ、更新された箇所のみ親と子で別々の物理メモリ空間が割り当てられる。 • 例 [perl] #!/usr/bin/perl use strict; use warnings; use threads; use threads::shared; my $var : shared = 10; # $var をスレッド間で共有する my $th = threads->new( sub { while(1) { printf("[TID: %d] %d\n", threads->self->tid, $var); $var *= 2; sleep 1; } } ); while(1) { [...]]]></description>
			<content:encoded><![CDATA[<p>業務とは離れたことをほんとは書きたいのですが、半日つぶしちゃったのでせっかくなのでメモ。<br />
perlのスレッド(ithreads)について。</p>
<p>ithreadsはスレッド生成時にすべての変数をコピーし、Copy on Write※は行われません (C/C++から使えるpthreadsだとスタック以外のメモリ領域は<strong>暗黙的</strong>に共有され、コピーは行われない)。変数をスレッド間で共有したい場合は、宣言時にthreads::sharedのshared属性を<strong>明示的</strong>に付ける必要があります。ちなみに、C/C++でOpenMPを使う場合、共有したい変数にshared指示節を付けますが、これを省略すると変数は暗黙的に共有されます。</p>
<p>※ Copy on Write<br />
共有しているメモリ空間に更新が発生するときに初めてコピーが行われ、更新された箇所のみ親と子で別々の物理メモリ空間が割り当てられる。</p>
<p>• 例</p>
<pre>[perl]
#!/usr/bin/perl

use strict;
use warnings;
use threads;
use threads::shared;

my $var : shared = 10;  # $var をスレッド間で共有する

my $th = threads->new(
  sub {
    while(1) {
      printf("[TID: %d] %d\n", threads->self->tid, $var);
      $var *= 2;
      sleep 1;
    }
  }
);

while(1) {
  printf("[TID: %d] %d\n", threads->self->tid, $var);
  $var += 1;
  sleep 1;
}

$th->join;

# 結果
# [TID: 0] 10
# [TID: 1] 11
# [TID: 0] 22
# [TID: 1] 23
# [TID: 0] 46
# [TID: 1] 47
# [TID: 0] 94
#  ...
[/perl]</pre>
<p>ithreadsは前述のようにスレッド生成時にすべての変数のコピーを行うのでコストが高いです。なので、もしこれでサーバを書く場合はper-threadな設計は止めた方がいいということですね。</p>
<p><strong>cond_signal() / cond_wait()</strong><br />
スレッドの同期に使うcond_wait()/cond_signal()の使い方。</p>
<p>・ 例<br />
produce側ではまずキューをロック、そこに数値をpushしてcond_signal()を呼び出しています。このcond_signal()は別スレッドにキューを操作したことを知らせます。consume側ではまずキューをロック、キューが空の時はcond_wait()でロックを解放して待ち状態になって休み、キューに値が入っている時はそこから値をpopして計算後、出力を行っています。</p>
<pre>[perl]
#!/usr/bin/perl

use strict;
use warnings;
use threads;
use threads::shared;

my @queue : shared;

threads->new(\&#038;produce);
threads->new(\&#038;consume);

$_->join for threads->list;

sub produce {
  while(1) {
    {
      lock @queue;
      push @queue, int(rand(10));
      cond_signal(@queue);
    }
    sleep 1;
  }
}

sub consume {
  while(1) {
    lock @queue;
    while(@queue == 0) {
      cond_wait(@queue);
    }
    my $i = pop @queue;
    printf "$i * $i = %d\n", $i * $i;
  }
}

# 結果
# 0 * 0 = 0
# 1 * 1 = 1
# 5 * 5 = 25
# 3 * 3 = 9
#  ...
[/perl]</pre>
<p>僕自身は業務でithreadsを使ったことはないのですが、他の人が書いたコードを読む時の前提知識としてメモしておきました。</p>
<p>• 参考<br />
<a href="http://www.donzoko.net/doc/memo/perlithreads.html">Perlのithreads（iスレッド）に関するメモ</a><br />
WEB+DB PRESS vol.42 (エントリ内のサンプルコード)</p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2778/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cassandraについて</title>
		<link>http://rest-term.com/archives/2775/</link>
		<comments>http://rest-term.com/archives/2775/#comments</comments>
		<pubDate>Sun, 18 Apr 2010 10:32:00 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2775</guid>
		<description><![CDATA[分散ストレージのCassandraについて調査中。 CassandraはNoSQL(Not only SQL)データベースの一つ。TwitterやDiggがMySQLからCassandraに移行したことでも有名です。公式サイトのOverviewにもあるように特徴は以下のようになっています。 特徴 Proven (証明) Facebook, Twitter, Diggなど多くのサービスでの利用実績 Fault Tolerant (耐障害性) レプリケーションによりサーバがダウンしても自動復帰可能 Decentralized (分散) クラスタにより単一障害点がない Eventually Consistent (結果整合性) 楽観的なデータ一貫性を提供 Rich Data Model (高度なデータモデル) 単純なKVSを超える機能を提供 Highly Available (高可用性) 一貫性のレベルを設定可能 分散ストレージを扱う上で、Eventually Consistent (結果整合性) は大切な概念なのでしっかり抑えておく必要があります。(参考：EventuallyConsistent &#8211; 結果整合性) また、Cassandraはmemcachedのような従来のKVSよりリッチなデータ構造を提供していて、従来のKVSでは1つのkeyに対して1つのvalueを保持しますが、Cassandraではそのkeyの部分を4次元、もしくは5次元で扱うことができます。READMEに例が載っています。 set Keyspace1.Standard2['jsmith']['first'] = 'John' \ \ \ \ \ \ \ \_ key \ \_ value \ \ [...]]]></description>
			<content:encoded><![CDATA[<p>分散ストレージの<a href="http://cassandra.apache.org/">Cassandra</a>について調査中。</p>
<p>CassandraはNoSQL(Not only SQL)データベースの一つ。TwitterやDiggがMySQLからCassandraに移行したことでも有名です。公式サイトのOverviewにもあるように特徴は以下のようになっています。</p>
<h2 class="term">特徴</h2>
<table class="entry">
<tr>
<td>Proven (証明)</td>
<td>Facebook, Twitter, Diggなど多くのサービスでの利用実績</td>
</tr>
<tr>
<td>Fault Tolerant (耐障害性)</td>
<td>レプリケーションによりサーバがダウンしても自動復帰可能</td>
</tr>
<tr>
<td>Decentralized (分散)</td>
<td>クラスタにより単一障害点がない</td>
</tr>
<tr>
<td>Eventually Consistent (結果整合性)</td>
<td>楽観的なデータ一貫性を提供</td>
</tr>
<tr>
<td>Rich Data Model (高度なデータモデル)</td>
<td>単純なKVSを超える機能を提供</td>
</tr>
<tr>
<td>Highly Available (高可用性)</td>
<td>一貫性のレベルを設定可能</td>
</tr>
</table>
<p>分散ストレージを扱う上で、<strong>Eventually Consistent</strong> (結果整合性) は大切な概念なのでしっかり抑えておく必要があります。(参考：<a href="http://www.hyuki.com/yukiwiki/wiki.cgi?EventuallyConsistent" title="EventuallyConsistent - 結果整合性">EventuallyConsistent &#8211; 結果整合性</a>)</p>
<p>また、Cassandraはmemcachedのような従来のKVSよりリッチなデータ構造を提供していて、従来のKVSでは1つのkeyに対して1つのvalueを保持しますが、Cassandraではそのkeyの部分を4次元、もしくは5次元で扱うことができます。READMEに例が載っています。</p>
<pre>
  set Keyspace1.Standard2['jsmith']['first'] = 'John'
       \            \         \        \          \
        \            \         \_ key   \          \_ value
         \            \                  \_ column
          \_ keyspace  \_ column family

Data stored in Cassandra is associated with a column family (Standard2),
which in turn is associated with a keyspace (Keyspace1). In the example
above, we set the value 'John' in the 'first' column for key 'jsmith'.
</pre>
<p>Cassanndraの構造を図にしてみると以下のようになります。<br />
<img src="http://rest-term.com/wp-content/uploads/2010/04/cassandra.png" alt="" title="cassandra" width="512" height="272" class="alignnone size-full wp-image-2781" /><br />
RDBに置き換えると、Keyspaceがデータベース、ColumnFamilyがテーブル、keyが主キー、columnがテーブルのカラムにそれぞれ対応しているイメージです。5次元の場合はSuperColumn(columnのリスト)という次元が追加されます。columnはCassandraにおけるデータの最小単位で以下のような構造。nameがcolumnの名前、valueが値でその他にタイムスタンプも入っています。</p>
<pre>
{
  "name": "site",
  "value": "rest-term",
  "timestamp":  1271591729517000
}
</pre>
<p><strong>インストール</strong><br />
CassandraはJavaで書かれています。(JDK 1.6以降が必要)</p>
<p>• 確認</p>
<pre>
$ java -version
java version "1.6.0_17"
Java(TM) SE Runtime Environment (build 1.6.0_17-b04-248-10M3025)
Java HotSpot(TM) 64-Bit Server VM (build 14.3-b01-101, mixed mode)
</pre>
<p>以下からビルド済みバイナリを入手して任意の場所に置きます。<br />
<a href="http://cassandra.apache.org/download/">The Apache Cassandra Project</a><br />
ログとデータベースを保存するディレクトリを作成し、パーミッションを変更。</p>
<pre>
$ sudo mkdir -p /var/log/cassandra
$ sudo chown -R `whoami` /var/log/cassandra
$ sudo mkdir -p /var/lib/cassandra
$ sudo chown -R `whoami` /var/lib/cassandra
</pre>
<p><strong>起動、接続確認</strong><br />
フォアグラウンドで起動</p>
<pre>
$ bin/cassandra -f
</pre>
<p><strong>データ操作</strong><br />
コマンドラインクライアント cassandra-cli を利用<br />
 (&#8216;Test Cluster&#8217;で接続、デフォルトポートは9160)</p>
<pre>
$  bin/cassandra-cli --host localhost --port 9160
Connected to: "Test Cluster" on localhost/9160
Welcome to cassandra CLI.

cassandra> show cluster name
Test Cluster
cassandra> show keyspaces
Keyspace1
system
cassandra> set Keyspace1.Standard1['rt']['name'] = 'wellflat'
Value inserted.
cassandra> set Keyspace1.Standard1['rt']['age'] = '25'
Value inserted.
cassandra> set Keyspace1.Standard1['rt']['site'] = 'rest-term'
Value inserted.
cassandra> get Keyspace1.Standard1['rt']
=> (column=73697465, value=rest-term, timestamp=1271591793931000)
=> (column=6e616d65, value=wellflat, timestamp=1271591729517000)
=> (column=616765, value=25, timestamp=1271591787205000)
Returned 3 results.
cassandra> del Keyspace1.Standard1['rt']['site']
column removed.
cassandra> get Keyspace1.Standard1['rt']
=> (column=6e616d65, value=wellflat, timestamp=1271591729517000)
=> (column=616765, value=25, timestamp=1271591787205000)
Returned 2 results.
</pre>
<p>データの登録/取得/削除の操作が直感的でわかりやすいですね。</p>
<pre>get Keyspace1.Standard1['rt']</pre>
<p>で複数のカラムのvalueが取得できているところも単純なKVSとの違いです。</p>
<p>Cassandraの設定ファイルは<strong>conf/storage-conf.xml</strong> で、ここでKeyspaceやColumnFamily、ポート番号などを指定します。MySQLだとコマンドでtableを追加したりできますが、Cassandraの場合は起動前にこのファイルで追加することになります。</p>
<p><strong>Perlクライアントの利用</strong><br />
ここではCPANの<a href="http://search.cpan.org/~teodor/Net-Cassandra-Easy-0.12/lib/Net/Cassandra/Easy.pm">Net::Cassandra::Easy</a>モジュールを使います。<br />
(<a href="http://search.cpan.org/dist/Net-Cassandra/lib/Net/Cassandra.pm">Net::Cassandra</a> モジュールというのもあります)</p>
<pre>[perl]
#!/usr/bin/perl

use strict;
use warnings;
use Net::Cassandra::Easy;
use Data::Dumper;

eval {
  my $client = Net::Cassandra::Easy->new(
    server => 'localhost',
    port => 9160,
    keyspace => 'Keyspace1');
  $client->connect();
  my $key = 'rt';
# get
  my $result = $client->get([$key],
                            family => 'Standard1',
                            byname => [qw/name age site/]);
  print Dumper($result);
# insert
  $client->mutate([$key],
                  family => 'Standard1',
                  insertions => { 'site' => 'rest-term' });
# get
  $result = $client->get([$key],
                         family => 'Standard1',
                         byname => [qw/name age site/]);
  print Dumper($result);
};
die Dumper($@) if $@;
[/perl]</pre>
<p>• 結果</p>
<pre>
$VAR1 = {
          'rt' => {
                    'Standard1' => {
                                     'name' => 'wellflat',
                                     'age' => '25'
                                   }
                  }
        };
$VAR1 = {
          'rt' => {
                    'Standard1' => {
                                     'site' => 'rest-term',
                                     'name' => 'wellflat',
                                     'age' => '25'
                                   }
                  }
        };
</pre>
<p>なかなか良いんではないでしょうか。Thriftで通信できるので他の言語からでも簡単に使えそうです。引き続き調査を進めたいと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2775/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>livedoor reader ..?</title>
		<link>http://rest-term.com/archives/2770/</link>
		<comments>http://rest-term.com/archives/2770/#comments</comments>
		<pubDate>Sun, 04 Apr 2010 08:05:21 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[nonsorted]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2770</guid>
		<description><![CDATA[なにが起きたのかわからない。。 livedoor reader を普段使っていないので全く気付かなかったんですが、いったい年明けに何が起こったのか。。 参考：[TopHatenar] FeedBurnerの管理ページでは数字の大きな変化は特にないようですが、 livedoor reader 上だとなんかリセット(? されてます。 心配なのはこのブログの記事がLDRユーザーの人にちゃんと通知されてるのかどうか。 この記事自体もそれを確認するためのテスト記事です。 以上、よろしくおねがいします。]]></description>
			<content:encoded><![CDATA[<p>なにが起きたのかわからない。。<br />
<img src="http://rest-term.com/wp-content/uploads/2010/04/rest-term.com_.htm.jpg" alt="" title="rest-term.com.htm" width="364" height="300" class="alignnone size-full wp-image-2771" /></p>
<p>livedoor reader を普段使っていないので全く気付かなかったんですが、いったい年明けに何が起こったのか。。<br />
参考：<a href="http://tophatenar.com/entry/145786/Rest+Term" title="[TopHatenar]">[TopHatenar]</a></p>
<p>FeedBurnerの管理ページでは数字の大きな変化は特にないようですが、<br />
livedoor reader 上だとなんかリセット(? されてます。<br />
心配なのはこのブログの記事がLDRユーザーの人にちゃんと通知されてるのかどうか。</p>
<p>この記事自体もそれを確認するためのテスト記事です。<br />
以上、よろしくおねがいします。</p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2770/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>mx.rpc.http.HTTPServiceってなに？</title>
		<link>http://rest-term.com/archives/2740/</link>
		<comments>http://rest-term.com/archives/2740/#comments</comments>
		<pubDate>Sun, 28 Mar 2010 10:32:41 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[actionscript]]></category>
		<category><![CDATA[flex]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2740</guid>
		<description><![CDATA[このクラスの存在を初めて知りました。 そもそも mx.* パッケージを真面目に調べたことがないから； 今までREST APIなどをActionScriptから利用するときは、URLLoaderとかURLRequestとかURLVariablesとかよく考えると不思議な名前のクラスを使っていましたが、HTTPServiceを使うとちょっと楽です。シンプルになります。 URLLoader.load(URLRequest) っていうインタフェースがどうもしっくりこないので； 以下、Flex 4での利用例。 ・テスト用 mxml emacsでmxmlを書くのがツライので極力短くしてます。が、マネしない方がいいかと。 mxmlの書き方はちゃんと公式のサンプルを参考に。 [xml] [/xml] ・HTTPTest.as [as] package { import spark.components.Application; // テスト用クラス // Yahoo!ブログ検索APIを利用する public class HTTPTest extends Application { namespace ns = "urn:yahoo:jp:blogsearch:article"; use namespace ns; public function HTTPTest() { var http:HTTP = new HTTP("http://search.yahooapis.jp/BlogSearchService/V1/blogSearch", {appid:"your AppID here..", query:"apple"}, "GET"); http.addEventListener(HTTP.SUCCESS, function():void [...]]]></description>
			<content:encoded><![CDATA[<p>このクラスの存在を初めて知りました。<br />
そもそも mx.* パッケージを真面目に調べたことがないから；</p>
<p>今までREST APIなどをActionScriptから利用するときは、URLLoaderとかURLRequestとかURLVariablesとかよく考えると不思議な名前のクラスを使っていましたが、HTTPServiceを使うとちょっと楽です。シンプルになります。<br />
URLLoader.load(URLRequest) っていうインタフェースがどうもしっくりこないので；</p>
<p>以下、Flex 4での利用例。<br />
<strong>・テスト用 mxml</strong><br />
emacsでmxmlを書くのがツライので極力短くしてます。が、マネしない方がいいかと。<br />
mxmlの書き方はちゃんと公式のサンプルを参考に。</p>
<pre>[xml]
<?xml version="1.0" encoding="utf-8"?>
<local:HTTPTest xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:local="*" />
[/xml]</pre>
<p><strong>・HTTPTest.as</strong></p>
<pre>[as]
package {
  import spark.components.Application;
  // テスト用クラス
  // Yahoo!ブログ検索APIを利用する
  public class HTTPTest extends Application {
    namespace ns = "urn:yahoo:jp:blogsearch:article";
    use namespace ns;
    public function HTTPTest() {
      var http:HTTP = new HTTP("http://search.yahooapis.jp/BlogSearchService/V1/blogSearch", {appid:"your AppID here..", query:"apple"}, "GET");
      http.addEventListener(HTTP.SUCCESS, function():void {trace(http.response);}, false, 0, true);
      http.addEventListener(HTTP.CLIENT_ERROR, function():void {trace("CLIENT_ERROR: status " + http.statusCode);}, false, 0, true);
      http.addEventListener(HTTP.SERVER_ERROR, function():void {trace("SERVER_ERROR: status " + http.statusCode);}, false, 0, true);
    }
  }
}

// HTTPServiceのwrapper
import mx.rpc.events.*;
import mx.rpc.http.HTTPService;
import flash.events.*;

class HTTP extends EventDispatcher {
  public static const SUCCESS:String = "success";
  public static const CLIENT_ERROR:String = "client_error";
  public static const SERVER_ERROR:String = "server_error";
  private var service:HTTPService;
  private var _messageBody:XML;
  private var _statusCode:int;

  public function HTTP(url:String, requestParam:Object, method:String) {
    service = new HTTPService();
    service.url = url;
    service.method = method;
    service.resultFormat = "xml";
    service.send(requestParam);
    service.addEventListener(ResultEvent.RESULT, function(e:ResultEvent):void {
      _statusCode = e.statusCode;
      _messageBody = new XML(e.result);
      dispatchEvent(new Event(SUCCESS));
    }, false, 0, true);
    service.addEventListener(FaultEvent.FAULT, function(e:FaultEvent):void {
      _statusCode = e.statusCode;
      if(_statusCode.toString().charAt(0) == "4") {
        dispatchEvent(new ErrorEvent(CLIENT_ERROR));
      }else if(_statusCode.toString().charAt(0) == "5") {
        dispatchEvent(new ErrorEvent(SERVER_ERROR));
      }
    }, false, 0, true);
  }
  public function get response():XML {
    return _messageBody;
  }
  public function get statusCode():int {
    return _statusCode;
  }
}
[/as]</pre>
<p>GETの濫用を避けるためにHTTPメソッドはインタフェースで明示した方がいいかと。<br />
RESTを利用する場合はHTTPステータスコードを意識することも重要です。</p>
<p>あとぜんぜん関係ないですけど、昨日の夜友達と<a href="http://www.roppongiartnight.com/">六本木アートナイト</a>に行ってきました。<br />
Art Lover だけでなくいろんな人が訪れていて大きなお祭りといった感じ。<br />
まるで別世界。<br />
感性を芯から刺激されました。</p>
<p><a href="http://rest-term.com/wp-content/uploads/2010/03/rat.jpg"><img src="http://rest-term.com/wp-content/uploads/2010/03/rat-168x300.jpg" alt="" title="rat" width="168" height="300" class="alignnone size-medium wp-image-2741" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2740/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML5の勉強</title>
		<link>http://rest-term.com/archives/2555/</link>
		<comments>http://rest-term.com/archives/2555/#comments</comments>
		<pubDate>Sat, 20 Mar 2010 16:53:14 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2555</guid>
		<description><![CDATA[HTML5::canvas test (Firefox3.5, Safari4でのみ動作確認しています) 先日の社内コンペでHTML5を使ったすごいデモを出してきたチームがあったので、 僕もそれに刺激を受けていろいろ調べています。 以前Flashで作ったものをHTML5のcanvas要素を使って作り直したりしながら勉強。 簡単な画像処理なんかもできそうなので引き続き調べていきたいと思います。 [2010/03/21 追記] ソースコードを大幅に書き換えました。 ネイティブのJavascriptでしっかりOOPできるようになりたいな。精進します。 ・クライアント [javascript] var heart = new Heart(document.getElementById('Canvas'), 8); heart.play(50, 0.03); // time, angle [/javascript] ・heart.js [javascript] var Heart = function(canvas, n) { this.initialize.apply(this, arguments); }; Heart.prototype = { initialize : function(canvas, n) { if(canvas == undefined &#124;&#124; canvas == null) return ; this.context [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://rest-term.com/contents/other/html5/canvas.html"><img src="http://rest-term.com/wp-content/uploads/2009/11/html5_canvas.png" alt="html5_canvas" title="html5_canvas" width="370" height="239" class="alignnone size-full wp-image-2556" /><br />
HTML5::canvas test</a> (Firefox3.5, Safari4でのみ動作確認しています)</p>
<p>先日の社内コンペでHTML5を使ったすごいデモを出してきたチームがあったので、<br />
僕もそれに刺激を受けていろいろ調べています。<br />
以前Flashで作ったものをHTML5のcanvas要素を使って作り直したりしながら勉強。<br />
簡単な画像処理なんかもできそうなので引き続き調べていきたいと思います。</p>
<p><strong>[2010/03/21 追記]</strong><br />
ソースコードを大幅に書き換えました。<br />
ネイティブのJavascriptでしっかりOOPできるようになりたいな。精進します。</p>
<p>・クライアント</p>
<pre>[javascript]
var heart = new Heart(document.getElementById('Canvas'), 8);
heart.play(50, 0.03);  // time, angle
[/javascript]</pre>
<p>・<a href="http://rest-term.com/contents/other/html5/libs/js/heart.js" title="heart.js">heart.js</a></p>
<pre>[javascript]
var Heart = function(canvas, n) {
  this.initialize.apply(this, arguments);
};

Heart.prototype = {
  initialize : function(canvas, n) {
    if(canvas == undefined || canvas == null) return ;
    this.context = canvas.getContext('2d');
    this.WIDTH = canvas.width;
    this.HEIGHT = canvas.height;
    this.SCALE = 25;
    this.FOV = 250;
    this.points = [];
    this.numPoints = 0;
    this.isPlay = false;
    this.setStyle(this.context.createLinearGradient(0, 0, 0, 300));
    this.setPoints(n);
  },
  setStyle : function(grad) {
    grad.addColorStop(0, 'rgb(255, 255, 255)');
    grad.addColorStop(0.7, 'rgb(196, 196, 196)');
    grad.addColorStop(0.8, 'rgb(160, 160, 160)');
    grad.addColorStop(0.9, 'rgb(128, 128, 128)');
    grad.addColorStop(1, 'rgb(96, 96, 96)');
    this.context.fillStyle = grad;
    this.context.strokeStyle = 'rgb(255, 0, 160)';
  },
  setPoints : function(num) {
    var r = 0.0;
    var theta = 0.0;
    var z = 0.0;
    var n = 0;
    for(i=-Math.PI*num; i<=Math.PI*num; i++) {
      for(j=-num; j<=num; j++) {
        theta = i/num;
        z = j/num;
        r = 4*Math.sqrt(1 - z*z)*Math.pow(Math.sin(Math.abs(theta)), Math.abs(theta));
        point = [(this.SCALE*r*Math.sin(theta)), (this.SCALE*r*Math.cos(theta)), (this.SCALE*z)];
        this.points.push(point);
        n++;
      }
    }
    this.numPoints = n;
  },
  play : function(t, angle) {
    var self = this;
    if(!this.isPlay) {
      this.timerID = setInterval(function(){self.render(angle);}, t);
      this.isPlay = true;
    }
  },
  stop : function() {
    if(this.isPlay) {
      clearInterval(this.timerID);
      this.isPlay = false;
    }
  },
  render : function(angle) {
    this.context.fillRect(0, 0, this.WIDTH, this.HEIGHT);
    for(i=0; i
<this.numPoints; i++)	{
      this.rotateY(this.points[i], angle);
      this.draw(this.points[i]);
    }
  },
  draw : function(point3d) {
    var scale = this.FOV/(this.FOV + point3d[2]);
    var x = (point3d[0]*scale) + this.WIDTH/2;
    var y = (point3d[1]*scale) + this.HEIGHT/2;
    this.context.lineWidth= scale*2;
    this.context.beginPath();
    this.context.moveTo(x, y);
    this.context.lineTo(x + scale, y);
    this.context.stroke();
  },
  rotateY : function(point3d, angle) {
    var x = point3d[0];
    var z = point3d[2];
    var c = Math.cos(angle);
    var s = Math.sin(angle);
    var tempZ = z;
    var tempX = x;
    x = tempX*c + tempZ*s;
    z = tempZ*c - tempX*s;
    point3d[0] = x;
    point3d[2] = z;
  }
}
[/javascript]</pre>
<p>・関連記事<br />
<a href="http://rest-term.com/archives/2685/" title=" HTML5でSymmetric Nearest Neighbor "> HTML5でSymmetric Nearest Neighbor </a><br />
<a href="http://rest-term.com/archives/2566/" title=" HTML5でConvolutionFilter "> HTML5でConvolutionFilter </a></p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2555/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tech Note「OpenMP」加筆</title>
		<link>http://rest-term.com/archives/2716/</link>
		<comments>http://rest-term.com/archives/2716/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 14:13:40 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2716</guid>
		<description><![CDATA[Tech Note で OpenMP の加筆を再開しました。 情報量がもう少し増えてきたら、ページを分割して見やすく整理しようと思ってます。 PThreadsと比べるとOpenMPは使うだけなら楽です。 ただ、マルチスレッドプログラミング一般の知識を持たずに使ってもあまり効果は出ないでしょう。 それどころか危険なコードに化けてしまう可能性の方が高いです。。 基礎は大事ですね。]]></description>
			<content:encoded><![CDATA[<p><a href="http://rest-term.com/contents/other/technote/index.php/Top" title="Top - Tech Note">Tech Note</a> で <strong>OpenMP</strong> の加筆を再開しました。<br />
情報量がもう少し増えてきたら、ページを分割して見やすく整理しようと思ってます。</p>
<p>PThreadsと比べるとOpenMPは使うだけなら楽です。<br />
ただ、マルチスレッドプログラミング一般の知識を持たずに使ってもあまり効果は出ないでしょう。<br />
それどころか危険なコードに化けてしまう可能性の方が高いです。。<br />
基礎は大事ですね。</p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2716/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTML5でSymmetric Nearest Neighbor</title>
		<link>http://rest-term.com/archives/2685/</link>
		<comments>http://rest-term.com/archives/2685/#comments</comments>
		<pubDate>Sat, 20 Feb 2010 17:19:35 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[cv/im]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2685</guid>
		<description><![CDATA[久しぶりの投稿； Demo: HTML5 Image Processing (Symmetric Nearest Neighbor) (Firefox3.5とSafari4で動作確認しています) HTML5でConvolutionFilterに続いて、簡単な画像処理を試してみます。 以前、ActionScriptで書いたSymmetric Nearest NeighborをJavaScriptで。 半径を大きくするとそれなりに絵画っぽくなってくれますが、やはり重いです； ・クライアント [javascript] var context = document.getElementById(&#8216;Canvas&#8217;).getContext(&#8217;2d&#8217;); var bmp = new Bitmap(&#8216;sample.jpg&#8217;, context); var radius = 3; bmp.applyFilter(new SNNFilter(radius)); [/javascript] bitmap.js (関係ある箇所だけ抜粋) [javascript] var Class = { create : function() { var properties = arguments[0]; function self() { this.initialize.apply(this, arguments); } for(var [...]]]></description>
			<content:encoded><![CDATA[<p>久しぶりの投稿；</p>
<p><img src="http://rest-term.com/wp-content/uploads/2010/02/snn.jpg" alt="" title="snn" width="550" height="198" class="alignnone size-full wp-image-2708" /></p>
<p>Demo: <a href="http://rest-term.com/contents/other/html5/snn.html" title="HTML5 Image Processing (Symmetric Nearest Neighbor)">HTML5 Image Processing (Symmetric Nearest Neighbor)</a><br />
(Firefox3.5とSafari4で動作確認しています)</p>
<p><a href="http://rest-term.com/archives/2566/" title="HTML5でConvolutionFilter">HTML5でConvolutionFilter</a>に続いて、簡単な画像処理を試してみます。<br />
以前、ActionScriptで書いた<a href="http://rest-term.com/archives/2103/" title="Symmetric Nearest Neighbor « Rest Term">Symmetric Nearest Neighbor</a>をJavaScriptで。<br />
半径を大きくするとそれなりに絵画っぽくなってくれますが、やはり重いです；</p>
<p>・クライアント<br />
[javascript]<br />
var context = document.getElementById(&#8216;Canvas&#8217;).getContext(&#8217;2d&#8217;);<br />
var bmp = new Bitmap(&#8216;sample.jpg&#8217;, context);<br />
var radius = 3;<br />
bmp.applyFilter(new SNNFilter(radius));<br />
[/javascript]</p>
<p><a href="http://rest-term.com/contents/other/html5/libs/js/bitmap.js" title="bitmap.js">bitmap.js</a><br />
(関係ある箇所だけ抜粋)<br />
[javascript]</p>
<p>var Class = {<br />
  create : function() {<br />
    var properties = arguments[0];<br />
    function self() {<br />
      this.initialize.apply(this, arguments);<br />
    }<br />
    for(var i in properties) {<br />
      self.prototype[i] = properties[i];<br />
    }<br />
    if(!self.prototype.initialize) {<br />
      self.prototype.initialize = function() {};<br />
    }<br />
    return self;<br />
  }<br />
};</p>
<p>var Bitmap = Class.create({<br />
  initialize : function(source, context) {<br />
    this.bitmapData = new Image();<br />
    this.bitmapData.src = source;<br />
    this.context = context;<br />
    this.bitmapData.addEventListener(&#8216;error&#8217;,<br />
                                     function() { alert(&#8220;can&#8217;t load image&#8221;); },<br />
                                     false);<br />
  },<br />
  applyFilter : function(filter) {<br />
    try {<br />
      if(this.bitmapData.complete) {<br />
        this.context.drawImage(this.bitmapData, 0, 0);<br />
        var w = this.bitmapData.width, h = this.bitmapData.height;<br />
        var src = this.context.getImageData(0, 0, w, h);<br />
        var dst = this.context.createImageData(w, h);<br />
        filter.apply(src, dst);<br />
        this.context.putImageData(dst, 0, 0);<br />
      }else {<br />
        throw new Error(&#8220;load image incomplete&#8221;);<br />
      }<br />
    }catch(e) {<br />
      throw e;<br />
    }<br />
  }<br />
});</p>
<p>var SNNFilter = Class.create({<br />
  initialize : function(radius) {<br />
    this.radius = radius;<br />
  },<br />
  apply : function(src, dst) {<br />
    var w = src.width, h = src.height;<br />
    var srcData = src.data;<br />
    var dstData = dst.data;<br />
    var sumR, sumG, sumB;<br />
    var rc, gc, bc, r1, g1, b1, r2, g2, b2;<br />
    var cnt = 0;<br />
    var xyPos, uvPos;</p>
<p>    for(var y=0;y<h;++y) {<br />
      for(var x=0;x<w;++x) {<br />
        xyPos = (w*y + x) << 2;<br />
        sumR = 0, sumG = 0, sumB = 0;<br />
        cnt = 0;<br />
        rc = srcData[xyPos];<br />
        gc = srcData[xyPos + 1];<br />
        bc = srcData[xyPos + 2];<br />
        for(var v=-this.radius;v<=this.radius;++v) {<br />
          for(var u=-this.radius;u<=this.radius;++u,++cnt) {<br />
            uvPos = (w*v + u) << 2;<br />
            try {<br />
              r1 = srcData[xyPos + uvPos];<br />
              g1 = srcData[xyPos + uvPos + 1];<br />
              b1 = srcData[xyPos + uvPos + 2];<br />
              r2 = srcData[xyPos - uvPos];<br />
              g2 = srcData[xyPos - uvPos + 1];<br />
              b2 = srcData[xyPos - uvPos + 2];<br />
            }catch(e) {<br />
              break;<br />
            }<br />
            if(this.delta.apply(this, [rc, gc, bc, r1, g1, b1]) < this.delta.apply(this, [rc, gc, bc, r2, g2, b2])) {<br />
              sumR += r1;<br />
              sumG += g1;<br />
              sumB += b2;<br />
            }else {<br />
              sumR += r2;<br />
              sumG += g2;<br />
              sumB += b2;<br />
            }<br />
          }<br />
        }<br />
        dstData[xyPos] = sumR/cnt;<br />
        dstData[xyPos + 1] = sumG/cnt;<br />
        dstData[xyPos + 2] = sumB/cnt;<br />
        dstData[xyPos + 3] = 255;<br />
      }<br />
    }<br />
  },<br />
  delta : function(rc, gc, bc, r1, g1, b1) {<br />
    return Math.sqrt((rc - r1)*(rc - r1) + (gc - g1)*(gc - g1) + (bc - b1)*(bc - b1));<br />
  }<br />
});</p>
<p>[/javascript]</p>
<p>最近、HTML5とFlashの話題が盛んですね。<br />
これまでは 主に canvas を利用したものしか試してないんですが、<br />
業務で動画配信に携わっているので video に関することも調査中です。<br />
技術の外側でH.264/Theoraを巡る政治的な争いを見守りつつ、<br />
来年度からのスタートに出遅れないように今の内にしっかり勉強しておきたいです。</p>
<p>・関連記事<br />
<a href="http://rest-term.com/archives/2103/" title="Symmetric Nearest Neighbor « Rest Term">Symmetric Nearest Neighbor « Rest Term</a><br />
<a href="http://rest-term.com/archives/2555/" title="HTML5の勉強 « Rest Term">HTML5の勉強 « Rest Term</a></p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2685/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>メイリオ</title>
		<link>http://rest-term.com/archives/2670/</link>
		<comments>http://rest-term.com/archives/2670/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 11:50:28 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[font]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2670</guid>
		<description><![CDATA[実はメイリオまだ進化中！ 誕生秘話を河野氏に聞いた － ＠IT たくさんはてブされてる記事なので読んだ人も多いかもしれませんがこれは熟読すべき！ 河野氏は熱い人だなぁ。一文字へのこだわりがすごい。 Wikipediaの項目もなんだか熱い気がする。。(メイリオ &#8211; Wikipedia) 社内プレゼンで使うフォントはメイリオにしよう。 あと、Windows 7には Meiryo UI が入っているので要確認。 ・関連記事 XPでも「メイリオ」が正式利用可能に]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.atmarkit.co.jp/news/201001/07/meiryo.html" title="実はメイリオまだ進化中！ 誕生秘話を河野氏に聞いた － ＠IT">実はメイリオまだ進化中！ 誕生秘話を河野氏に聞いた － ＠IT</a></p>
<p>たくさんはてブされてる記事なので読んだ人も多いかもしれませんがこれは熟読すべき！<br />
河野氏は熱い人だなぁ。一文字へのこだわりがすごい。<br />
Wikipediaの項目もなんだか熱い気がする。。(<a href="http://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%A4%E3%83%AA%E3%82%AA" title="メイリオ - Wikipedia">メイリオ &#8211; Wikipedia</a>)</p>
<p>社内プレゼンで使うフォントはメイリオにしよう。<br />
あと、Windows 7には Meiryo UI が入っているので要確認。</p>
<p>・関連記事<br />
<a href="http://rest-term.com/archives/17/" title=" XPでも「メイリオ」が正式利用可能に "> XPでも「メイリオ」が正式利用可能に </a></p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2670/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>libevent</title>
		<link>http://rest-term.com/archives/2660/</link>
		<comments>http://rest-term.com/archives/2660/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 12:21:33 +0000</pubDate>
		<dc:creator>wellflat</dc:creator>
				<category><![CDATA[tech/study]]></category>
		<category><![CDATA[c/c++]]></category>

		<guid isPermaLink="false">http://rest-term.com/?p=2660</guid>
		<description><![CDATA[libeventを使ったhello, world的な小さなプログラム。 (libeventはmemcachedやThriftなどでも利用されているイベント通知API) ・ファイルが更新されたら内容を表示する [csharp] #include #include #include #include #include #define BUF 256 void callback(int fd, short event, void* arg); int main(int argc, char** argv) { int fd; struct event ev; if((fd = open(argv[1], O_RDONLY)) == -1) { perror(&#8220;open&#8221;); return -1; } event_init(); event_set(&#038;ev, fd, EV_READ &#124; EV_PERSIST, callback, &#038;ev); event_add(&#038;ev, NULL); event_dispatch(); return 0; [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.monkey.org/~provos/libevent/">libevent</a>を使ったhello, world的な小さなプログラム。<br />
(libeventはmemcachedやThriftなどでも利用されているイベント通知API)</p>
<p>・ファイルが更新されたら内容を表示する<br />
[csharp]<br />
#include <stdio.h><br />
#include <unistd.h><br />
#include <sys/types.h><br />
#include <fcntl.h><br />
#include <event.h></p>
<p>#define BUF 256</p>
<p>void callback(int fd, short event, void* arg);</p>
<p>int main(int argc, char** argv) {<br />
	int fd;<br />
	struct event ev;<br />
	if((fd = open(argv[1], O_RDONLY)) == -1) {<br />
		perror(&#8220;open&#8221;);<br />
		return -1;<br />
	}<br />
	event_init();<br />
	event_set(&#038;ev, fd, EV_READ | EV_PERSIST, callback, &#038;ev);<br />
	event_add(&#038;ev, NULL);<br />
	event_dispatch();<br />
	return 0;<br />
}</p>
<p>void callback(int fd, short event, void* arg) {<br />
	char buf[BUF];<br />
	int len;<br />
	//  event_add((struct event*)arg, NULL);<br />
	if((len = read(fd, buf, sizeof(buf) &#8211; 1)) == -1) {<br />
		perror(&#8220;read&#8221;);<br />
		return;<br />
	}<br />
	buf[len] = &#8216;\0&#8242;;<br />
	printf(&#8220;%s&#8221;, buf);<br />
}<br />
[/csharp]</p>
<p>event_set 関数で EV_PERSIST を指定すると、イベント通知を継続して受け取ります。<br />
これを指定しない場合は、コールバック関数内で再度 event_add 関数を呼び出す必要があります。<br />
また、登録したイベントを削除したい場合は event_del 関数を利用します。</p>
<p>・参考<br />
<a href="http://www.ninxit.com/blog/2008/02/13/libevent-%E4%BD%BF%E3%81%84%E6%96%B9/" title="libevent + 使い方 | NINXIT-BLOG">libevent + 使い方 | NINXIT-BLOG</a></p>
]]></content:encoded>
			<wfw:commentRss>http://rest-term.com/archives/2660/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
