2011年5月 7日

Remove '@Override' annotation

Eclipseで、そこらへんのコードをコピペすると、

Remove '@Override' annotation

と怒られることがある。言われた通り消せば良いのだが、サンプル丸ごとビルドしてみたい時などは面倒だ。

Errors/Warningsのオプションをいじれば直るのかと思ったが、なかなかそれっぽい項目が見つからない。

いろいろ調べた結果、Compiler compliance level を 1.6 に変更すればよいことが分かった。(プロジェクトのプロパティを開いて、Java Compiler の中にある)

理想と現実の乖離にぶつかる度に、Javaが嫌いになる。理想とはもちろん"Write once, run anywhere"のことで、現実とはもちろん"Write once, debug anywhere"のことだ。

Posted by rukihena at 21:24:48 | Comments [0] | Trackbacks [0]

2011年5月 1日

JJYエミュ

先日作成したJJYシミュレータ for Androidを改良してAndroid Marketに登録した。・・のは20日頃だっただろうか。

名前についてちょっと悩んだんだが、「JJYエミュ」とした。

シミュレータとエミュレータの違いについては微妙なんだが、ここでの目的としては実験環境の用意ではなく、本物の模倣である。
どっちかと言えばエミュレータかなと思った次第。

本家の方は送出する時刻を変更することが可能なあたりがシミュレータの要素を含んでいると思う。
まあ、名前なんかはどうでもいい。

それにしてもインストール数が伸びない。

リーチの想定は「マーケット内にて"JJY"で検索する」というものであるが、そんなことをする人は少ないのだろうか。
2chで宣伝して、20インストール。それから伸びない伸びない。1個も増えない。
しばらくすると、突如89になった。おそらく、Make:Japan で iPhone版が紹介されたことをキッカケに、マーケットでJJYを検索したのだろう。
その後、また伸びなくなった。

福島が復帰して、再度停波したときに伸びなかったのは残念だ。


本ソフトの特徴としては、タイムコードが視覚的に分かる点があげられる。見れたからといってどうなるものでもないのだが、もしかしたらコレで理解できて別プラットホームに移植する人が出てくるかもしれない。そんな期待を込めて、画面を作ってみた。

バグがいくつかある。画面更新が59秒の時に行われてしまう。気づくと気になるが、知らなければ気付かないかもしれない。

機能的にももうちょっと配慮があってもいい。まず、開始・停止ボタンが無い。音量コントロールを全く考慮してない。バックライト制御(暗転抑制)も入れた方がいいだろう。バッファが無駄に長めで、終了しても1秒ぐらいお漏らしする。

それと、実用的にはNTPとの同期もやった方がいいだろう。SIMが差さっていれば、多くの場合に内蔵時計が信頼できるが、そうでない場合もある。

長時間運用時にズレていく点も、問題になる運用例は少ないかもしれないが、対応したいところだ。

自分的に納得いくものになる日は来るのだろうか。

Posted by rukihena at 02:52:07 | Comments [0] | Trackbacks [0]

2011年4月11日

JJYシミュレータ for Android

電波時計用JJYシミュレータを見て、Android版があったら便利かもなと思って作ってみた。
とりあえず作ってみました的な感じですが。

simjjy.apk

※長時間動作させっぱなしにすることは想定していません。微妙にずれていく内蔵時計をNTPなどで補正しても、無視して時刻を刻み続けます。一度同期が終わったら終了させるような使い方を推奨します。

Posted by rukihena at 06:11:43 | Comments [0] | Trackbacks [0]

2008年5月 6日

業務システムにおける祝日の扱いについて

 某システムで、休日の設定をテキストファイルでチマチマ設定しなければならないものがあった。

 ボクはそれを見て、「ダサイ」と思った。

 振り替え休日とかハッピーマンデー法とかもロジックで組みやがれ! と。

 技術ヲタにありがちな発想である。


 最近になって、その考えは間違いだと気づいた。

 祝日などは、「国民の祝日に関する法律」で定められている。これが意外とコロコロ変わって行くのだ。カレンダー屋さえも困るぐらい変わりやがってコノヤロー。

 ロジックで組んでいた場合、法律改正とともにロジック変更が必要になる。設定ファイルで設定する場合も、その設定ファイルのメンテナンスが必要となるが、プログラマ未満のスキルの人でもメンテナンス可能であり、そーゆーことを考えると、設定ファイル案が有利だろう。


 設定ファイルのメンテ方針も意外とハマルところである。

 冒頭の某システムは設定ファイルを変更したら再起動が必要だった。

 まあ、休日を参照する処理が大量にある場合、起動時に読み込んでおきたいのは分かる。しかし、おいそれと再起動できないシステムにおいて再起動を要するのはいかがなものか。

 対処の運用におけるアプローチとしては、休日ファイルを書き換える日付を決めておくべきだろう。カレンダーが配布される時期になったら設定ファイルを書き換えて再起動すべしとドキュメントに書いておく。書いておくだけでなく、実行する。

 冒頭の某システムは、ドキュメントに書いてあったが、引継ぎでちゃんと伝わっていなかった。年次処理は抜け落ちやすい。類似のものにドメイン更新や、SSL証明書更新がある。


 対処のプログラムからのアプローチとしては、休日ファイルのキャッシュが考えられる。タイムスタンプが違っていたら読み込むとか、タイムスタンプを読み込むのもそこそこ時間のかかる処理なのでタイムアウト時間を設定して、タイムアウトしたらタイムスタンプを読み、新しかったらファイル読み込みとか。

 だが、例えば予約システムなどにおいて休日は予約できないとか料金が高くなるとか、そういったものがある場合に、予約済みの日付に対して休日平日が変わってしまうことが起こると面倒だ。そこらへんのガードも考えると結構面倒くさい。

Posted by rukihena at 23:57:04 | Comments [0] | Trackbacks [0]

2008年4月26日

プログレスバーの更新を必要最小限の間隔で行う

 表題のことを考えていたら、ブレゼンハム(Bresenham)の線分描画アルゴリズムが適用できそうなことに気づいた。

 以下、C言語風の擬似コード。

e=0
while ( !EOF ) {
 1行読み込み
 なにかの処理
 e+=1行の長さ*100
 if ( ファイル長 < e ) {
  プログレスバー更新
  e-=ファイル長
 }
}

 いまどき、線分描画アルゴリズムを用いて線分を描画するシチュエーションは稀だと思う。

 しかし、知っていると思わぬところで応用が利くなと思った。


 前提条件として、プログレスバー1%分が1行より大きい必要がある。が、プログレスバーを表示したいのだから、その条件は満たすだろう。

 満たさない場合は100%に到達せずに終わってしまうが、最後に100まで移動するコードを書いておけば、見た目はOKだと思われる。

Posted by rukihena at 01:00:57 | Comments [0] | Trackbacks [0]

2008年4月 1日

モバイルSOS

 というわけでエープリルフールなわけですが、例によって impress がやらかしています。

 ノートPCのディスプレイを点滅させて遭難信号を発信「モバイルSOS」

 GIFアニメはあるが、ソフトはない。

 このぐらいのソフトは作っとけよ!

 っていうか俺が作ってやる!

 完成↓
 mobileSOS.exe

 WIN32apiだけで作った軽量アプリ。ALT+F4 または ESC で終了します。

Posted by rukihena at 12:17:50 | Comments [0] | Trackbacks [0]

2008年1月14日

