» Publishers, Monetize your RSS feeds with FeedShow: More infos (Show/Hide Ads)
Date: Wednesday, 22 Jul 2009 19:40
Z-Termっていまいち使い勝手がよくない。
Mac環境下では、Z-Termを利用してシリアル接続していたが、通常のターミナルからscreenコマンドにボーレート引数を渡せばシリアル接続できる事を知りこれは便利。
Mac環境下では、Z-Termを利用してシリアル接続していたが、通常のターミナルからscreenコマンドにボーレート引数を渡せばシリアル接続できる事を知りこれは便利。
% screen /dev/tty.XXXXXXX 115200
Date: Tuesday, 07 Apr 2009 12:04
今日は、第二種電気工事士の締切日でした。
試験日がWWDCの日程とダブルブッキングしている事もしらず、申し込みを完了させている人もいましたが、受験料を振込み無事申し込み完了。第二種電気工事士を取得して、キャリアパスを変更しようと考え中。
そう、Mr.ZigBeeなるブログを始めました。
ZigBeeメン目指します。
Posted by ZigBee Man
試験日がWWDCの日程とダブルブッキングしている事もしらず、申し込みを完了させている人もいましたが、受験料を振込み無事申し込み完了。第二種電気工事士を取得して、キャリアパスを変更しようと考え中。
そう、Mr.ZigBeeなるブログを始めました。
ZigBeeメン目指します。
Posted by ZigBee Man
Date: Monday, 16 Mar 2009 22:10
Scalaでは、オブジェクトの作成〜オブジェクトのメソッド呼び出しによる初期化のための、シンタックスシュガーが用意されている。コンストラクタでオブジェクトを作成して、その後オブジェクトのメソッドを呼び出してオブジェクトを初期化する事はよく例を一つ紹介。
Jettyのハンドラーの初期化をシンタックスシュガーでコーディングした例。ブロック内のスコープは、オブジェクト内でのスコープと同じになるので、メソッドを呼ぶ事ができる。
ほんの少し気持いい。
Jettyのハンドラーの初期化をシンタックスシュガーでコーディングした例。ブロック内のスコープは、オブジェクト内でのスコープと同じになるので、メソッドを呼ぶ事ができる。
before:
val handler = new ResourceHandler
handler.setResourceBase("/webapp")
after:
val handler = new ResourceHandler { setResourceBase("/webapp) }
ほんの少し気持いい。
Date: Thursday, 12 Mar 2009 12:06
Scalaでは、Javaの型の多くをラップしたクラスにて再定義している。
byte型 -> scala.Byte
short型 -> scala.Short
int型 -> scala.Int
など。
そのため、ScalaからJavaのライブラリを利用していると、ライブラリのAPIの返り値がJavaの型で、Scalaのラッパークラスではないので変換が必要な事がよくある。例えば、java.util.List型は、ScalaのSeq[A]を継承していないので、enumerableではない。
このため、Scalaの標準ライブラリ中にいくつかの明示的な変換規則を定義してある。例えば、java.util.List[T]からList型への変換などは、scala.collection.jcl.Conversion.convertListを読みこむだけで、後はScalaの言語仕様の明示的な型変換機構により自動的に変換してくれる。
java.util.ListからList型への変換以外にも、java.util.MapからMap, java.util.SetからSetなど、多数の明示的変換が定義されているので、必要に応じて読みこむと使用できる。
byte型 -> scala.Byte
short型 -> scala.Short
int型 -> scala.Int
など。
そのため、ScalaからJavaのライブラリを利用していると、ライブラリのAPIの返り値がJavaの型で、Scalaのラッパークラスではないので変換が必要な事がよくある。例えば、java.util.List型は、ScalaのSeq[A]を継承していないので、enumerableではない。
このため、Scalaの標準ライブラリ中にいくつかの明示的な変換規則を定義してある。例えば、java.util.List[T]からList型への変換などは、scala.collection.jcl.Conversion.convertListを読みこむだけで、後はScalaの言語仕様の明示的な型変換機構により自動的に変換してくれる。
var primNumberList = new java.util.ArrayList[Int](3)
primNumberList.add(1)
primNumberList.add(3)
primNumberList.add(5)
// ScalaのSeq[A]を実装していないのでイテレーターとして扱えない
primNumberList.foreach { println(_) } // ERROR: エラー
// implicit conversionの読みこみ
import scala.collection.jcl.Conversions.convertList
primNumberList.foreach { println(_) }
1
3
5
java.util.ListからList型への変換以外にも、java.util.MapからMap, java.util.SetからSetなど、多数の明示的変換が定義されているので、必要に応じて読みこむと使用できる。
package scala.collection.jcl
object Conversions {
implicit def convertSet[T](set : java.util.Set[T]) = Set(set)
implicit def convertList[T](set : java.util.List[T]) = Buffer(set)
implicit def convertSortedSet[T](set : java.util.SortedSet[T]) = SortedSet(set)
implicit def convertMap[T,E](set : java.util.Map[T,E]) = Map(set)
implicit def convertSortedMap[T,E](set : java.util.SortedMap[T,E]) = SortedMap(set)
implicit def unconvertSet[T](set : SetWrapper[T]) = set.underlying
implicit def unconvertCollection[T](set : CollectionWrapper[T]) = set.underlying
implicit def unconvertList[T](set : BufferWrapper[T]) = set.underlying
implicit def unconvertSortedSet[T](set : SortedSetWrapper[T]) = set.underlying
implicit def unconvertMap[T,E](set : MapWrapper[T,E]) = set.underlying
implicit def unconvertSortedMap[T,E](set : SortedMapWrapper[T,E]) = set.underlying
}
Date: Sunday, 08 Mar 2009 20:10
DreadLocks 0.2を公開しました。今回のアップデートでは、テンプレート中のScala構文中でのタプルとシンボルへの対応とScalaInterpreterの実装をリファクタリングし事が主な変更点です。現在、対応している構文は、if-elseif-elseでの条件分岐、算術式の計算、変数へのメソッドの呼び出し、iterableなSeqやmapに対するループ等です。
Jarファイルは、dreadlocks-0.2.1.jarからダウンロード。
以下のような、タプルの要素への参照を含むforeachのループが書けます。
dreadlocks.txt
Test.scala
Jarファイルは、dreadlocks-0.2.1.jarからダウンロード。
以下のような、タプルの要素への参照を含むforeachのループが書けます。
dreadlocks.txt
Hamburger Cafe:
<?sc cafes.foreach { cafe => ?>
* ${cafe._1} in ${cafe._2}
<?sc } ?>
Test.scala
val tmpl = examplTmplateFile("foreach2.shtml")
val source = Source.fromFile(tmpl).getLines.mkString
val template = Template(source)
val context = Context("cafes" -> List(("Authentic", "Akasaka, Tokyo"), ("FELLOWS", "Komazawa, Tokyo")))
val output = template.render(context)
Console.println(output)
// Hamburger Cafe:
// * Authentic in Akasaka, Tokyo
// * FELLOWS in Komazawa, Tokyo
//
Date: Thursday, 05 Mar 2009 13:18
BenchmarkSuite - Scalaのベンチマークライブラリ
ページ中段BenchmarkSuiteよりGitHubへリンクしています。
Jarファイルは、BenchmarkSuite-1.0.jarから。
知ってるんだから。Scalaに標準のベンチマークライブラリscala.testing.Benchmark...が、測定したい対象の度にBenchmarkクラスを継承して実装しないといけないなど、APIがかなり硬派! LLでなまった体には正直キツイです。そこで、コードブロックを対象にベンチマークを測定するライブラリが、BenchmarkSuiteです。現在の所、実行時間のみ計測できるとてもシンプルなライブラリです。
使い方は、次の通りです。Benchmark.runに引数を一つ持つブロックを渡し、ブロック引数に対して、reportメソッドを呼ぶだけです。ラベルや実行回数を指定できます。
[Scala] Released Scala’s BenchmarkSuite Library(for English users)
ページ中段BenchmarkSuiteよりGitHubへリンクしています。
Jarファイルは、BenchmarkSuite-1.0.jarから。
知ってるんだから。Scalaに標準のベンチマークライブラリscala.testing.Benchmark...が、測定したい対象の度にBenchmarkクラスを継承して実装しないといけないなど、APIがかなり硬派! LLでなまった体には正直キツイです。そこで、コードブロックを対象にベンチマークを測定するライブラリが、BenchmarkSuiteです。現在の所、実行時間のみ計測できるとてもシンプルなライブラリです。
使い方は、次の通りです。Benchmark.runに引数を一つ持つブロックを渡し、ブロック引数に対して、reportメソッドを呼ぶだけです。ラベルや実行回数を指定できます。
import org.scalalites.benchmark.Benchmark
Benchmark.run("Benchmark of ack:") { b =>
def ack(x: Int, y: Int): Int = x match {
case 0 => y + 1
case _ => y match { case 0 => ack(x - 1, 1); case _ => ack(x - 1, ack(x, y - 1))}
}
// run over the test named "ack(3, 2) x 50" 50 times
b.report("ack(3, 4) x 10", 10) { ack(3, 4) }
// If you don't pass second argument run benchmark once.
b.report("ack(3, 2)") { ack(3, 2) }
}
// Output
// Benchmark of ack:
// ack(3, 4) x 10 : 4.730000 sec (avg. 0.473000 sec)
// ack(3, 2) x 1 : 0.029000 sec
[Scala] Released Scala’s BenchmarkSuite Library(for English users)
Date: Wednesday, 04 Mar 2009 22:04
DreadLocks - Scalaベースのテンプレートエンジン
Scalaのテンプレートエンジンを探していたけど見つからなかったので、DreadLocksテンプレートエンジンを実装しました。現在は、基本的なScalaの構文のみサポートしています。完全なScalaプログラムのサポートと高速化が次のリリースの目標としています(foreachやif文は実装済み)。ソースコードは、GitHub dreadlocks/trunkで、今後のマイルストーンとロードマップは、TwitterやGoogle Groupsで確認できるので、よければどうぞ。
簡単なサンプルコードは、以下の通り。
高速化と完全なScala構文のサポートを引き続き目指します。
Released DreadLocks-0.1 template engine for Scala programmers (in english)
Scalaのテンプレートエンジンを探していたけど見つからなかったので、DreadLocksテンプレートエンジンを実装しました。現在は、基本的なScalaの構文のみサポートしています。完全なScalaプログラムのサポートと高速化が次のリリースの目標としています(foreachやif文は実装済み)。ソースコードは、GitHub dreadlocks/trunkで、今後のマイルストーンとロードマップは、TwitterやGoogle Groupsで確認できるので、よければどうぞ。
簡単なサンプルコードは、以下の通り。
hamburgers.txt:
Delicious hamburger restraunts in Japan:
<?sc restraunts.foreach { restraunt => ?>
* ${restraunt}
<?sc } ?>
Side menus:
<?sc if(haveSideMenu) { ?>
* ${sideMenus("potato")}
* ${sideMenus("coleslaw")}
<?sc } ?>
Hamburgers.scala
import org.scalalites.dreadlocks._
// You can specify instance of java.io.File, scala.io.Source or String to constructor of Template class.
val source = Source.fromFile("template_variable.shtml")
val template = Template(source)
val context = Context("restraunts" -> List("Baker Bounce", "Great Burger", "FELLOWS"),
"haveSideMenu" -> true,
"sideMenus" -> HashMap("potato" -> "French fries", "coleslaw" -> "Coleslaw"))
val output = template.render(context)
// Console.println(output)
// Delicious hamburger restraunts in Japan:
// * Baker Bounce
// * Great Burger
// * FELLOWS
//
// Side menus:
// * French fries
// * Coleslaw
高速化と完全なScala構文のサポートを引き続き目指します。
Released DreadLocks-0.1 template engine for Scala programmers (in english)
Date: Saturday, 14 Feb 2009 21:49
scalaの言語仕様に用意されているヒアドキュメントを使用すれば、エスケープシーケンスをエスケープする必要が無いため正規表現が簡単に書ける。
before
なお、Stringクラスの"r"メソッドでStringクラスのインスタンスから正規表現のパターンオブジェクトを構築できる。
after
before
var bwh = "90.60.88"
val pat = new Regex("\\d+")
pat.findAllIn(bwg) foreach println
なお、Stringクラスの"r"メソッドでStringクラスのインスタンスから正規表現のパターンオブジェクトを構築できる。
after
"""\d+""".r.findAllIn("90.60.58") foreach println
Date: Thursday, 04 Dec 2008 11:42
Oops, long time no post.
Boost has powerful Graph library named BGL(Boost Graph Library), and serialization libraries, however the library for serialization of boost::subgraph doesn't exist, so i implement simple library to do that.
boost_subgraph_serialize was commited on Github, so you can check out them with git.
subgraph_serialize_test.cpp
Demo that serialize boost::subgraph.
subgraph_serialize.h
Implementation of serialazation of boost::subgraph.
Theses codes aren't tested enough, if you find bugs please email me(rakuto+nospam@gmail.com).
Boost has powerful Graph library named BGL(Boost Graph Library), and serialization libraries, however the library for serialization of boost::subgraph doesn't exist, so i implement simple library to do that.
boost_subgraph_serialize was commited on Github, so you can check out them with git.
% git clone git://github.com/rakuto/boost_subgraph_serialize.git
subgraph_serialize_test.cpp
Demo that serialize boost::subgraph.
/**
* Serialization of boost::subgraph
*
* Created by Rakuto Furutani <xri://rakuto/> (rakuto+nospam@gmail.com)
*
* output:
* original:
* 0 <--> 1 2
* 1 <--> 0 4
* 2 <--> 0
* 3 <-->
* 4 <--> 5 5 1
* 5 <--> 4 4
* children num: 1
*
* from file:
* 0 <--> 1 2
* 1 <--> 0 4
* 2 <--> 0
* 3 <-->
* 4 <--> 5 5 1
* 5 <--> 4 4
* children num: 1
*/
#include <fstream>
#include <string>
#include <boost/graph/subgraph.hpp>
#include <boost/graph/graph_utility.hpp>
// arhivers
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include "subgraph_serialize.h"

using namespace boost;
typedef property<vertex_name_t, char> VertexProperty;
typedef property<edge_index_t, uint32_t,
property<edge_weight_t, uint32_t> > EdgeProperty;
typedef subgraph<adjacency_list<listS, vecS, undirectedS, VertexProperty, EdgeProperty> > Graph;
static const char* DAT_FILE_NAME = "subgraph.dat";
int main()
{
enum {A, B, C, D, E, F, N};
const char* node_names = "ABCDEF";
// create root graph
Graph root(N);
property_map<Graph, vertex_name_t>::type vertex_names = get(vertex_name_t(), root);
for(uint32_t i = 0; i < N; ++i) vertex_names[i] = node_names[i];
add_edge(A, B, EdgeProperty(1), root);
add_edge(A, C, EdgeProperty(2), root);
add_edge(E, F, EdgeProperty(3), root);
// create sub graph
enum {B1, E1, F1}; // refering to vertices in sub_g1
Graph& sub_g1 = root.create_subgraph();
add_vertex(B, sub_g1);
add_vertex(E, sub_g1);
add_vertex(F, sub_g1);
add_edge(E1, F1, sub_g1);
add_edge(B1, E1, sub_g1);
std::cout << "original:" << std::endl;
print_graph(root);
std::cout << "children num: " << root.num_children() << std::endl;
// serialize and save graph
std::ofstream ofs(DAT_FILE_NAME, std::ios::out | std::ios::binary);
if(!ofs.is_open()) {
std::cerr << "Can't open " << DAT_FILE_NAME << " file." << std::endl;
return EXIT_FAILURE;
}
archive::binary_oarchive oa(ofs);
oa << root;
ofs.close();
// Try to restore saved graph
Graph g;
std::ifstream ifs(DAT_FILE_NAME, std::ios::in | std::ios::binary);
if(!ifs.is_open()) {
std::cerr << "Can't open " << DAT_FILE_NAME << " file." << std::endl;
return EXIT_FAILURE;
}
archive::binary_iarchive ia(ifs);
ia >> g;
std::cout << "\nfrom file:" << std::endl;
print_graph(g);
std::cout << "children num: " << g.num_children() << std::endl;
return EXIT_SUCCESS;
}
subgraph_serialize.h
Implementation of serialazation of boost::subgraph.
/**
* Serialization of boost::subgraph
*
* Created by Rakuto Furutani <xri://rakuto/> (rakuto+nospam@gmail.com)
*/
#ifndef SUBGRAPH_SELIALIZE_H
#define SUBGRAPH_SELIALIZE_H
#include <boost/graph/adj_list_serialize.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/subgraph.hpp>
namespace boost {
namespace serialization {
template<class Archive, class Graph>
inline void save(Archive& ar,
const subgraph<Graph> graph,
const unsigned int /* file_version*/)
{
typedef typename subgraph<Graph>::vertex_descriptor Vertex;
typedef typename subgraph<Graph>::const_children_iterator ChildrenIter;
// serialize global verticies and edges
size_t num_children = graph.num_children();
bool root = graph.is_root();
ar << BOOST_SERIALIZATION_NVP(root);
ar << BOOST_SERIALIZATION_NVP(num_children);
ar << BOOST_SERIALIZATION_NVP(graph.m_graph);
ChildrenIter ci, ci_end;
tie(ci, ci_end) = graph.children();
for(; ci != ci_end; ++ci) {
ar << *ci;
}
}
template<class Archive, class Graph>
inline void load(
Archive& ar,
subgraph<Graph>& graph,
const unsigned int /* file_version */)
{
typedef typename subgraph<Graph>::vertex_descriptor Vertex;
typedef typename Graph::vertex_iterator VertexIter;
Graph g;
bool root;
size_t num_children;
ar >> BOOST_SERIALIZATION_NVP(root);
ar >> BOOST_SERIALIZATION_NVP(num_children);
ar >> BOOST_SERIALIZATION_NVP(g);
if(root) {
graph.m_graph = g;
} else {
VertexIter vi, vi_end;
tie(vi, vi_end) = vertices(g);
graph.create_subgraph(vi, vi_end);
}
for(size_t i = 0; i < num_children; ++i) {
ar >> BOOST_SERIALIZATION_NVP(graph);
}
}
template<class Archive, class Graph>
inline void serialize(
Archive& ar,
boost::subgraph<Graph>& graph,
const unsigned int file_version)
{
boost::serialization::split_free(ar, graph, file_version);
}
} // namespace serialization
} // namespace boost
#endif
Theses codes aren't tested enough, if you find bugs please email me(rakuto+nospam@gmail.com).
Date: Tuesday, 21 Oct 2008 11:57
The Most Beautiful Code I Never Wrote.
Less is more. by ミース・ファン・デル・ローエ
l'essentiel est invisible pour les yeux by サン・テグ. ジュペリ
負のデザイン by My father
書かない事で何かを書く事ができていない。
Less is more. by ミース・ファン・デル・ローエ
l'essentiel est invisible pour les yeux by サン・テグ. ジュペリ
負のデザイン by My father
書かない事で何かを書く事ができていない。
Date: Monday, 13 Oct 2008 19:15
Revision 37555時点で、106の命令コードが実装されていて、103の命令コードについてドキュメントがコメント形式で与えられている。
命令コードドキュメントの生成
バイトコードプリティプリント
DEBUGモードでビルドした時のみ、バイトコードを表示するための-dオプションが有効です。
date_test.js
命令コードドキュメントの生成
% cd /path/to/WebKit/JavaScriptCore
% perl docs/make-bytecode-docs.pl VM/Machine.cpp docs/bytecode.html
バイトコードプリティプリント
DEBUGモードでビルドした時のみ、バイトコードを表示するための-dオプションが有効です。
date_test.js
var d = new Date();
print(d.getFullYear(), 1 + d.getMonth(), d.getDate());
% ./JavaScriptCore/build/Debug/jsc -d date_test.js
18 instructions; 388 bytes at 0x905b50; 1 parameter(s); 18 callee register(s)
[ 0] enter
[ 1] mov r-14, r0
[ 4] mov r2, r0
[ 7] resolve_global r3, [object global], Date(@id0)
[ 13] get_by_id r4, r3, prototype(@id1)
[ 21] construct r-14, r3, r4, 5, 1, 14
[ 28] construct_verify r-14, r5
[ 31] resolve_func r2, r3, print(@id2)
[ 35] get_by_id r6, r-14, getFullYear(@id3)
[ 43] call r5, r6, r-14, 7, 1, 16
[ 50] mov r7, r1
[ 53] get_by_id r8, r-14, getMonth(@id4)
[ 61] call r9, r8, r-14, 9, 1, 18
[ 68] add r6, r7, r9
[ 73] get_by_id r8, r-14, getDate(@id5)
[ 81] call r7, r8, r-14, 9, 1, 18
[ 88] call r2, r3, r2, 4, 4, 16
[ 95] end r2
Identifiers:
id0 = Date
id1 = prototype
id2 = print
id3 = getFullYear
id4 = getMonth
id5 = getDate
Constants:
r0 = undefined
r1 = 1
StructureIDs:
[ 7] resolve_global: 0x0
[ 13] get_by_id: 0x0
[ 35] get_by_id: 0x0
[ 53] get_by_id: 0x0
[ 73] get_by_id: 0x0
2008 10 13
End: undefined
LEAK: 135 StructureID
%
Date: Sunday, 12 Oct 2008 18:55
「recursive callを得意とするV8が、recursive callに比重をおいた、V8 Benchmark Suiteで速い!速い!と語られるのはフェアではない」
今回、正規表現のみに焦点を当ててJavaScriptエンジンを比較してみた。
環境
SFX(SquirrerlFish Extreme)に新しく搭載されたWREC("the WebKit Regular Expression Compiler")、Safari 3に搭載されているJavaScript Coreに比べて、なんと5倍も速い。正規表現の実行が占める実行時間が、Webアプリケーション全体の実行時間の3%ほどだとすれば、WRECは、2.4%ほどの高速化に貢献している。
V8, SFX, SpiderMonkey, Safari 3でregexp-dna.htmlをベースに作成したベンチマークスクリプトでベンチマークを計測した。スループット(1分間の実行回数)を算出しているので、グラフが大きい方が高性能。(5回測定した結果の中央値を利用)

SFXが、Safari 3の6.44倍も速いという結果がでた!!公式に発表されている結果では、5倍だからそれよりも速い!が、String.prototype.replaceメソッドの実装に差があるため、この結果はフェアではない。regex-dna.jsを修正し、実行した結果は次の通り。
実行結果

公式の発表に近い、Safari 3の5.19倍速いという結果がでたので、概ね正しそうだ。
regexp-dna.jsの修正内容は、次のとおり。
String.prototype.replaceの実装の差
ECMAScript262によるString.prototype.replace(searchValue, replaceValue)の定義では、第三引数は受付けないが、MozillaのSpiderMonkeyでは、第一引数に文字列が渡された場合に、第三引数に正規表現フラグを指定できるように拡張している。
もうひとつ。SpiderMonkey(js), SFX(jsc), v8(v8-shell)でString.prototype.replace関数の比較をすると、SFXの実装だけ明らかに他の2つとは異なることがわかる。
WRECでは、第一引数が通常の文字列の場合は、通常の文字列置換が行われ、第二引数の置換テキスト($&)が展開されない。SFX中では、"WebKit/JavaScriptCore/kjs/StringPrototype.cpp"にString.prototype.replaceの実装があるが、文字列を探索して、マッチした以前の部分、置換する文字列、マッチした後の文字列を連結して返している。
WebKit/JavaScriptCore/kjs/StringPrototype.cpp
String.prototype.replaceの第一引数が文字列の場合に、単純な文字列置換をおこないパフォーマンスを向上する最適化は、SpiderMonkeyでもとりこまれる予定だ。(See Bug 432525)
WRECでは、グルーピングは未実装
シンプル!軽量!速い!と3拍子そろったWRECだけど、グルーピングの機能は実装しておらず、グルーピング付きのパターンが指定された時は、PCREに処理を任せることになるため、実行速度が低下する。
regepx-dna.htmlのベンチマークでグルーピングありとなしを比べると実行速度の差が明らかになる。実行時間が変更前の140%になったSpiderMonkeyに比べて、SFXは、680%もの増加となった。
変更前
変更後 (SFXでは、680%の速度低下)
今回、正規表現のみに焦点を当ててJavaScriptエンジンを比較してみた。
環境
- SpiderMonkey - 1.7.0 2007-10-03
- SFX - Revision: 37445
- v8 - Revision: 389
SFX(SquirrerlFish Extreme)に新しく搭載されたWREC("the WebKit Regular Expression Compiler")、Safari 3に搭載されているJavaScript Coreに比べて、なんと5倍も速い。正規表現の実行が占める実行時間が、Webアプリケーション全体の実行時間の3%ほどだとすれば、WRECは、2.4%ほどの高速化に貢献している。
V8, SFX, SpiderMonkey, Safari 3でregexp-dna.htmlをベースに作成したベンチマークスクリプトでベンチマークを計測した。スループット(1分間の実行回数)を算出しているので、グラフが大きい方が高性能。(5回測定した結果の中央値を利用)

SFXが、Safari 3の6.44倍も速いという結果がでた!!公式に発表されている結果では、5倍だからそれよりも速い!が、String.prototype.replaceメソッドの実装に差があるため、この結果はフェアではない。regex-dna.jsを修正し、実行した結果は次の通り。
実行結果

公式の発表に近い、Safari 3の5.19倍速いという結果がでたので、概ね正しそうだ。
regexp-dna.jsの修正内容は、次のとおり。
< dnaInput = dnaInput.replace(k, subs[k], "g")
---
> dnaInput = dnaInput.replace(new RegExp(k, 'g'), subs[k]);
String.prototype.replaceの実装の差
ECMAScript262によるString.prototype.replace(searchValue, replaceValue)の定義では、第三引数は受付けないが、MozillaのSpiderMonkeyでは、第一引数に文字列が渡された場合に、第三引数に正規表現フラグを指定できるように拡張している。
もうひとつ。SpiderMonkey(js), SFX(jsc), v8(v8-shell)でString.prototype.replace関数の比較をすると、SFXの実装だけ明らかに他の2つとは異なることがわかる。
% js
js> 'aaaaa'.replace('a', '_$&_', 'g') # SpiderMonkeyでは、gフラグが有効
_a__a__a__a__a_
% v8-shell
V8 version 0.2.5
> 'aaaaa'.replace('a', '_$&_', 'g') # v8では、gフラグは無効
_a_aaaa
% jsc
> 'aaaaa'.replace('a', '_$&_', 'g') # SFXでも、gフラグは無効
_$&_aaaa
>'aaaaa'.replace(/a/, '_$&_', 'g')
_a_aaaa
WRECでは、第一引数が通常の文字列の場合は、通常の文字列置換が行われ、第二引数の置換テキスト($&)が展開されない。SFX中では、"WebKit/JavaScriptCore/kjs/StringPrototype.cpp"にString.prototype.replaceの実装があるが、文字列を探索して、マッチした以前の部分、置換する文字列、マッチした後の文字列を連結して返している。
WebKit/JavaScriptCore/kjs/StringPrototype.cpp
JSValue* stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue* thisValue, const ArgList& args)
{
// 引数の処理
if (pattern->isObject(&RegExpObject::info)) {
// 第一引数がRegExpオブジェクトのケースの処理
}
// 第一引数が文字列の場合
// First arg is a string
UString patternString = pattern->toString(exec);
int matchPos = source.find(patternString);
int matchLen = patternString.size();
// Do the replacement
if (matchPos == -1)
return sourceVal;
if (callType != CallTypeNone) {
ArgList args;
args.append(jsSubstring(exec, source, matchPos, matchLen));
args.append(jsNumber(exec, matchPos));
args.append(sourceVal);
replacementString = call(exec, replacement, callType, callData, exec->globalThisValue(), args)->toString(exec);
}
return jsString(exec, source.substr(0, matchPos) + replacementString + source.substr(matchPos + matchLen));
}
String.prototype.replaceの第一引数が文字列の場合に、単純な文字列置換をおこないパフォーマンスを向上する最適化は、SpiderMonkeyでもとりこまれる予定だ。(See Bug 432525)
WRECでは、グルーピングは未実装
シンプル!軽量!速い!と3拍子そろったWRECだけど、グルーピングの機能は実装しておらず、グルーピング付きのパターンが指定された時は、PCREに処理を任せることになるため、実行速度が低下する。
bool WRECParser::parseParentheses(JmpSrcVector&)
{
// FIXME: We don't currently backtrack correctly within parentheses in cases such as
// "c".match(/(.*)c/) so we fall back to PCRE for any regexp containing parentheses.
m_err = TempError_unsupportedParentheses;
return false;
}
regepx-dna.htmlのベンチマークでグルーピングありとなしを比べると実行速度の差が明らかになる。実行時間が変更前の140%になったSpiderMonkeyに比べて、SFXは、680%もの増加となった。
変更前
> dnaInput = dnaInput.replace(/g*t/g, subs[k]);
% jsc regexp-dna.js
285 (msec)
% js regepx-dna.js
1789 (msec)
変更後 (SFXでは、680%の速度低下)
> dnaInput = dnaInput.replace(/(g*)t/g, subs[k]);
% jsc regexp-dna.js
1942 (msec)
% js regexp-dna.js
2501 (msec)
Date: Thursday, 11 Sep 2008 19:25
おっPythonハカーを多数抱える、煩悩駆動開発で有名なglucose.jpのお手伝いをする機会があり、4年ぶりにPythonを書いた。2.3以来だったので、2.5を眺めているとデコレーターと呼ばれる機能が導入されていた。
デコレーターとクロージャーを組み合わせれば、メソッドの挙動を自由にカスタマイズすることができる。この機能を使用して、関数の結果をmemcachedでキャッシュする機能を付与するデコレーターを作ってみた。
あらかじめ、CACHE変数をmemcachedクライアントで初期化しておく必要がある。
挙動
ソースは、少々ややこしいけど、実行の仕組みは単純。
Step 1:
@cached構文実行時に、ack関数に対して、cached関数が実行され、ack関数がdecorated_funcを呼び出した結果でack関数が置換される。(返り値は、callableなオブジェクトでないといけない。)
Step 2:
decorated_func関数の呼び出し時の引数は、元のack関数。decorated_func関数の内部では、func_with_cacheが定義されており、ack関数に渡した引数を渡して実行される。この関数が、関数呼び出しの結果のキャッシュをチェックする本体となる。
実行結果
まとめ
来月から、shn@glucose.jpによるおっPython連載がオライリーで始まるらしい。代表取締役としての世間体と、煩悩の狭間で、どこまで書いていいのか悩んでいるようだ。結論をそれに帰着するという路線と合わせて、”ゆるかわPython”なるコンセプトを提案し、20代後半女性Pythonianを増やす革命者になるという路線も考えているようだ。
記事の影響により、glucose発の女性Pythonハカー誕生なるか。
デコレーターとクロージャーを組み合わせれば、メソッドの挙動を自由にカスタマイズすることができる。この機能を使用して、関数の結果をmemcachedでキャッシュする機能を付与するデコレーターを作ってみた。
あらかじめ、CACHE変数をmemcachedクライアントで初期化しておく必要がある。
挙動
ソースは、少々ややこしいけど、実行の仕組みは単純。
Step 1:
@cached構文実行時に、ack関数に対して、cached関数が実行され、ack関数がdecorated_funcを呼び出した結果でack関数が置換される。(返り値は、callableなオブジェクトでないといけない。)
Step 2:
decorated_func関数の呼び出し時の引数は、元のack関数。decorated_func関数の内部では、func_with_cacheが定義されており、ack関数に渡した引数を渡して実行される。この関数が、関数呼び出しの結果のキャッシュをチェックする本体となる。
# Decorate methods with capability for caching result
#
# @author Rakuto Furutani <http://raku.to/>
# @version 0.1.0
#
import cPickle
import memcache
import time
import md5
__all__ = ['cached', 'init']
# TODO: CACHE variable and function for initialize move to scope in Devkit.cache.*
# You must define global variable named 'CACHE' with instance of memcache client.
CACHE = None
def init(cache_client):
""" We should initialize this library with this method
examples:
CACHE = memcache.Client(['127.0.0.1:11211'], debug=0)
methods_cache.init(CACHE)
"""
global CACHE
CACHE = cache_client
def cached(d_args):
""" Decorate method with caching capability for caching
All result call the function are cached with cache key generated by function name and parameters.
examples:
@cached({'ttl': 3600})
def havy_complex_func(args):
# do something
# Return whether result call real function or cached result
havy_complex_func()
# You can specify cache key name explicitly
@cached({'ttl': 3600, 'key': 'foo_bar'})
def foo_bar():
# doo something
# You can also decorate one without ttl parameter
@cached
def havy_complex_func(args):
# do something
"""
def cache_key(func, args):
"""Generate unique cache key with funcion name and arguments"""
return "%s_%s" % (func.__name__, md5.new(str(args)).hexdigest())
def call_and_cache(func, args, key):
ret = func(*args)
data = {'ttl': (time.time() + d_args['ttl'] if 'ttl' in d_args else None), 'd': ret}
CACHE.set(key, cPickle.dumps(data))
return ret
def decorated_func(func):
def func_with_cache(*args):
key = d_args['key'] if ('key' in d_args) else cache_key(func, args)
cached_val = CACHE.get(key)
if cached_val is not None:
cached_val = cPickle.loads(cached_val)
if (cached_val['ttl'] is not None) and (cached_val['ttl'] >= time.time()):
return cached_val['d']
return call_and_cache(func, args, key)
return func_with_cache
return decorated_func
if __name__ == '__main__':
import sys
import time
sys.setrecursionlimit(10000)
# Define memcache client
CACHE = memcache.Client(['127.0.0.1:11211'], debug=0)
def _internal_ack(m, n):
if m == 0:
result = n + 1
elif n == 0:
result = ack(m - 1, 1)
else:
result = ack(m - 1, ack(m, n -1))
return result
def ack(m, n):
return _internal_ack(m, n)
@cached({'ttl': 3600})
def ack_with_cache(m, n):
return _internal_ack(m, n)
t = time.time()
ret = ack(3, 4)
print("ack(3, 4) returned %d - %s sec" % (ret, str(time.time() - t)))
ack_with_cache(3, 4) # cached once
t = time.time()
ret = ack_with_cache(3, 4)
print("ack(3, 4) returned %d with cached - %s sec" % (ret, str(time.time() - t)))
実行結果
ack(3, 4) returned 125 - 0.00920796394348 sec
ack(3, 4) returned 125 with cached - 0.000248908996582 sec
まとめ
来月から、shn@glucose.jpによるおっPython連載がオライリーで始まるらしい。代表取締役としての世間体と、煩悩の狭間で、どこまで書いていいのか悩んでいるようだ。結論をそれに帰着するという路線と合わせて、”ゆるかわPython”なるコンセプトを提案し、20代後半女性Pythonianを増やす革命者になるという路線も考えているようだ。
記事の影響により、glucose発の女性Pythonハカー誕生なるか。
Date: Friday, 29 Aug 2008 11:38

脆弱性。
将来において改善されそうなiPhoneの仕様 or バグの一つが話題になっている。パスコードロックがかかっている画面から緊急電話をクリックした画面でホームボタンをダブルクリックすると「よく使う項目」にアクセスできてしまう。(表示された画面のキャンセルボタンも機能しないし、おそらくバグ)
脆弱性回避のために、
設定 -> 一般 -> ホームボタンで、「よく使う項目にチェックされているフィールドを、「ホーム」にしておく。
P.S.
パスコードロックの画面では、スクリーンショット機能は起動できないが、緊急電話をかけるための画面では、スクリーンショット機能が利用できた。(ただし、実際は、壁紙しか映らなかった。)
関連記事
Date: Tuesday, 26 Aug 2008 13:32
「机に座り、起動時間が3分程かかる窓のアイコンを眺めつつ、ただ待つ。モデムのスイッチを入れて、PPP接続アシスタントを立ち上げ、青いeのアイコンをクリックする。さぁ、インターネットを始めるぞ!」13年程前か。そんな時代が、随分と懐かしく感じる。
iPhoneの登場が、私達のオフラインでいる時間を無情にも奪う。Firmware 2.0.2でも、電波状況は(まだ)悪いけど、場所を選ばすにSafariが立ち上がり、Google Readerを読めるのはとても魅力的だ。オンラインでいる時間が増えるから、ライフストリーミング系のアプリケーションが盛り上がるわけだ。パーベイシブコンピューティング、インターネットは場所を選ばず利用できるようになりつつある。原丈人氏の言葉で言えば、PUC(パーベイシブユビキタスコミュニケーション)だろうか。GPS, WiFiをiPhone上で使っていて、電池の減りがいつも気になる。iPhoneは、バッテリーの交換が出来ないのに。
瀧内氏と飲んでいる時にも、よく盛り上がる話題の一つが、ワイヤレス給電だ。
WiFi同様に、電力が場所を選ばずに利用できる時代、町中に"パワースポット"が普及するのはいつ頃だろうか?といった内容の話をする。人体に影響を与えず、利用料に応じて課金される従量制。そんな電力スポットの登場が待ち遠しい。
インテル・デベロッパー・フォーラム(IDF)Fall 2008で、MITで研究されているWREL(Resonant Energy Link)のデモが公開された。
via 2050 年までに人間と機械はより一層近づくと講演

WRELは、MITの物理学者Marin Soljacic氏らの研究をベースにしている。関連記事は次の通り。
このプレスリリースには、ポイポイカプセルを思い起こさせるような一節がある。「物体もプログラム可能に:形を変えるコンピューター」と題して、次のように記載されている。
インテル面白いなぁ...
iPhoneの登場が、私達のオフラインでいる時間を無情にも奪う。Firmware 2.0.2でも、電波状況は(まだ)悪いけど、場所を選ばすにSafariが立ち上がり、Google Readerを読めるのはとても魅力的だ。オンラインでいる時間が増えるから、ライフストリーミング系のアプリケーションが盛り上がるわけだ。パーベイシブコンピューティング、インターネットは場所を選ばず利用できるようになりつつある。原丈人氏の言葉で言えば、PUC(パーベイシブユビキタスコミュニケーション)だろうか。GPS, WiFiをiPhone上で使っていて、電池の減りがいつも気になる。iPhoneは、バッテリーの交換が出来ないのに。
瀧内氏と飲んでいる時にも、よく盛り上がる話題の一つが、ワイヤレス給電だ。
WiFi同様に、電力が場所を選ばずに利用できる時代、町中に"パワースポット"が普及するのはいつ頃だろうか?といった内容の話をする。人体に影響を与えず、利用料に応じて課金される従量制。そんな電力スポットの登場が待ち遠しい。
インテル・デベロッパー・フォーラム(IDF)Fall 2008で、MITで研究されているWREL(Resonant Energy Link)のデモが公開された。
via 2050 年までに人間と機械はより一層近づくと講演
ノートブック PC を持って空港や部屋に入るだけで、バッテリーが消耗するどころか充電されるとしたら…。MIT の物理学者の理論をもとに、インテルではワイヤレス共振エネルギー・リンク(Wireless Resonant Energy Link:WREL)の研究を行っています。ラトナーは、電源プラグも電線も使わずに、60 ワットの電球を点灯してみせました。60 ワットは、標準的なノートブック PC の消費電力を上回る電力です。
WREL の素晴らしい点は、電力をワイヤレスで安全かつ効率的に供給できることです。この技術は強結合共振器を使用します。訓練された歌手が声でガラスを割ることができるのとよく似た原理です。これはガラスの固有振動数で音響エネルギーが吸収されることと同じ様に、受信側の共振器の固有振動数と共振することで、エネルギーは効率よく吸収されます。このテクノロジーをノートブック PC などに搭載すれば、送信側の共振器から数十センチの距離に近づけることでバッテリーを充電することが可能になります。
WRELは、MITの物理学者Marin Soljacic氏らの研究をベースにしている。関連記事は次の通り。
このプレスリリースには、ポイポイカプセルを思い起こさせるような一節がある。「物体もプログラム可能に:形を変えるコンピューター」と題して、次のように記載されている。
インテルではまた、何百万個もの「catom」と呼ばれる微小なマイクロロボットによって、自在に形状を変えることができる素材の研究を進めています。この素材をコンピューティング機器の筐体やディスプレイ、キーボードの製造に使うことにより、ユーザー固有の形状にすることができます。例えばノートブック PC ならば、ポケットに入れるときは小さくなり、携帯電話として使用するときは受話器の形になり、インターネットを閲覧したり映画を見るときは、大きく薄くなってキーボードも現れる、といったことが可能になります。
インテル面白いなぁ...
Date: Friday, 08 Aug 2008 18:11
海の向こうで話題になっていた時は、その圧倒的な力に感心する程度であったが、実際に日本でもGoogle Street Viewが、リアルクローラーを走らせているとなるとプライバシーが気になる。公共の道路で撮影された映像には、著作権は存在しなく、まずい画像については、モザイクやユーザからの投稿で対応していくとの事だが、土地所有者や人にもrobot.txtを書く権利を与えてくれてもいいだろう。

「ベッドルームの撮影はお断り」との事だ。
クローラーがVanでなくて、小型偵察機や昆虫のような大きさまで小さくなった時には、どうなるのだろうか。拡張現実社会の到来にむけて、実世界におけるrobots.txtの書き方を真剣に考えるべき時である。
撮影された画像に著作権が無いとすれば、Google Street View上に広告を配信することは可能なんだろうか?ネタ画像を探そうと、みんながどこを探しまわっているかは、だいたい想像がつく。何よりGoogleには、Google Street View上での膨大なユーザのアクティビティログが残っている。ユーザが良く訪れる場所に広告を出して、「一部、拡張現実です」と明記している事はいけないのだろうか?
ザッツ監視社会はどのような世界なのか?
覗いてみたい方は、大統領暗殺の濡れ衣を着せられた一人の男の物語、ゴールデンスランバーを一読してみると良い。街中に設置されたセキュリティポットは、犯罪をおかさない善良な市民にとってはいいかもしれない。しかし、この男は、"見えない力"によりオズワルドに仕立てられた男なのだ。
Google.govなんてくそくらえ。

via Robots.txt 2.0
「ベッドルームの撮影はお断り」との事だ。
クローラーがVanでなくて、小型偵察機や昆虫のような大きさまで小さくなった時には、どうなるのだろうか。拡張現実社会の到来にむけて、実世界におけるrobots.txtの書き方を真剣に考えるべき時である。
撮影された画像に著作権が無いとすれば、Google Street View上に広告を配信することは可能なんだろうか?ネタ画像を探そうと、みんながどこを探しまわっているかは、だいたい想像がつく。何よりGoogleには、Google Street View上での膨大なユーザのアクティビティログが残っている。ユーザが良く訪れる場所に広告を出して、「一部、拡張現実です」と明記している事はいけないのだろうか?
ザッツ監視社会はどのような世界なのか?
覗いてみたい方は、大統領暗殺の濡れ衣を着せられた一人の男の物語、ゴールデンスランバーを一読してみると良い。街中に設置されたセキュリティポットは、犯罪をおかさない善良な市民にとってはいいかもしれない。しかし、この男は、"見えない力"によりオズワルドに仕立てられた男なのだ。
Google.govなんてくそくらえ。
Date: Saturday, 19 Jul 2008 13:12
第三回 Liberty Alliance 技術セミナーで=natさんの基調講演を公聴してきて、OpenID関連の動向を仕入れたのでメモ。
OPとRP間で属性情報を交換するための拡張として、SREGやAXがあるが、AXも今ひとつ普及するに至っていない。(myopenid.comとVeriSignだけ?)また、プライバシポリシーや利用規約の問題もあり、日本企業では、ユーザ属性をサードパーティに公開出来ない事も多い。
基本的に、AXとSREGの違いは、
が挙げられるが、根本的な問題は、OpenIDのユーザ属性として、クレジットカード番号や電話番号などプライバシー性の高い情報を使う事など、気が狂っていると思われている事だ。AXへの本格的な以降が進まないのは、結局OpenIDで扱うユーザ属性は、ニックネームやメールアドレスのみで、SREGで十分に事が足りているからではないだろうか。
さて、単純なユーザ属性の交換と、OP側でのユーザの許可の仕組みしか提供していないAXに代わる仕様として、Trusted Data Exchangeが=natさん、=masakiさん (NRI)から提出されている。
TXのコンセプトには次のような物が含まれる。
年内に取り込まれるだろうか?
もう一つの最新動向は、PAPEの仕様拡張。PAPEと言えば、OpenIDの認証強度を明示するためのOpenID拡張だが、採用するセキュリティモデルを明示的に指定するための仕様を提案しているとの事。現状のPAPEでは、NISTの定めるセキュリティモデルを指定できるだけであるが、日本のFISCの基準を採用する際には、次のように指定できるとの事だ。
See also: まちゅダイアリー - SAML と OpenID と CardSpace
OPとRP間で属性情報を交換するための拡張として、SREGやAXがあるが、AXも今ひとつ普及するに至っていない。(myopenid.comとVeriSignだけ?)また、プライバシポリシーや利用規約の問題もあり、日本企業では、ユーザ属性をサードパーティに公開出来ない事も多い。
基本的に、AXとSREGの違いは、
- 交換可能な属性をコミュニティベースで提案&決定する
- 属性を識別するために、プリミティブな値でなく、ネームスペースURIを使う
- OPに要求する属性の個数が指定可能
- RPがOPに対して属性の保存をする事が可能。(ただし、使われているプロバイダは知らない。)
が挙げられるが、根本的な問題は、OpenIDのユーザ属性として、クレジットカード番号や電話番号などプライバシー性の高い情報を使う事など、気が狂っていると思われている事だ。AXへの本格的な以降が進まないのは、結局OpenIDで扱うユーザ属性は、ニックネームやメールアドレスのみで、SREGで十分に事が足りているからではないだろうか。
さて、単純なユーザ属性の交換と、OP側でのユーザの許可の仕組みしか提供していないAXに代わる仕様として、Trusted Data Exchangeが=natさん、=masakiさん (NRI)から提出されている。
TXのコンセプトには次のような物が含まれる。
- 契約ベースの属性提供
- XML Encryption/XML Signatureによる暗号化•書名
- 非同期な属性提供 (非否認性を持った契約ベース)
- RPの信憑性を判断するReputation Platform (現状のホワイトリストに代わる)
年内に取り込まれるだろうか?
もう一つの最新動向は、PAPEの仕様拡張。PAPEと言えば、OpenIDの認証強度を明示するためのOpenID拡張だが、採用するセキュリティモデルを明示的に指定するための仕様を提案しているとの事。現状のPAPEでは、NISTの定めるセキュリティモデルを指定できるだけであるが、日本のFISCの基準を採用する際には、次のように指定できるとの事だ。
openid.pape.auth_level.fisc:2
openid.pape.auth_level.ns.fisc: http://www.fisc.or.jp/ex/authlevel
See also: まちゅダイアリー - SAML と OpenID と CardSpace
Date: Wednesday, 16 Jul 2008 11:03
Hmm..,
I spent three hours for a Mnesia's strange error message, so write tips about error I'm confused. The tables on Mnesia often need a time to prepare their tables, and if tables aren't available, then we'll see storange error message.
% db_test.erl
You may see the error is as follows:
It seems it need to call mnesia:wait_for_tables.
% db_test.erl
I think that error message "{no_exists, table_name}" is not human friendly.
I spent three hours for a Mnesia's strange error message, so write tips about error I'm confused. The tables on Mnesia often need a time to prepare their tables, and if tables aren't available, then we'll see storange error message.
% db_test.erl
write_db_test() ->
start(), % Start the server, mnesia and create required tables.
?assertMatch({ok, _}, mnesia:transaction(fun() -> #person{name="rakuto"})).
You may see the error is as follows:
{badmatch,{aborted,{no_exists,ready_queue}}}
It seems it need to call mnesia:wait_for_tables.
% db_test.erl
write_db_test() ->
start(), % Start the server, mnesia and create required tables.
mnesia:wait_for_tables([person], 3000),
?assertMatch({ok, _}, mnesia:transaction(fun() -> #person{name="rakuto"})).
I think that error message "{no_exists, table_name}" is not human friendly.
Date: Tuesday, 15 Jul 2008 11:49
Google anounced about Gears on Rails, see Take your Rails application offline with the Gears on Rails project. We can listen to audio interview. This is Rails plugin to manipulate offline data from RoR.We can install GoR as Rails plugin is as follows:
It need to add acts_as_local method in your controller in order to use it.
Sorry, I never use GoR yet, but It seems interesting, so i may use it. See Gears on Rails in order to see how to write view and controller for more details.
% sudo gem install json_pure
% rails gor_demo && cd gor_demo
% ruby script /plugin install http://gearsonrails.googlecode.com/svn/trunk/acts_as_local
It need to add acts_as_local method in your controller in order to use it.
acts_as_local :except => [:hello]
def create_local
'
post = Post.build(params("post"));
Post.create_local(post);
window.location.reload( false );
'
end
Sorry, I never use GoR yet, but It seems interesting, so i may use it. See Gears on Rails in order to see how to write view and controller for more details.
Date: Friday, 04 Jul 2008 21:45
We usually need to package system and repositories in order to create a big application. Erlware is a repository for Erlang programs and it provides softaware to create a package and release it to the world. There are pretty cool, it is just thing I want to. This entry introduces that how to create an application as package and install to system.
I create a HAVAL bindings for Erlang in order to learn how to create linked-in driver.
See Tutorial for how to create Erlang linked-in driver.
In this entry, I introduce how to create an application provides API for HAVAL bindings for Erlang. We need to install Faxien and Sinan previously.
0. Dicied a names of application and start to development a pakcage.
Create required directories for the application.
Create a HAVAL bindings for Erlang in this entry. This includes following source codes:
HAVAL bindings requires shared library named "erl_drv.so", we may think want to integrate building task for linked-in driver to the package manager(Faxien). But unfortunately I don't know that, so I need to research for handling shared library.
All sources are here.
Do make task manually here.
It 'sinan' command is used for building the application. We need to run background server with 'sinserv' command before compile them.
Some of tasks are required in order to install the application. At first, we need to prepare the directory for released package, copy "_build/development/release" to "releases/haval-1.0.0/" and copy "_build/development/haval-1.0.0" to "releases/haval-1.0.0".
Install the application locally, there will be deployed on "/usr/local/erlware/release_packages/haval-1.0.0/". We can use 'faxien' command in order to handle the packages (local and remote). Please execute "faxien help commands" for more details.
We can use EUnit for testing the application, and do test with following command:
I create a HAVAL bindings for Erlang in order to learn how to create linked-in driver.
See Tutorial for how to create Erlang linked-in driver.
In this entry, I introduce how to create an application provides API for HAVAL bindings for Erlang. We need to install Faxien and Sinan previously.
0. Dicied a names of application and start to development a pakcage.
Create required directories for the application.
% mkdir haval && cd haval && mkdir -p cmds doc bin libCreate directories for HAVAL bindings.
% ls .
bin/ cmds/ doc/ lib/ releases/
%
% mkdir -p lib/haval && cd lib/hava && mkdir src ebin include priv/libConfiguration file named "_build.cfg" for this application.
% cat > _build.cfg1. Create an application
project : {
name : haval
vsn : "1.0.0"
},
repositories : ["http://repo.erlware.org/pub", "http://repo.martinjlogan.com/pub"]
Create a HAVAL bindings for Erlang in this entry. This includes following source codes:
- haval.erl - Source provides API for HAVAL bindings
- haval_server.erl - Server to handle the shared library of HAVAL linked-in driver.
- haval_sup.erl - Supervisor
- haval_app.erl - An application
- Makefile
- config.h
- haval.c
- haval.h
- haval_drv.o
HAVAL bindings requires shared library named "erl_drv.so", we may think want to integrate building task for linked-in driver to the package manager(Faxien). But unfortunately I don't know that, so I need to research for handling shared library.
All sources are here.
Do make task manually here.
% cd lib/haval/c_src3. Build the application.
% make # Copy haval_drv.so haval/priv/lib
It 'sinan' command is used for building the application. We need to run background server with 'sinserv' command before compile them.
% sinserv # Placed in "/usr/local/erlware/release_packages/sinan-0.10.0.12/bin/sinserv" in my enviromentBuild the application with 'sinan' command. We can see help when '+help' command is passed.
% sinan +helpCreate a package for release. This package is generated underneath "_build/development/apps/" directory.
sinan [args] [task]
local args (+) and server args. local args may be any of the following
+url : The url to connect to and control
+help : This help message
Server args are much more complex. There are always sane defaults so
you shouldn't need them, but you may. To get information about server
args read the sinan documentation.
%
% sinan # Default task is build
starting run
[check_depends] start
[check_depends] stop
[build] start
[build] Building ~/haval-1.0.0/lib/haval/src/haval_server.erl
[build] Building ~/haval-1.0.0/lib/haval/src/haval_sup.erl
[build] Building ~/haval-1.0.0/lib/haval/src/haval_app.erl
[build] Building ~/haval-1.0.0/lib/haval/src/haval.erl
[build] stop
run complete
% ls _build/development/apps/haval-1.0.0 # Generated following sources
c_src/ ebin/ include/ priv/ src/
%
% sinan release4. Install the application locally.
starting run
[check_depends] start
[check_depends] stop
[build] start
[build] stop
[release] start
[release] stop
run complete
%
Some of tasks are required in order to install the application. At first, we need to prepare the directory for released package, copy "_build/development/release" to "releases/haval-1.0.0/" and copy "_build/development/haval-1.0.0" to "releases/haval-1.0.0".
% mkdir releases/haval-1.0.0/ && mkdir lib
% cp -r _build/development/release releases/haval-1.0.0/
% cp -r _build/development/apps/haval-1.0.0 releases/haval-1.0.0/lib
Install the application locally, there will be deployed on "/usr/local/erlware/release_packages/haval-1.0.0/". We can use 'faxien' command in order to handle the packages (local and remote). Please execute "faxien help commands" for more details.
Run and test.
% faxien install-release releases/haval-1.0.0
ok
% ls /usr/local/erlware/release_packages/haval-1.0.0/
LICENCE README lib/ release/
% erl5. Test the application
Erlang (BEAM) emulator version 5.6.2 [source] [smp:2] [async-threads:0] [kernel-poll:false]
Eshell V5.6.2 (abort with ^G)
1> haval:start().
ok
2> haval:haval_string("test").
"593C9AED973BB51A3C852FB4E051D7C26686B9468B4E405350CB6805DC1B99E6"
3> haval:haval_file("_build.cfg").
"5A114E356FBB0CCCED8C7574B7A71780C8F33D3A9B37B8642126B78429B2988F"
4>
We can use EUnit for testing the application, and do test with following command:
% sinan test
» © All content and copyrights belong to their respective authors.«
» © FeedShow - Online RSS Feeds Reader







