プログラミングのこと、Pythonのこと、気になったソフトウェアのこと、身の回りのこと、いろんなこと。"soma.classname"でエラーTomcat7がでてしばらくたつので、そろそろ安定し始めるころかと思います。言っても、実際に安定しているかどうかはともかく、そう信じ込みたいころです。言えば、今から検討し始めるので、半年後に安定していればいいのですが・・・。ちなみに、僕はJavaはあんまり好きじゃない上に、ばかでかいTomcatとよりコンパクトなJettyを推しているのですが、会社の「いわがが」こと、id:kirisにjettyの検討をお願いしてもう、二年近くたちます。彼の知り合いの人は、是非「仕事をちゃんとするように」としかってあげてください。よい前置きはこのぐらいにして、Tomcat7で会社の製品を動かすとJSPのEL式でsomaObj.class.nameとオブジェクトのクラス名を取得しようとしているところでエラーがでます。一言でいうと、会社の製品が全く動きません。true.と出ています。ログを見れば対処方法がわかりますが、org.apache.el.parser.SKIP_IDENTIFIER_CHECKをtrueにして起動すればいいようです。以前のバージョンのTomcat6ではこの値がtrueになっていて、デフォルト値が変わったらしいです。経緯はしりませんが、パフォーマンスかセキュリティの事情なんでしょう。Windowsは知りません。共有2011年6月15日RabbitMQのJavaクライアントをdisる会社のプロダクトではRabbitMQを使い始めています。製品自体はJavaで作られているので、当然、RabbitMQへのアクセスはJavaのライブラリを使っています。本家でもJavaのライブラリは開発しているようで、ありがたく使わせてていただいています。最初に製品にRabbitMQを組み込んだのは「いわがが」こと、id:kirisです。彼はまじめそうなそぶりを見せながら・・・。これ以上書くと怒られるので自重します。このJavaのライブラリについてdisりまくります。挙げ句の果てに、「もう、こんなライブラリ、使っていられません!スクラッチから書き直します。彼が言ったことをそのまま、インターネットで公開できないのが残念ですが、あまりにも・・・。今回は彼がdisりまくったことのまとめです。RabbitMQというか、MQのプロトコル自体のお話は以前書いたので、そっちを見てください。ある程度プロトコルを知っている、という前提です。RabbitMQのライブラリはcom.rabbitmq.clientのパッケージの中でインターフェースが定義されています。ネットワーク周りを中心に言うと、アプリケーションは最初にConnectionオブジェクトを作ります。ConnectionオブジェクトはTCP/IPのコネクションを管理するヒトです。仕様としてConnectionオブジェクトはスレッドセーフです。Connectionオブジェクトが実在するコネクションを管理するのに対して、ChannelオブジェクトはConnection上で論理的な接続を管理します。この辺りの概念はちょっとややこしいですね。実際にアプリケーションがMQとやりとりをするのはChannelオブジェクトを通してです。Channelオブジェクトもスレッドセーフということになっています。アプリケーションに近いところから見ていくと、Channelの実装は、implの下にあるChannelNです。ネットワークへの送信だけにフォーカスすると、ChannelNの基底クラスのAMQChannelにある、transmitメソッドです。この中でchannelに対してsynchronizedしているので、channelがスレッドセーフと言うことになっています。その先の、quiescingTrans内でネットワークの送受信が行われるので、channelを複数スレッドで使い回してそこそこの書き込みを行うと、ここの同期でブロックされます。Channelって実は、書き込みがそこそこある場合は、スレッド間で共有しない方がいいです。それじゃ、もう少しおっていきます。その後の処理はAMQCommandのtransmitメソッド中に入っていきます。このメソッドでAMQConnectionオブジェクト、一番最初に出てきたConnectionの実体ですね、その人のwriteFrameメソッドをコールして何回かに分けて書き込みを行っています。AMQCommandはAMQChannelのtransmitをコールするごとに作られたりするので、アトミックです。AMQChannelのsynchronizedが本当に何を守ろうとしているのか、微妙です。transmit自体はvoidなので、送った後に何かする訳じゃないです。面白いのはここじゃないのです。AMQConnectionの中で実際にTCPのコネクションを管理しているわけではなく、FrameHandlerが管理しています。正確にはこの人はインターフェースで、実体はSocketFrameHandlerです。TCP/IPだけじゃなくUnixソケットとかをあつかう壮大な計画の一部なのでしょう。複数のChannelで複数のスレッドからConnectionオブジェクトのwriteFrameが呼び出されます。ネットワークへの書き込みは同期しないと悲しいことになります。SocketFrameHandlerのネットワークへの書き込みは、writeFrameです。このヒト、outputstreamをsynchronizedしています。えーと、ChannelでブロックするのでChannelを複数スレッドで使い回さないようにして、スレッドごとに一つのChannelで処理をしようとしても、悲しい現実につきあたります。結局複数のスレッドで書き込みを行っても、最終的に実際のネットワークへの書き込みでブロックされちゃいます。悲しいことはvoidで結果を意識していないにもかかわらずです。これをサーブレットのRequstのスレッドの中でやると、負荷が集中し始めると世界がとまるんですねん。本当にスループットを得たいなら、スレッドごとに一つのコネクションを管理する必要があります。それはちょっとやり過ぎじゃ?僕たちの欲しいモノはブロッキングしないモノです。解の一つはスレッドを一つ作って、その中でゆっくりとデータを送信することです。一つがid:kirisが作っているはず、僕はそう信じている高速でノンブロッキングなライブラリを待つことです。共有2011年6月9日IronPythonって速かったのね普段はあまりWindowsは使わず、ほとんどの作業はMacとUbuntuで済ませています。積極的にWindowsを使う理由も見当たらない生活を送っていました。動作確認をするためだったり、間違ってボタンを押してしまったりしてVMの中にいるWindowsが立ち上がってしまうことがあります。今日は間違ってVIrtualBoxの中にいるWindowsを起動しちゃいました。ついでなので、IronPython2.7をインストールして先日pypyで遊んだときのフィボナッチで計測しました。結果はこんな感じです。再帰するほうでは、2.2倍もCPythonより速いです。Javaには及びませんが、3割ぐらい遅くなる程度です。ループ版では再帰版ほど速度差はです、1.4倍程度速くなりました。みんなが大好きなJavaとの速度差ですが、ループ版でも3割ぐらいの落ち込みなので、わりと安定したスピードです。JSstackoverflowの記事にあるように、以前はTweetButtonがあってJavaScirptで後からロードしたHTMLに対してTweetButtonをレンダリングすることができました。気がついたらこれができなくなっています。Buttonは表示できません。Boxが何なのか知りません。調べると、情報がありません。以前の方法でやるのはあきらめます。Buttonを表示するのはJavaScriptでやる方法とiframeを使う方法の二つがあります。JavaScriptを使うのはあきらめたので、iframeでがんばります。JavaScriptはtwitter-share-buttonというクラスを当てたaタグをボタンに変身させる技を使っていました。iframeを使う方はもっと簡単です。次のhtmlの断片で実現できます。height:20px;"></iframe>これをDOM要素にあとから追加していけば、TweetButtonがあとからあとからどんどん現れていきます。