SIPで遊んでみる

 12月初旬にBフレッツ&ひかり電話を入れた話は書いてなかったか。

 ひかり電話を入れたら、RV-230SE というルータが来た。VDSLモデムとルータとひかり電話が一体になったモノである。

 これにアナログ電話を接続できるのはもちろんなのだが、SIPクライアント(VoIP端末)を接続することも可能のようだ。

 これは試すしか! と思い、フリーのSIPクライアントを探したら X-Lite というのがあったのでVistaマシンにインスコして設定してみた。

 設定項目が意味不明なものが多いが、いろいろググりながら適当に項目を埋めたら設定できた。

 しかし、パソコンを電話端末にするのは非常にまどろっこしい。

 多くの人が、パソコンを目の前にしながら横で電卓を使っているのと同様、電話は電話機で話したほうが65536倍使いやすいと思う。


 だが、ウチの電話にはナンバーディスプレイが無い。

 「着信お知らせメール」のオプションをつけているので、着呼後にメールで確認できるし、RV-230SE のログでも確認できるのだが、そんな未来に知ってもしょうがない。

 やはり、着呼したその瞬間に番号通知を見たい。


 これはナンバーディスプレイ専用SIPクライアントを作るしか!!!


 というのはひかり電話を入れた12月初旬から考えていた。

 で、突然プログラミングする気になり、実装してみた。

 使用言語(開発環境)は Visual C# 2008 Express Edition。

 SIP はよく分からんので、X-Lite と RV-230SE の通信を Wireshark(旧Ethereal) で盗聴して解析。

 通信には UdpClient クラスを利用。非同期メソッド使いまくりでマルチスレッドにはせず。

 着信イベントを通信クラスからUIクラスに渡す方法(イベントとかデリゲートとか)で苦労したがなんとか実装。

 ダイジェスト認証がさっぱり分からず、でもググりまくってなんとか実装。

 1日で、登録(REGISTER)→着信受信(INVITE) の動作を確認するところまで行った。


 あとはもうUIの世界で使いやすくしていくのみ!

 といいたいところだが、SIPは謎仕様が多い。RFC全然読んでないので謎なのは当然だが、なんか Uniq ID の類が多いあたりがわけわかめ。

 特に branch のマジッククッキーって何ですか? って全然調べてない。

 が、個人的には RV-230SE とだけ喋れればよいので、細かいことは気にせず、先に UI を実装しようと思う。

 今はまだいかにもサンプルなフォーム1個のUIなので、タスクトレイ常駐とか、電話帳逆引きで名前表示とか、そこらへんから手をつけようかなと。

Posted by rukihena at 21:51:15 | Comments [0] | Trackbacks [0]

2007年12月30日

Vista に Windiff


 Vista に Windiff を入れようと思った。

 Windiff は VC++6.0時代に重宝された、ファイル比較ツールである。UNIX の diff コマンドの GUI 版と思っていただけるとよいと思う(これで理解できる人がどれだけの割合で存在するか疑問だが)

 いまさら VC++ 6.0 を入れるのもアレなので、 Visual Studio 2008 Express Edition (Visual C++ 2008 Express Edition) をインストールしてみた。

 そしたら入ってなかった。


 いろいろググって見ると、Windows XP Service Pack 2 サポート ツールの中に Windiff が入っているっぽい。

 しかし、WGAを無事通過してダウンロードしたバイナリを実行しても、対応OSじゃない旨が表示されてインストールできない。たぶん、XPマシンにインストールして、exe だけコピってくれば動くとは思うのだが・・・。


 で、またまたいろいろググって見たら、.NET時代のソース・コード差分ツールとは? [@IT] を見つけた。

 WinMerge というのが .NET時代のツールらしい。

 日本語版もあるようだが、本家のインストーラーから入れても日本語表示できた。EUCなファイルが文字化けしたが、設定で「.html, .rc, .xmlファイルのコードページ情報を検出する」をオンにしたら文字化けしなくなった。

 それと多分 .NET時代 とはいえ、.NET Frameworkは不要だと思う。それと、タイトルに Vista を入れたが、Vista はあまり関係ない。

Posted by rukihena at 17:17:48 | Comments [0] | Trackbacks [0]

2007年8月 9日

GridViewのDataSourceが空の場合にヘッダが表示されない件

 ASP.NET 2.0 でメニーユーズされるGridViewはハイファンクショナリでコンビニエンスだ。

 ・・・ルー語は面倒くさいな。

 便利なのだが、機能が豊富すぎて何をどうしたらよいのか分からなくなることがある。

 今日困ったのは、データが空っぽの場合に何も表示されなくなる点。ヘッダだけ表示してほしい場面は多々あるだろう。

 一応、EmptyDataText というプロパティがある。これを設定しておくと、この文字列だけが表示される。だがボクはHeaderを表示してほしいのだ。

 EmptyDataTemplate というのもある。ここにヘッダ相当の記述を書けば一応は解決する。

 だが、同じことを2回書くのはイヤだ。作成時は問題ないと思うが、修正時にミスる可能性がある。

 失敗する可能性のあるものは、失敗する。

 失敗する可能性は排除しなければならない。


 ググりまくったが「日本語のページを検索」をONにすると解決策が見つからない。外してググったら、複数の掲示板からリンクされているブログを見つけた。どうやらこれが最善策らしい。

 Displaying GridView When No Data Exists

 これはGridViewを継承して、新しくEmptyGridViewという名のコンポーネントを作っている。.aspx での記述例が無いが、

 新しくコンポーネントを作る大げさ感と、EmptyDataTemplate を使って失敗する可能性を盛り込むのとを天秤に掛けて、どちらかを採用しましょう。


 仕様としては、プロパティが2つ増えている。

 ShowEmptyTable は、データが無いときにヘッダだけのTABLEを表示するかのブール値。デフォルトは True なので、通常は指定しなくても問題ない。

 EmptyTableRowText は、空テーブルのヘッダの下に表示するテキスト。

 個人的に不満なのは、フッタに対応していない点。なので対応させた。それとC#からVB.NETに移植した。

 GridViewX.vb.txt


 ところで、「失敗する可能性のあるものは、失敗する」で始まるマーフィーの法則の最新刊、21世紀版 マーフィーの法則が先月発売された。

 信頼性工学の入門書としてお勧めしたい(w

Posted by rukihena at 22:27:33 | Comments [0] | Trackbacks [0]

2007年8月 8日

ASP.NET 2.0 でトランザクション

 Webアプリにおけるトランザクションってのは、リクエストされたときに開始して、ページがつつがなく生成できたレスポンス時にコミットするのがほとんどであろう。

 その途中でなにかエラーがあれば、もちろんロールバックする。

 というわけで、意識的に書かなきゃならんのはエラー時のロールバックだけなんじゃねぇの? と思う。


 Web全盛から10年は経っているので、なんか便利な機能があるはずだ! と思って調べたら、ちゃんとあった。

 まず、.aspx ファイルの先頭に

<%@ Transaction="Required" %>

 を書く。

 これだけで、ページ全体が1つのトランザクションになる。

 あとは、エラー時に ContextUtil.SetAbort() を呼び出してロールバックさせるだけ。

Posted by rukihena at 22:41:12 | Comments [0] | Trackbacks [0]

2007年7月27日

ORA-12571: TNS: パケット・ライターに障害が発生しました

 某所でOracleを使っていると、たまに表題のエラーが出る。「ORA-12571」でググって見ると、謎の現象で解決しない例が多く見られる。

 原因がさまざまであり、対策もさまざまなのだろう。

 ここの環境では、一定時間通信しなかったあとでクエリを投げると出るようだ。

 これはどうも、DBサーバまでの間にあるファイアウォールがTCPコネクションを切断してしまうため出ているようだ。

 ファイアウォールではNATしているので、NATテーブルの飽和を防ぐために、一定時間アイドルだったTCPコネクションをNATテーブルから消してしまう。

 また、NATしていなくても、TCPセッションハイジャックなどのリスクから回避するために、SPIでフィルタしてしまっているなんていう環境もあったりするだろう。

 ネットワーク環境的な回避方法だと、キャッシュ時間を延ばす方法が考えられるが、むやみやたらと長時間にするわけにもいかない。


 そこでクライアント側の設定での回避策。(3階層アプリならWebサーバでの設定)

 TNSNAMES.ORA に (ENABLE = BROKEN) を追加する。追加する場所は以下のとおり。

HOGE =
(DESCRIPTION =
(ENABLE = BROKEN)
(ADDRESS_LIST = 〜

 それに加えて、レジストリをいじってTCP KeepAlive パケットの送出間隔を短くする。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
KeepAliveTime DWORD:0x493E0

 ここで設定する値の単位は ms.

 上記の 0x493E0 の場合は 300000msで 300秒で、すなわち5分。これは間にあるファイアウォールのNATテーブルタイムアウト時間より短い値に設定する。

 利用者(ファイアウォール配下の端末数)が少なければ、1分とかでも問題ないだろう。それ以下にするのはちと勿体無い感じがする。

 ちなみにデフォルト値は2時間だ。長すぎる。

 これらの設定を組み合わせることにより、設定した間隔でKeepAliveパケットが流れるので、ファイアウォールがタイムアウトで切断してしまう現象が出なくなる。

 さて、例によって定型文。レジストリの書き換えは自己責任で。書き換え後は再起動が必要。

Posted by rukihena at 00:07:26 | Comments [0] | Trackbacks [0]

2007年7月 7日

SQLインジェクション対策

 今更だが、SQLインジェクション対策の話。

 対策方法はただひとつ。SQL文を生成(文字列連結)するときに入力文字列をエスケープすること。

 SQL文を生成した後でエスケープしようとしても、そこにある文字がエスケープすべき文字なのかどうかは判別不可能だ。また、SQLインジェクションが発生しているかどうかを検知するのも不可能だ。構文エラーになっていたら検知できるが、それは仮に実行してしまってもエラー終了するだけで大きな副作用は発生しない。また、実行できるSQL文になっていたら、それがSQLインジェクションなのかどうかは機械的には分からない。

 「マルチステートメントなら実行できない」といった程度の対策なら可能だ。しかし、SQLインジェクションが成立するにはマルチステートメントが必須なわけではないので、それで対策完了というわけには行かない。


 で、連結時にエスケープしようと思うのだが、これも結構厄介だ。調べれば調べるほど、危険な文字の存在に気づかされる。UTF-8などのわけわからない空間から攻撃されると困ってしまう。

 そこで、普通は prepared statement (プリペアドステートメント:準備された文) あるいは parameterized query (パラメタライズドクエリ)を用いる。

 これなら、何をブチ込んでもそれなりに解釈されて、そのままDBのフィールドにブチ込んでくれる。

 もちろん、' (シングルクオーテーション)などもそのまま格納可能だ。

 大量の音楽に対して 「80's J-POP」みたいなカテゴリをつけたいときなどには非常に重宝する。

 それでも例外がひとつあり、LIKE句の時だけは % と _ を変換しなければならない。


参考:第2章 セキュアDBプログラミング [2-1.]SQL組み立て時の引数チェック

Posted by rukihena at 00:09:44 | Comments [0] | Trackbacks [0]

2007年1月22日

Webスクリーンショット取得

 Webスクリーンショットは簡単そうで難しい。特にクローラで収集したような雑多なサイトに対して取ろうと思った場合に様々な地雷が・・・。

 画面サイズはどうするのか、縦長の場合にどうするか、アニメーションGIFやフラッシュなどはどのタイミングの画像を採用するか、などなど。

 ポップアップも邪魔なものであり、JavaScriptで出てくるものや、IE自身がセキュリティ警告で出してくるものなど、さまざまなケースに対応しなければならない。JavaScript OFF にすれば緩和されるかもしれないが、最近はAjaxサイトで困ることが多いだろう。

 それと、レンダリングエンジンはIEを採用しないと意図どおりにレイアウトされないサイトがあるので、Windowsが必須である。


 という苦労は過去の話なので今は全然必要ないのだが、30分で作れるWebキャプチャ作成phpを読んだのでメモしとく。

 つまりはCrenaHtml2jpgを呼び出すだけですな。

Posted by rukihena at 00:43:13 | Comments [0] | Trackbacks [0]

2006年12月19日

Visual Studio 2005 Professional Edition をインストールした

 ものすごく久しぶりにマイクロソフトの開発環境をインストールした。

 ボクの実地体験は VS6.0 で止まっており、すなわち .NET での開発をしたことがない。それでも .NET の概要は各種記事から知っているつもりだ。


 で、インストールなのだが、まず、どのメディアを使えばいいのか悩んだ。

 MSDN サブスクリプションのディスクを見ると、「Visual Studio 2005 Professional Edition」と「Visual Studio 2005 Professional Edition Disc 1」と「Visual Studio 2005 Professional Edition Disc 2」がある。なぜDisc番号の付いていないのがあるのだ!?

 相当悩んで、とりあえず番号の付いてないのをPCのドライブに入れてから気づいた。それはDVDだった。DVDなので1枚に収まっていた。

 CDとDVDは大きさが同じで困る。ラベルに透過部分が多ければ記録層の位置でDVDの区別が付きやすいんだけど、今のMSDNのディスクはベタ塗りなので気づかなかった。CDとかDVDを意味するロゴを見ればいいのだが。


 インストールは適当に次へ次へで終了。ちなみに「標準」ではなく「全て」を選んだ。「全て」だと、C++ に 64bit 対応が付くのと、なんかのサンプルが付いてくる点だけ違った。容量で1割up程度なので気持ちよく全てを選んでしまえ、と。

 次に、SP1を当てるかどうかで悩んだ。リリースが昨日じゃねぇか。とりあえず保留。


 さて、今回の仕事は VB.NET を使うらしいので、いじってみた。VBの経験は業務でやったようなやらないような、記憶が無いのだが、プログラムを書いている途中でコピペしようとして行を移動すると文法エラーのダイアログが出てOKボタンを押すのがウザイという記憶はある。なんで使ってたんだっけかな。思い出せない。

 VB.NET ではそんなにウザく無い感じでいろいろ支援してくれる。なんか Eclipse を使っているような錯覚を覚えるんですが。Eclipse を使っているのに VB 風味の文法で、ライブラリは .NET で、非常にキモチ悪い。

 文法もライブラリも知らないので、ちょっとしたことでもググってサンプルを見ないと書けないのでイライラしてくる。

 でも、適当に Hashtable あるかなと思ってタイプするとインテリセンスが補完してくれて、ああ、あるんだなと思ったりして、やっぱインテリセンス最高。[F1]キーでヘルプ連動とか、懐かしすぎて涙が出てくる。


 あと、Professional Edition は CE 向けの開発も出来るようなので、何か作りてー!っつーか、無意味にCEマシンが欲しくなっちゃうぞ!! ・・・見なかったことにしよう。

Posted by rukihena at 21:33:59 | Comments [0] | Trackbacks [0]

2006年12月 8日

ココログがタイヘンなことに

 そもそもココログのベースであるTypePadのベースであるMovableTypeを開発したSix Apartに、計算機概論みたいな知識が無いのが原因のような気がする。

 エントリ数とかコメント数とかトラックバック数が増えたときに対数オーダーで処理時間が増えるのなら良いのだが、指数関数的に増えてないか!?と思うのだ。ベンチしてないけど。

 Six Apartの中の人は情報処理工学科に入学して、時間計算量とか空間計算量とかランダウの記号とかを勉強しなおしたほうが良いと思う。

 ボクは勉強してないけど。

Posted by rukihena at 01:01:07 | Comments [0] | Trackbacks [0]

2006年12月 1日

オルソ化空中写真ダウンロードシステムとGoogle Maps APIのマッシュアップ

 でっかいJPEGを扱う で書いた、国土交通省のカラー空中写真を Google Maps API で重ねてみようとした話の続き。

 いろいろググっていたらオルソ化空中写真ダウンロードシステム(試作版)ってのを見つけた。オルソ化とは、緯度経度をピッシリ合わせてGIS的に利用しやすくすることらしい。

 オルソ化空中写真ダウンロードシステムとはを読むと、ISO19128のWMSインターフェイス云々書いてある。

 WMSって良く分からんが、Google Maps に貼りやすそうな予感。

 で、これを作った。↓

 オルソ化空中写真ダウンロードシステムとGoogle Maps APIのマッシュアップ

 使い方のコツとしては、広域方面に縮小できないので、他の場所に移動するときは表示モードを「地図」などに変えて移動して拡大して「国交省」モードに戻すと良いでしょう。

 楽しみ方としては2つ。

 国土交通省の写真は平成初期あたりなので、ちょっと古い町並みを体験できる。例えば東京都庁新庁舎やレインボーブリッジは工事中だし、フジテレビ新社屋周辺は更地だし、パレットタウン(トヨタメガウェブなど)に至っては海である。

 あとは、月並みですが、Google Mapで詳細な航空写真が無い地域を見て楽しみましょう。(どちらにも無い場合もありますが)


 万が一、人気コンテンツになってしまうとサーバーが大変そうだが、ウチのサーバーにはあまり影響が無い。ウチのサーバーは index.html を吐くだけで済む。タイヘンなのは Google 様と、国土交通省様。

 本当は画像をキャッシュしてユーザビリティの向上と国土交通省サーバの負荷軽減を図りたいのだが、規約上コピるとマズそうなのでキャッシュは止めた。

Posted by rukihena at 07:44:52 | Comments [0] | Trackbacks [0]

2006年11月16日

でっかいJPEGを扱う

 Google Maps API をいじっていると楽しくてしょうがないので コレを貼り付けて遊んでみようかと思った。

 しかし、3800x3800ピクセルぐらいのデッカイ画像なので読込展開にスゲー時間がかかる。1枚当たり1.7秒ぐらい。Google Maps API のタイル単位に PHP で処理しようとすると、タイル生成要求ごとに読込展開してしまう。初回アクセス時に25枚ぐらい読み込まなきゃならんので、25×1.7秒という長大な時間が掛かってしまってダメダメだ。

 Java Servlet なら、JPEG展開済み画像オブジェクトを管理するクラスを作ってメモリに常駐させてどうにかするのだが、PHPだとそーゆーのって無理だよな。(ボクが知らないだけかもしれないが)

 Perl だと mod_perl を使えばなんとかなるかもしれないが、ちょっとトリッキーな感じがする。そこまでするならJavaれよ、みたいな。


 しかし、Javaるには、環境のセットアップとかがあって面倒なので、PHPでなんとかしたい。

 JPEGの指定した一部分だけを読込展開できれば、高速化できるんじゃないかと思った。今までのプログラムは、全体を展開してから、その一部分だけを採用しており、要らない部分まで展開処理をしていて無駄である。

 JPEGは8x8ピクセルのブロックごとに圧縮して格納されているので、要らない部分の展開をサボっても一部分だけ取り出せるはずだ。

 そして、さんざん調べた結果見つけたのが jpegtran コマンドの -crop オプション。Loss less で部分取り出し!

 で、使ってみたら 0.8秒ぐらいになった。2倍の高速化!

 でも、それでも遅いよなぁ。

 やはり、Javaとかでオブジェクトプーリングを実装しないと実用にならん。

 つーか、タイル画像を全部プレ変換してディスクに置いとくのが一番速い。

Posted by rukihena at 00:41:18 | Comments [0] | Trackbacks [0]

2006年11月13日

GTileLayer.isPng() の使い方

 Google Maps API で GTileLayer を使おうとしたとき、実装に悩むのが isPng() である。悩まずに PNG ならtrueを返せば良いような気もするが、どうも値を見ているのか見てないのか良く分からない挙動をする。

 イロイロ実験してみた結果、PNG の alpha blending(半透明)を使いたいときに ture を返すよう実装するものらしい。


 なぜこのメソッドが存在するのか。

 IE6は、PNGに対応しているが、アルファブレンディング付きのPNGにはちゃんと対応していない。重ねて表示したときに、半透明してくれない。だがコレには回避策があって、AlphaImageLoaderフィルタを使えば良いらしい。

 ということでおそらく、isPng() は IE6 の時にAlphaImageLoaderを使うか使わないかを指定するものなのではないだろうか。


 だがしかし、isPng() を true にすると、なんか挙動がおかしくなる。初回表示はいいのだが、ブラウザのキャッシュに乗っている画像(地図)を表示しようとすると画像が抜けてしまうことが頻発する。

 回避策が分からず困っているんですが、どうにかならないですかね。

 IE7では試していないが、AlphaImageLoaderを使わなくても正しく扱えるようになっているらしいので、この問題も起きないだろう。Windows Update でIE7が強制配布される半年後からはIE6を無視して半透明を使いたい気分。

 ちなみに、透過GIFなら isPng() とか getOpacity() を実装しないでも(getTileUrl()のみ実装するだけで)フツーに重ね合わせて、透過部分は透過されて表示できる。あ、もちろんGIFだから半透明は出来ないケド。

 IE7が普及するまでは、GTileLayerには透過GIFを使うのが良いような気がするのでした。

Posted by rukihena at 01:04:41 | Comments [0] | Trackbacks [0]

2006年11月 7日

GTileLayer のサンプル

 GTileLayerとメルカトル図法の続き。


 サンプルを公開してみる。

 GTileLayerのサンプル

 タイル生成はPHPで行っている。ソースはコチラ

Posted by rukihena at 00:07:36 | Comments [0] | Trackbacks [0]

2006年11月 5日

Ajaxはサーバー負荷が軽い

 Ajaxはサーバー負荷が軽いってことに、今さらながら気づいた。

 例えばGoogle Mapsは、地図をマウスでグリグリ動かしてもサーバーへのリクエストは256x256pxの静的画像の取得のみであり、サーバーは動的なページ生成を行う必要が無い。

 近くのラーメン屋とかを検索すれば、動的なクエリが発生するが、それでもサーバー側はテキトーなXMLを吐くだけで良く、レイアウト込みのHTMLを作る必要が無い。

 Ajaxじゃない地図だと、クライアント側で表示させたい画像やHTMLを全てサーバー側で生成する必要がある。画像の切り貼り処理と、マーカーのプロット処理をし、さらにHTMLも作って、と大忙しだ。


 Ajaxにおけるパフォーマンスチューニングのツボは、「クライアント側で出来ることは極力クライアントに任せる」というところにあるのかも。

 クライアントサイドスクリプトが多少遅くても、ユーザー数が増えたところで速度に変わりはないが、サーバーサイドプログラムが遅いとユーザー数に比例して遅くなってしまう。

 クライアント処理を増やすのは、究極の負荷分散だなと思った。

Posted by rukihena at 23:17:03 | Comments [0] | Trackbacks [0]

2006年10月29日

GTileLayerとメルカトル図法

 Google Maps API の話。

 GTileLayerを利用すると画像の重ね合わせをすることが出来る。

 詳細は端折るが、ここで引数として渡されてくる値が、緯度経度でなく、平面座標の x,y になっている。

 この値を JavaScript の中(クライアント側)で緯度経度に変換するのはカンタンだ。Google Maps API に任せてしまえばよい。

 しかし、サーバー側でプロットとかしたいなら、サーバー側が変換式を知っていなければならない。

 Google Maps はメルカトル図法を用いているので、それの変換が必要だ。

 ググってみると、緯度→Y座標 の式は見つけることが出来た。(経度→X座標はそのまんまなので問題ない。)

 しかし、Y座標→緯度 の式がなかなか見つからない。緯度→Y座標 から逆関数を求められるほどボクは頭よくない。

 さあ困った困ったとググリ続けて数時間。メルカトルとかMercatorとか投影とか逆投影とか逆変換とかtanとかatanとかイロイロ思いつく言葉を入れたが見つからない。

 ふと発想を変えて、英語のWikipedia を見てみた。

 そしたらあった。

 Mercator projection

 最初からココ見りゃ良かった・・・。

Posted by rukihena at 20:43:41 | Comments [0] | Trackbacks [0]

2006年10月20日

測地系変換で悩む(2)

 昨日の続き。

 だんだん頭の中が整理されてきた。

■世界測地系

・ITRF2000
  超高精度。緯度経度のほかに時刻情報(年)が必要。
  何で年が必要なのかと言うと、プレートテクトニクス理論の補正のため。
  すなわちcm単位の精度。

・JG2000=ITRF94=ITRF96=ITRF97

  単に世界測地系と言ったらコレなのかな。

・ITRF90・ITRF91・ITRF92

  よく分からんが、微妙な誤差があったのかな? 1990年代前半の規格と思われるので無視

・WGS84
  GPS用。WGS84といっても微妙なバリエーションがある。
  しかし、そもそもGPSの精度が微妙なのでバリエーションはキニシナイ。
  精度数mの観点なら、JGD2000とかと一緒。

・まとめ
  精度数mの観点なら、全部一緒。


■日本測地系

・Tokyo97
  厳密な意味での日本測地系。
  測量網の誤差が含まれているので、世界測地系への変換には「地域毎の座標変換パラメータ」なるものが必要。
  誤差は場所によっては100m単位。特に離島。
  GPS普及以前に、明治時代の基準点を使って3点測量した座標だと、コレになる。
  地図に多く見られる。

・Tokyo3p
  測量網誤差がないモノ。
  GPSで計測して、幾何変換で日本測地系にした座標だと、コレになる。
  最近作られたデータに多く見られる。
  正式名称は無い。Tokyo3p の命名は コチラ


■で、どうすれば?

 ここでは精度数mのレベルで考えます。

 そうすると、世界測地系は全部一緒と考えられる。日本測地系は世界測地系から単純変換したTokyo3pと、測量網誤差入りのTokyo97がある。つまり、3種類の測地系が存在すると。

 で、文字コード変換におけるチルダ的存在に相当するは石垣島とか与那国島。

 WILLCOMのエリア確認ツールで石垣島(の隣の竹富島)を見ると、アンテナが海上にある。これは、アンテナ位置はTokyo3pで、地図はTokyo97を採用しているためにズレているのではないかと思う。

Posted by rukihena at 23:10:20 | Comments [0] | Trackbacks [0]

2006年10月19日

測地系変換で悩む

 こんなのを作ってみた。

 WILLCOMのアンテナの位置を Google Maps API でプロットするものである。


 で、本題。

 WILLCOMの位置情報は日本測地系を採用しているらしく、世界測地系のGoogle Mapsにプロットすると位置がずれる。なので測地系変換をしなければならない。

 測地系変換が必要なのは以前から知っていた。少なくとも測量法改正の2002年の時には知っていた。

 だが、いざ変換してみようと思って調べたら奥が深すぎる。

 日本測地系と言っても微妙なバリエーションがある。世界測地系もバリエーションがある。準拠楕円体が微妙に違うとか。

 それだけならいいが、測地網の誤差ってのもある。明治時代に決めた全国各地の基準点がずれていて、ずれたまま地図が作られてしまっているのだ。

 いろいろあるので、そもそもWILLCOMが日本測地系の微妙なバリエーションの中のどれを使っているのか分からず、どんな変換をすればよいのか分からなくなった。

 Google MapsもWGS84でいいのかよくわからんし。


 文字コード変換の世界でも、微妙なバリエーションがある。単純な機械的計算だけで済む変換とか、テーブルが必要な変換とか。

 そっちの世界であれば、機種依存文字を正しく変換できるかとか、チルダを正しく変換できるかとか、検証すべき地雷源を知っている。

 しかし、測地系変換だとそのようなノウハウが無い。ウチの近所がズレずに変換出来てればOKかなとか思ってしまう。

 測地系変換しまくりの人だと、北海道とか九州とかのズレを見て、採用測地系が分かってしまうような能力をつけてしまっているんじゃないかと想像する。また、測地網の誤差に関しても、「この島はスゲーずれるんだよな」とか、そんなポイントを知っているんじゃないかと思う。文字コード変換におけるチルダのように。


 そんなことを考えつつ、幾何変換すら面倒で単純な平行移動だけでごまかしたらやっぱり稚内でズレている。東京・大阪あたりはズレていない模様。

 しかし、ウチの最寄のアンテナ位置が現物目視確認の位置からズレている。と思ったらWILLCOMの地図でも同じようにズレていた。

 頭混乱中。

Posted by rukihena at 23:10:21 | Comments [0] | Trackbacks [0]

2006年9月22日

ブラウザのサイズ

 ユーザーはブラウザをどんなサイズで使っているのか。

 いい加減、画面サイズ800x600を意識する必要は無いだろう。しかし、幅800でも横スクロールなしで表示できるようにはしておきたい。1024x768の画面で、800幅のウィンドウを開くのが、マルチウィンドウシステムとしては最適なような気がするからだ。

 幅800は業界スタンダードでもある。たとえば Yahoo! のトップページは幅800になっている。

 800が基準なのだが、800固定と言うのもキライだ。ユーザーがウィンドウ幅を広げたら、広げたなりにウィンドウいっぱいにコンテンツを表示させたい。

 もちろん、このブログはそういう仕様になっている。


 ウェブページをデザインするときは、いろんな幅を試してみることが多い。いや、ウェブページに限らず、GUIモノを作るときは適切なサイズを意識しなければならない。メインで使用している画面は1400x1050なのだが、1024x768で表示すると狭すぎないだろうかとか、800x600でも最低限機能するだろうかとか考える。

 それを試す際、ボクはWindows付属アプリのペイントブラシを使っていた。具体的には次のような感じ。

 [WIN]+[R] pbrush [ENTER] でペイントブラシ起動 → キャンパスサイズを 1024x768 に指定 → テスト画面をそれに合わせる


 だがそれが面倒くさい。

 いろいろ考えて、液晶の縁にエンピツで線を書いた。左上基準だけの線を引くとバランスが悪くカッコ悪いので、全方向から上下左右対称に線を引いた。

 うぉースゲー便利だぜ。

 線を引いて思ったのだが、コレを基準に液晶の背面まで黒い線を引いたら仮面ライダーカブトのゼクトが持っているPCっぽくなるかも。

 ゼクトデザインだけど実用の意味もある線。

 カッティングシート買ってきて貼り付けるかな。

 いや、でも、VAIOロゴが中途半端に半分隠れてカッコ悪くなるなぁ。

Posted by rukihena at 23:09:23 | Comments [0] | Trackbacks [0]

2006年9月19日

GPolyline.fromEncoded

 Google Maps API を使って経路を書く話。

 先日コンナモノを作ったわけだが、車輪の再発明だった。

 APIドキュメントを読んでいたところ、GPolyline.fromEncoded が目に留まった。

 Google謹製Polylineフォーマットですか!!!

 ボクが考えたのは64進数でデータ長ヘッダを持たせる戦略なんですが、Google謹製では32進数にデータエンドビットを加えて64キャラクタ使ってます。

 そしてGoogle謹製の方が短い文字数で表現できてしまう!

 さすがGoogleの中の人は頭良いな。


 ということで今後は fromEncoded のフォーマットを使うことにしよう。

 一応、旧フォーマットを読み込ませることも出来る。その場合も、下に表示される完成URLはGoogle謹製フォーマットになっている。

 それと、経路に沿ってスクロールする機能を付けてみた。しかし、スクロールが速過ぎて見にくい。酔う。改善の余地あり。


 参考例として、ウチのナビで、よみうりランドから港北ICへルート検索した結果を示してみよう。

 よみうりランド→港北IC

 ゆりがおか駅付近で左折した道は狭かった。なぜそこを選んだ?

 あざみ野駅付近で混雑した。VICSで駅東側道路が渋滞していることから西側を走らされたが、そっちも混んでいた。

Posted by rukihena at 23:09:20 | Comments [3] | Trackbacks [0]

2006年9月15日

ルートデルタ

 きのうの続き。

 数字を単に10進数で表現するのは勿体無い。かといってバイナリの表現はURLパラメータにできない。%xxで表現できるが、余計に伸びてしまう。

 BASE64のように、使えるキャラクタだけ用いて64進数で表現したらどうだろうか。BASE64にはURLパラメータとして使えない文字があるからそれは別の文字に置き換えよう。

 これで、5桁+5桁ぐらいで表現できるかな。しかし、これでも大きい。

 緯度経度は、前回の地点からの差分を取ると、小さい数字になるだろう。それを可変長フォーマットでつなげていくとかなり圧縮できるのではないだろうか。

 可変長だと、データ長を示すヘッダが必要になる。ヘッダには緯度経度それぞれのデータ長が必要だ。それに2ビットずつ使おう。2ビットなので0〜3になる。3桁だとオーバーフローしそうなので、3のときは4桁と定義しよう。0桁は意味無いからな。0は1桁だ。さらに、符号も必要だ。初めは補数で表現しようかと思ったが、可変長データの補数は面倒だ。符号用のビットもちょうど余っているので使おう。

 ということで、ヘッダは 緯度符号(1bit)・緯度データ長(2bit)・経度符号(1bit)・経度データ長(2bit) の計6ビット。ちょうど64進数の一桁を使うことになる。

 そのあと、緯度経度の差分値を並べる。

 これで1つの点の表現が完成。ヘッダ1文字+緯度1〜4文字+経度1〜4文字=3〜9文字で1つの点。

 最初の点だけ困るな。4桁だと全世界を網羅できない。日本のどこか適当な場所を基準点として、そこからの差分にしようか。

 などなど考えて作ったのがコレ。

 ルート (ルートデルタ)
 ルート 説明書

Posted by rukihena at 23:09:18 | Comments [0] | Trackbacks [0]

2006年9月14日

ルートマップ

 Google Maps API って、地図上に線を引けたりするんで、道順を線で引けたら便利だよな。と思った。

 APIが公開されてしばらく経つので、同じことを考えている人は多くいるだろう。

 ということでググッて見たら、そんなサイトを2つほど見つけた。

経路マップ
地図Z

 尚、前回書いた実用ジオコーディングの存在は、これらを見て知った。


 さて、これらは両方とも、経路データをサーバー側に持つようになっている。違いは、DBのキーの取り扱いについての思想だ。

 経路マップの場合はランダムな値(多分GUID)を用い、作成者だけが知ることになる(もちろん、作成者が他人に教えても良い)。

 地図Zの場合はシリアル値を用い、作成されたルートは全てリストに掲載されてしまう。

 「俺んちへの道順はコレだぜ!」などという私的な地図を作成する場合、地図Zは都合が悪い。また、経路マップの場合も、第三者のサーバーに経路データを置くわけで、気になる人は気になるだろう。

 サーバー側に経路データを置かないとすると、URLパラメータに全てのデータを入れなければならない。しかし、仮に緯度経度をフツーに表現すると、1つの地点だけで20文字になってしまう。10地点で200文字。多すぎるよな。

 つづく

Posted by rukihena at 23:09:18 | Comments [0] | Trackbacks [0]

2006年9月13日

ジオコーディング

 ジオコーディングとは、住所などの情報から緯度経度を求めることである。それをやるモノをジオコーダという。

 というのは最近知った話。気づいたキッカケは Google Maps API のドキュメントを読んでいたところ、Geocode に関する記述があったから。

 しかし、日本国内では、このAPIを呼んでもエラーが返るだけ。使えないのかよぉ。残念。


 でも、別のソリューションがあった。

Google Maps APIで日本の住所から緯度・経度を求める方法

 なぜ、こっちでは利用できるのか不明。有名になっちゃうと使えなくなっちゃったりして?

日本版 Yahoo! Widgets の地図情報ウィジェットの裏側にジオコーダが!

 いいっすね。コレ。でもこれも地図情報ウィジェットのアップデートとともに対策されそうな予感。

位置参照技術を用いたツールとユーティリティ

 これは、東京大学空間情報科学研究センターがやっているRESTサービス。実験なので利用制限が厳しそうと思ったが、商用利用も可能なようで。


 他にも商用製品があったりするが、よく分からんので省略。やる気のある製品なら 周りの AdSense に表示されているかも。

Posted by rukihena at 20:46:15 | Comments [0] | Trackbacks [0]

2006年9月 7日

うるう秒廃止?

 1秒の定義は、昔は地球の自転から決めていたが、今は原子時計が決めている。自転の方が揺らぎがあって正確ではないからだ。

 だが、原子時計が決めた時間で刻んでいったら、自転と合わなくなり、太陽の動きと時刻がリンクしなくなって不都合がある。

 ということで、うるう秒で補正する。


 だが、うるう秒の補正は面倒くさい。面倒なので1時間単位で補正してやれ! という話がITUの中にある。

 事実上の先送りだ。1年に1秒ずれたとしても、3600年は補正の必要が無い。100世代後の子孫も安心!


 個人的には、日常生活用の時計は秒の長さを可変にして、常に補正しつつ、うるう秒は必要としない運用が良いかなぁと思う。秒の長さの厳密性が重要な分野だけ、原子時計な時間を使えば良いんじゃないの? と。

 しかし、よく調べたら、1958年から1972年までは、そうしていたらしい。→協定世界時

閏秒によってずれを補正するようになったのは1972年からである。それまでは、地球の自転の変動にあわせて原子時計の周波数を一定値オフセットして世界時の進行に近似させ、必要に応じて0.1秒のステップ調整を行うことで、世界時とのずれが常に0.1秒以内になるようにしていた。しかし、周波数のオフセット値を毎年調整する必要があり、これは困難なものであった。そのため、1972年から1秒の閏秒による現在の方式に変更された。

 高度情報化社会の今なら、オフセット調整も面倒じゃないと思うけどな。


 ところで、時刻の表現方法に、ISO 8601というものがある。これを知らないプログラマはモグリだ!

 というのはウソで、ボクも使っているところを1度しか目にしたことが無い。XMLやってるときだったかな?

Posted by rukihena at 20:40:13 | Comments [0] | Trackbacks [0]

2006年8月29日

サーバーサイドで画像回転

 サーバーサイドで画像を回転させたくなった。

 system 関数で convert コマンドを呼べば一発だろう。しかし、system 関数はあまり使用したくない。コマンドの起動、すなわちプロセスの生成はコストの高い処理だ。

 できたらモジュールを使って回転させたい。

 最初、PHPで作ってみた。PHPで画像処理というと、GDを使ったImage関数群がよいだろう。で、回転関数を調べたら imagerotate が見つかった。しかし、この関数だけ、呼び出したときに undefined とか言われる。スペルミスか? ドキュメントからコピペだ! それでもダメ。

 ドキュメントにはこう書いてある。

注意: この関数は、PHP がバンドル版の GD ライブラリでコンパイルされている場合のみ使用可能です。

 意味分からん。Debian で aptitude install php4-gd してインスコした環境ではダメなのか。これだけのためにPHPを make すんのは面倒だよなぁ。


 PHP がダメなら Perl を使ってやる!

 ということで Perl のモジュールを調べ始める。

 Perl GD で、同じ地雷踏んだらイヤだな。PerlMagick を使ってみよう。aptitude install perlmagick でインスコ。

 しかし、Rotate関数を使ってみたら遅かった。角度指定が任意角度なので、90度回転であっても真面目に一次変換とかしているのだろう。ボクは90度回転に特化した高速処理をしたいのだ!

 Transpose がそれなのか? いや、これは縦横入れ替えだ。x軸 y軸 を単に入れ替えるので、画像が鏡像になってしまう。


 PerlMagick 捨て。次は Perl GD だ。PHP GD で制約があったのでちょっと不安だが、aptitude install libgd-gd2-perl でインスコ。

 その結果、copyRotate90 で高速回転できた。

Posted by rukihena at 23:08:30 | Comments [0] | Trackbacks [0]

2006年6月28日

窪塚電卓

 ちょっと思うことがあって、作ってみた。水平方向に物を投げて、高さ h, 水平距離 d の地点に落ちた場合、初速度は? という計算機。(ただし、空気抵抗は無視できるものとする。)

 名前の由来は言うまでも無い。何故今日作ったかというのも言うまでも無いかな?

重力加速度 g[m/s2]
高さ h [m]
水平距離 d [m]
落下時間 t [s]
初速度 v [m/s]
初速度 v [km/h]
Posted by rukihena at 23:47:11 | Comments [0] | Trackbacks [0]

2006年5月23日

TaskbarCreated

 あのー、アレ、デスクトップの右下にある、アイコンが並んでいるところ。なんて言うんだっけ? タスクバー? それはスタートボタンも含む下側全体のことでは?

 タスクトレイか。いや、システムトレイかな? ググッて件数を見ると、日本語だとタスクトレイが多い。英語だと、system tray が多い。

 つーか、XPからは「通知領域(Notification Area)」って言うんですか?

 名前はどうでも良いので、以下「アレ」と表記する。


 エクスプローラーが落ちると、勝手にエクスプローラーが再起動して「アレ」も修復される。しかし、一部のアプリは修復されずにどっかに消えてしまう。タスクマネージャで見るとプロセスは残っているので、「アレ」から消えただけのようだ。しかし、UIが「アレ」からしか出来ないアプリの場合は困る。困るので ログオフ→ログオン を強いられる。

 ノウハウのある人が作ったアプリは、ちゃんと復活するように出来ている。僕が使用しているアプリではどうか調べてみた。


 まとめ

 ○ハードウェアの安全な取り外し
 ○PowerPanel(VAIOの電源管理アプリ)
 ○Skype
 ○MSN メッセンジャー
 ○秀丸
 ×WPBF(メールチェッカ)
 ○ワイヤレスネットワーク接続
 ○TeraTerm
 ○IME Watcher
 ×CheckIt(メールチェッカ)
 ○音量
 ○Yahoo! メッセンジャー
 ○バッテリーメーター
 ○DAEMON Tools
 ×QuickTime
 ×Picasa2
 ×Touch Pad(VAIOのタッチパッドアプリ)
 ×ATIアイコン
 ○無線LAN機器の選択

 個人的にはメールチェッカが消えるのが痛い。(2種類利用しているのがナゾな感じだが、仕事用と個人用で別アプリを使っているから。)

 さて、復活の方法ってどうやるんだろうと常々思っていた。しかし、別に「アレ」登録アプリを作るわけでも無いので調べずにいた。

 そんな中、今やっているテストの仕事で、テスト対象アプリが同様の穴にハマっているので気晴らしに調べてみた。

 で、コレ。http://www.microsoft.com/msj/0299/c/c0299.aspx

 キーワードはTaskbarCreatedの模様。

Posted by rukihena at 22:27:10 | Comments [0] | Trackbacks [0]

2006年2月19日

耳ベンチ集計のグラフ

 昨日書いた耳ベンチの下にある「耳ベンチ集計結果」のグラフ生成の話。

 グラフの生成には1秒ぐらいの時間がかかっている。これを表示のたびに生成していると、サーバに負荷がかかる。1日は86400秒しかないので、万が一ページビューが増えた場合、8万アクセス/日 程度でサーバーはパンクすることになる。

 グラフの生成の処理には、高速化の余地は無いだろう。単純なSQLと、単純なグラフ描画だけだからだ。

 しかし、システム全体でみると、大幅に高速化する方法がある。それは、登録のときだけグラフ生成処理を動かす方法。なにもページリクエストのたびに生成しなくても、データが更新されたときだけグラフを生成しておけば事足りる。

 話は変わって、グラフにバグがある。低周波の方はサンプル数が0の項目があり、その部分は抜けているので、Y軸の目盛りが飛び飛びだ。SQLの group by を使ってラクをしたことによる副作用である。でも、1項目づつSQLを発行するのもアレだしどうしようかなと悩みつつ、放置。

Posted by rukihena at 23:00:59 | Comments [0] | Trackbacks [0]

2005年11月15日

MVC分離しろ!

 某Webアプリケーションで、データの登録・削除はできるが、修正機能が無いものがあった。修正したい場合は削除してから登録しなおす。しかし、データ量が多いと再入力の手間がもったいない。ということでユーザーが修正機能を希望した。

 閲覧機能と登録機能を混ぜて作成した。閲覧機能で修正前のデータをとってきてフォームに表示し、その後は登録機能に投げる。

 しかし、バグを入れてしまった。

 閲覧機能では、空文字列をテーブルに表示した際にレイアウトが崩れるのを防ぐため、データが空文字列なら全角スペースに置き換える処理が入っていた。それをそのままコピペしたため、修正機能を使ったときにフォームに全角スペースを突っ込んでしまい、意図せずに全角スペースへ修正されてしまう。

 「空文字列を全角スペースに置き換える処理」は、HTMLの都合でそうするのだから、MVC でいうところの View でやるものだと思う。しかし、Model部分で行っていた。元のプログラムがViewでやっていたのなら、ボクもその余計な処理に気づいて削除していただろう。

 このWebアプリケーションは、某社独自のフレームワークを利用しており、そのフレームワークはMVC分離を強く思想に盛り込んだものである。しかし、プログラマがそれを理解せずにコーディングしたからボクがバグを入れ込んじゃったじゃないか!!

 当時の某社はXMLに強く傾倒していたため、フレームワークのViewにXSLを採用した。XSLさえ習得すればカンタン♪ みたいな宣伝文句だったが、XSLはそうカンタンじゃない。というか仕様が簡単すぎてループを回すだけなのにループ構文が無いから再帰呼び出しで制約を回避する必要があったりして、それはもう大変である。

 あるデータが空文字列だったら、全角スペースなり   なりに変換して出力することもXSLで可能だと思うが、Model側でやっちゃえばカンタンだし高速だし、って思うプログラマの気持ちも分からなくはない。

 Viewの部分でラクにHTMLの都合に合わせた変換ができればよいと思う。今回の空文字列の変換とか、不等号などの変換とかをViewで行えたら、プログラマも積極的にViewで行うと思う。そしてそれはWebアプリケーションのセキュリティホール(クロスサイトスクリプティングとか)を作りこんでしまうリスクの軽減にもなるのではないだろうか。

Posted by rukihena at 23:17:01 | Comments [1] | Trackbacks [1]

2005年7月 2日

16進の掛け算の暗算

 日経の1面の左上にあるプチ連載。今は「働くということ」というタイトルである。今日のその記事で先輩の能力の高さを見て驚いたという話があった。その驚いた理由が「16進法のかけ算を暗算でこなす」というものだった。この表現を日経の読者の何割が理解できるだろうか。

 とりあえず理解できるものとして話を進める。

 気になるのは何桁×何桁までイケルか。1桁×1桁だと、掛け算九九ならぬ掛け算FFを覚えれば可能だ。基本はここから始まる。そこまで来れば、2桁×1桁程度は楽勝だろう。だが2桁×2桁になると途端に難しくなる。一時的に2つの3桁の数を記憶して、さらにそれらを足し算しなければならない。2桁×2桁の普通の10進の掛け算でも、暗算できるヤツはスゴイと思う。そろばん3級のボクもそれはできない。

 16進の2桁×2桁だったとしたら、マジですごすぎ。

Posted by rukihena at 23:37:44 | Comments [2] | Trackbacks [0]

2005年6月24日

恋におちたら反省会

 今クールで唯一見ていた、CX系 木10ドラマ「恋におちたら」が終わった。

 予想は全然当たらなかったけど、ハッピーエンドでネジを作ってるからまあ方向性は合ってたということで。

 でも、アレ、顧客から「セキュリティがガチガチすぎて重いからセキュリティレベル下げて。」とか、「ちょっと削るだけでしょ♪」とか言われたり、営業から「契約がかかってるんだからヤレ。」と押されたりとか、ありがちな話ですな。

 パソコンの前に座っていると食事を忘れるとかもありがちですよね。ねねね。話しかけても反応しないのは描写が誇張されすぎたけどノックに気付かない程度は普通ですよね。ねねね。

 パソコンに向かうときはゆでたまごを食べるというエピソードはダメだな。殻を剥くのに時間がかかる。しかも手が汚れる。やっぱ、プログラマーたるもの、お箸でポテチ。これだね。キーボード・マウスを汚さないために箸を使う。そして飲み物はコーラ。

 「プログラマー生態監修」というスタッフが必要でしたら是非お声掛けください。

Posted by rukihena at 21:04:13 | Comments [1] | Trackbacks [0]

2005年6月 3日

連想配列

 PHPとかPerlの連想配列は結構速い。

 C言語で育っていると、どうも連想配列を使うという発想が出来ない。C言語だけで実現しようとすると、自力でメモリ配列を考えなきゃならんし、追加削除でmalloc()とかfree()とかしてたらメモリリーク起こしそうだし、数が増えたらハッシュでキーを付けるとかして高速化しないと使い物にならない。出来れば有限個のまっすぐな配列だけで済ませたいとか思ってしまう。

 ところがPHPなどでは、とにかく何でも連想配列にぶち込むのがいい。数千件ならサクッと入って、キーから引いてくるのも一瞬。昔はメモリの心配もしなければならなかったが、今は数メガ程度のデータをメモリ上に持ってもなんら不都合は無い。

 今日のお仕事で、無茶苦茶遅いSQLがあった。数百万行のテーブルと、数千行のテーブルをジョインしている。ジョインしているのはIDから名前に変換しているだけなのだが、やたら遅い。ジョインしなければ一瞬で返ってくるんだが・・・。

 joinしないで結果を取得し、IDから名前に変換するのは1つ1つSQLを発行しなおす、という手もある。しかし、クエリの回数が増えるのはかなりオーバーヘッドが高い。

 そこで、IDから名前に変換するテーブルは全件取得し、連想配列にぶち込んでみた。数千件なら一瞬である。そして、表示時にその連想配列を使ってIDから名前に変換する。オンメモリなのでこれも速い。

 これで1〜2分かかっていた画面表示を1秒程度に高速化できた。

 Java Servlet で作っていたなら、この ID-名前 変換テーブルというか連想配列というか Hashtable を init() の中で作ってメモリに置きっぱなしにすると良いかもしれない。DB更新時に、Hashtableも同期しなければならないという手間・バグのリスクがあるので安易には採用できないけど。利用頻度によってはかなり高速化できると思う。

Posted by rukihena at 23:34:53 | Comments [0] | Trackbacks [0]

2005年4月30日

Javaの高速化

 Javaで高速に動くコードを書こうと思った場合、一番効くのが new を少なくすることだ。new はオブジェクトを「出産」するぐらい大変だと思ったほうがいい。

 ループの中で、不要な new をするのは無駄である。できるだけループの外で作っておき、ループの中では再利用しまくる。

 サーブレットの場合、必要なオブジェクトは init() で作成しまくっておくのが良い。サーブレットがCGIに勝る点は「常駐していること」である。事前に出来る処理は init() で行うことでサーブレットのメリットが生かされる。

 doGet() などは、引数にレスポンスオブジェクトが入っている。なぜ、返り値ではなく、引数なのか。返り値だと、doGet() の中で new しなければならない。引数なら、サーブレットエンジンにて new しておくことが出来る。おそらく、サーブレットエンジンは最大同時接続数分のレスポンスオブジェクトを生成済みで、リクエスト毎に new はせず生成済みオブジェクトを渡すだけにして、高速化しているものと思われる。

 リクエスト毎にSimpleDateFormat を「出産」して、日付を加工して表示しているコードを見るとムカつく。あーもー、こーゆーのはあらかじめ作っとけよ! と思う。

 とにかく、そうやってinit()を膨らましていく。最近はサーブレットエンジン自身も起動時の処理が増えているように思う。起動にやたら時間がかかり、メモリを食い、しかし、1リクエストあたりの時間は短い。

 こうやって、init()を膨らますと、オブジェクト指向から離れていく。高速化とオブジェクト指向的美しさは相反する。速くて美しいコードは難しい。

Posted by rukihena at 23:59:43 | Comments [1] | Trackbacks [0]

2005年4月 2日

ちょうど 0x20才になりました。

 2進数で言うと100000才。5ビットではオーバーフロー。11688日間、生きました。

 何日生きたか計算する、すなわち2つの日付の差を求めるにはどうしたらいいか。年数×365+大の月とか小の月とか、うるう年補正とか・・・って考えるのは情報処理道まっしぐらすぎ。真っ直ぐ進みすぎ。

 2つの日付をなんかのシリアル値に変換する関数に投げて、それらの差を取れば一発。Excelだったら、セルA1,A2に2つの日付を書いて、セルA3に =A2-A1 って書いて書式を数式にすればOK。

 ただし、処理系によっては2038年問題に引っかかる恐れアリ。倍ちょっと生きると2038年か。そのとき65歳。少子高齢化で定年がのびて、ちょうどその頃が定年だろうか。でも、30年以上生き延びるシステムが存在するだろうか。あんまり未来のことは考えたくないな。

Posted by rukihena at 20:38:34 | Comments [2] | Trackbacks [1]

2005年3月 1日

Perl と PHP

 Perl とか PHP とか使っているが、Perl は何年使っても使いにくい。初期に極度の省略志向があったようで、如何に短い記述で済ますか、を重点にしており、しかし後から近年のエレガントな、例えばオブジェクト指向のようなものを追加して言語仕様がグチャグチャになっているように思う。それと、ボク自身がC言語なヒトなので、それとかけ離れた記述が使いにくい一因かもしれない。

 一方、PHPは比較的新しい言語と言うこともあり、変なグチャグチャ感は少ない。ベースもC言語っぽく、ループの脱出などで困ることが無い。しかし、やはり拡張を重ねた結果、変なところもある。特に動作モードのスイッチが多すぎなのが良くない。設定が異なるサーバに持っていけないんじゃないかと言う不安がある。

 もうちょっとキッチリ作ったサーバーサイドスクリプト言語は無いものか、と思うのだが、世の中はキッチリ系のJavaServletと、お手軽系のPHPがあれば十分なんだろうなとも思う。そのスキマを狙うよりは長いものに巻かれていたほうが幸せかも。

 MSだと、ASPがここで所望するソリューションだろうか。まあ、MS縛りがあるプロジェクトなら、キッチリ系でもお手軽系でもASPを使うだろうな。

Posted by rukihena at 23:36:13 | Comments [0] | Trackbacks [0]

2005年2月18日

GDI+ と VC++ と日本語

 GDI+を使ってみた。GDI+ はWindowsXPから使えるようになった2DグラフィックAPIである。XP以前でも、gdiplus.dllを入れれば利用可能である。(98以降か、NT4.0sp6以降)

 昔はJPEGを読もうと思うと一苦労で、フリーソフトではSusieのプラグインを利用するのが一般的であったと思う。また、商用ではImageGearが有名だろうか(ボクがそれしか知らないだけかも)。今使うなら、GDI+がオススメかと思う。

 で、猫でもわかるプログラミングを見ながらMFCに移植しつつファイルを読ませて表示してみた。結構カンタンに表示できた。しかし、一部のファイルが読めない。読めない条件が分からない。しばらくして、ファイル名に漢字というか日本語というか2バイト文字というかMBCSがあると読めないことに気付いた。もともと GDI+ はUNICODEで渡さなきゃならんので、mbstowcs() は通している。しかし読めない。Imageクラスのコンストラクタでも、FromFile()関数でも読めない。Bitmapクラスでも同じ。なんでだゴルァ。ボクは猫未満か?

 「GDI+ 日本語」とかでググってもわからない。みんなちゃんと使えてるのかよ。それともGDI+をVC++で使う日本人はボクだけかよ。英語の文章も読もうかと思ったけど multi byte string のネタを英語で語るやつなんかいねぇよ。

 と、途方にくれているところで、過去の苦い経験を思い出した。mbstowcs() の前に setlocale() を呼んどかなきゃならんことを。デフォルトでOSのエンコードを採用してくれよと思うのだが、setlocale(LC_ALL,""); が必須なのである。VC6のせいなのだろうか。VC.NETでは直っているのだろうか。Windowsの仕様なのだろうか。

 全体的にVC++の話はググっても情報が少ない。Win32APIの関数名でググっても、VBとかDelphiから利用する話が多い。なので今回はググられそうなキーワードをちりばめつつ書いてみた。もしお役に立てたのであれば、清き1クリックをキボンとあいまいな表現で乞うテスト。




Posted by rukihena at 23:23:29 | Comments [5]

2005年1月18日

センター試験

 ちょっと前の話になるが、センター試験の問題が新聞に出ていた。物理IBをやったら68点だった。時間を掛ければもうちょっといけたかも。英語は最初のアクセント問題で挫折した。数学は殆ど分からなかった。数学の問題にBASICが出ていることに驚いた。コメントの無いプログラムを読んで動作を予想する作業なんてやってらんねー。

Posted by rukihena at 23:59:59 | Comments [0]

2005年1月 7日

MDBにぎりっぱ

 MS SQL鯖+WebLogicで動いているシステムをメンテしている。機能拡張で、他システムのMDB (MS AccessのDBファイル)を参照する必要があったので、ODBC&JDBCブリッジ経由で接続するようにした。

 やっぱ、パフォーマンスを考えたらコネクション張りっ放しがいいかなぁと思ってチョロいプーリングのコードを書いた。preparedクエリも利用した。パフォーマンスは上がった。

 しかーし、そのMDBは容量増大対策で、夜間に再構築していたのだが、ボクがにぎりっぱなので再構築に失敗。容量制限により新規レコード追加が行えない状態に!

 MDBの再構築なんて知りませんよ。だいたいこの規模のシステムでMDBなんか使うなよ。と思うが、先方のボスに怒られた。○| ̄|_

Posted by rukihena at 19:52:36 | Comments [4]

2004年12月 3日

ぬるぽ

String str = hoge.getHogeHogeString();
if ( str.equals("hage") ) { /* */ }

とかやると、ぬるぽが出てしまう恐れがある。

通常は

String str = hoge.getHogeHogeString();
if ( str!=null && str.equals("hage") ) { /* */ }

とするだろう。最初の条件で && 以降をやらなくていいと判断したら、次の式は評価しないというK&R時代からの思想を受け継ぐ書き方である。

しかし、変数strが勿体無い。

if ( hoge.getHogeHogeString()!=null && hoge.getHogeHogeString().equals("hage") ) { /* */ }

は書き方として冗長すぎる。

ということで、ボク的にオススメなのは

if ( "hoge".equals(hoge.getHogeHogeString()) ) { /* */ }

である。文字列リテラルも String 型なので、それのメソッドを呼べてしまうのである。

しかし、本当のオススメはJavaを採用しないことだ。

Posted by rukihena at 23:46:09 | Comments [0]