Category Archives: プログラミング

texlipseでantするbuild.xml

texlipseでPDFを作る場合、非常に面倒だ。

なぜなら「Latex原稿のプロジェクトを選択」して「右クリック」を行い、メニューから「プロパティー」を選び「Latex Project Properties」で「Output Format」を「”dvi”から”pdf”」にして「OKボタンを押す」必要があるためだ。さらに出力をdviに戻すためにはこの作業で「”pdf”から”dvi”」に変更する作業を行わなければならない。

これは非常に非効率だ。このために1回の右クリックと5回の左クリックといくらかのマウス移動カロリーを必要とする。dviに戻す作業を加えると、なんと12回のクリックだ。これほどのクリックを毎回するのならdff.jp | クリック募金 _ クリックで救える命がある。にクリックを費やし、さらに余ったクリックで誰かのWeb広告をクリックし、余ったついでにamazonでお勧めされた製品の購入ボタンをクリックした方が世界が幸せになることは間違いない。間違えてもエロサイトをクリックしてはいけない。

そこでantビルドを用いてpdf作成を行うことを考えた。build.xmlは以下のとおりだ。

Read more »

TCPタイムアウトの変更(3)

HZを250から1000にするためには、Kernelコンパイル時のconfigで1000HZを選択する。

Processor type and features —>
Timer frequency (1000 HZ) —>
( ) 100 HZ
( ) 250 HZ
(X) 1000 HZ

また、Omicron TCP/RTOpatchをそのまま入れるとipv6がわめくので、

Networking —>
Networking options —>
<> The IPv6 protocol

IPv6さらば…。

オープンソースに対する”まつもとゆきひろ”のスタンス

日本発プログラミング言語であるRubyの作者、まつもとゆきひろ氏のインタビュー記事3連載の最終回ITmedia エンタープライズ:まつもとゆきひろ――第3回:僕の存在価値はそこにある (2/4)にて、まつもと氏のオープンソース開発におけるスタンスが語られている。

―― 最近は、海外でも広く使われるようになっていますし、Ruby on Railsによって仕事で使うという人もますます増えてきています。そうした状況の中で、まつもとさんが感じる責任、あるいは受けるプレッシャーというのは変わってきましたか?

まつもと ときどき、社会的責任が……という人もいるのですが、「ふざけるなー」という感じで無視することにしています(笑)。

―― ただ、作っている本人は、あまり意識したくないと思いつつも、ある瞬間から周囲が勝手に何かを期待しちゃうという、ことはありますよね。

まつもと 期待する人は、期待するだけのコストを負担しているか、という話になるでしょうね。そのコストを負担する気があるなら、負担されたコストを使って、その責任を果たすプレーヤーが出てくると思うんですよね。

と、責任は感じながらも感じないように努力している、そして期待する人に対してはコストを負担する気があるのなら、LinuxにおけるRedhatのように管理しようとするビジネスに対してコストを払うべきだ、としている。

オープンソースに対する考えは人それぞれですが、期待するのなら期待するだけのコストを払え、ということになる。もともと企業の中にはオープンソース・ソフトウェアを採用・導入する大きな利点として、「コストの安さ」を挙げるケースが多いような気がするが、ソフトウェア自体が無償で手に入ってもサポート・メンテナンス等でコストがかかる。

そうなるとオープンソースソフトウェアとプロプライエタリとの違いはコストではなくなる。もともとオープンソースソフトウェアの考え方としてコストの安さを追求しているのではなく、メンテナンス性を考えてのことであるのだから、コスト面においては利点はないという認識を持つ方が正しいのだろう。

TCPタイムアウトの変更(2)

前回の投稿において、タイマ粒度はどうなっているのか、という疑問があったが、良く見るとHZの値がキーであることに気がついた。

#define TCP_RTO_MIN ((unsigned)(HZ/5))

Linux KernelにおけるHZについて詳しい説明があるのが@IT:Linux Kernel Watch 8月版 割り込み頻度変更で消費電力は低下するか?(1/2)で、

 カーネル2.6.13-rc1にて、タイマー割り込みの頻度「HZ」が変更可能になりました。その際に、デフォルトの値が以前の
HZ=1000

から
HZ=250

になりました。このデフォルト値変更は多くの議論を巻き起こしました。

と説明している。実際に/boot/config-2.6.18-3-686を見てみると、

# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250

と、それらしきことが書いてある。よってTCP_RTO_MINはHZ/5=250/5=50ということだ。

で、おそらく、このHZがKernelの割り込みであるのだから、TCPの割り込みもそれで入っているのかもしれない。また、興味深い事実として、

 デフォルト値を250から1000に戻してほしいという要求に対して、Linusは「それが必要なユーザーが1000に変更したらよいだけだろう」と反論しました。そして、「『デフォルトを1000にするべきだ』と主張するのであれば、それが本当に良いということを示すデータを見せろ」というのです。

と書かれている。すなわち、もしTCPのタイマの粒度=Kernelのタイマの粒度であるのなら、HZを1000にしてより細かい粒度のタイマを試すことも可能かもしれない。

4msタイマと1msタイマの違いがどれほどあるのか分からないが、レイヤ2との協調性を実現する道具としては魅力的ではある。誤差の範囲にしかならないかもしれないが…

TCPタイムアウトの変更(1)

Linux kernelの2.6.18のTCPのタイムアウト時間を変更したいため、kernel実装を見つめる。

RTO(Retransmission TimeOut)が関係していることは分かっていたので、grep。RTOについてはたtcp_input.cが一番多く出てきた。見てみると、ACK受信時の処理やRTT、RTOの計算などTCPの入力系が書かれる。

中でも気になったのはTCP_RTO_MINで、includeのnet/tcp.cの中で、

#define TCP_RTO_MAX ((unsigned)(120*HZ))
#define TCP_RTO_MIN ((unsigned)(HZ/5))
#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value */

と定義されている。TCP_RTO_MINがHZ/5ということはすなわち、1s / 5 = 200ms。Omicron TCP/RTOにて

Linux の tcp_set_rto を見る限り,”RTO = SRTT + 4 * RTTVAR” になっている気がするけど.最小値(TCP_RTO_MIN)は 200ms,最大値(TCP_RTO_MAX)は 120s.

と書かれているので、ほぼ間違いないだろう。さらに

最小が 200ms なのは,TCP/遅延ACKタイマが 200ms だから,これ以上小さくすると不必要な再送が増えるため.で,遅延 ACK はなぜ 200ms なのかというと…

とも言及している。確かに遅延ACKが200msだと遅延ACKが入る前にタイムアウト再送してしまう…。遅延ACKについて調べてみると、

#define TCP_DELACK_MAX ((unsigned)(HZ/5)) /* maximal time to delay before sending an ACK */
#if HZ >= 100
#define TCP_DELACK_MIN ((unsigned)(HZ/25)) /* minimal time to delay before sending an ACK */
#define TCP_ATO_MIN ((unsigned)(HZ/25))
#else
#define TCP_DELACK_MIN 4U
#define TCP_ATO_MIN 4U
#endif

TCP_DELACK_MAXはHZ/5でTCP_RTO_MINと同じ。ほうほう。

ちなみにOmicronさんのTCP/RTOページにはLinux kernelのpatchが置いてあって、ページ内でそのできることに言及はしていないが、実はsysctlで動的にTCP_RTO_MAXとTCP_RTO_MINを変更できるコードが書いてある。素晴らしい…

もし遅延ACKが問題になるようであれば、TCP_DELACK_MIN / MAXともに変更できるようにpatchを変更しよう。そこまでやれば後は現在のTCP_RTO_MINである200msより下限なRTOがRTTによって適切に決められることだろう。

TCP における確認応答と再送制御 – The all-round Dictionary of Network Terms技術フェチ日誌(2006-11-02)が参考になるかもしれない。もし、RTOが上限と下限を決めても上手く動作しない場合は、RTOのインスタンス値であるtp->mdevの計算ロジックを変更する必要がありそうだ。

後、調べておくべきことはタイマの粒度だが、タイマの粒度を調べるには、”いつRTO(tp->mdev)が待ち時間と「比較」されて再送ロジックに入っているのか”を調べればいいだろうと思っている。しかし、再送ロジックに入るところがまだ探せて確定できてない。もしタイマの粒度が最低200msだったら嫌だなと思っているが、遅延ACKの最低値がHZ/25(40ms)なので、そこまでなら大丈夫な気がしている。

ここまで調べておけば何とかなるか。

USBメモリ上のJava開発環境

開発環境を持ち歩いたり、また納品を求められる場合がある。その場合に非常に有効なのがUSBメモリを使うというアイディアである。

Eclipseは基本的にインストーラなしで利用できるので、当然のことながらUSBメモリ上に展開しても使える。さらにプロジェクトによっては、以下のコンパイル環境をプロジェクトディレクトリ自体に含めてしまう。

  • GCJ(GCC)
  • UPX
  • WiX

実際にWindowsネイティブで動作するexeを作成する場合にはbuild.xmlを作成してantからビルドをかける。そうすることによって、antビルドでEclipse-(gcj)->exe-(upx)->exe-(WiX)->msi(Windows向けインストーラ)が一連の動作で完成する。デバッグのときにはgcjを使わずにJava VMを使うことでコンパイルの時間を削減できる。美しい…

そうしてEclipseごとzipで固めたり、USBメモリに入れてしまえば、どこでも利用できる開発環境の出来上がりである。WindowsネイティブGUIアプリケーションを制作できる環境でここまでメンテナンスがしやすいものは他にはないだろう。

全てOSSなのでライセンスの問題が発生しないことも大きい。

別の手段として無償で利用できるようになったVmware等の仮想化PCを利用する手段が存在するが、Windowsなどプロプライエタリな製品を含む場合はライセンスの処理が必要になる。そこでLinuxという考えもあるが、開発環境を渡す相手によっては使いこなせない可能性が高い。

そこで無償のものを利用することを目的としたソリューションを今回構成した。開発言語がJavaという点でもメンテナンスしやすいことであろう。

今回のことで、つくづくOSSの素晴らしさを感じた。

gcjのリンクでハマる

gcjによるjavaのネイティブコンパイルで下記のコマンドで実行するとundefined referenceエラーでリンクが上手くいかない。

gcj –main=HelloSWT –classpath=swt/win32/3218/swt.jar -Lthisiscool-gcc/swt/win32/3218 -lswt HelloSWT.java swtgif.o

で、2時間ほど色々試した結果、

gcj –main=HelloSWT –classpath=swt/win32/3218/swt.jar -Lthisiscool-gcc/swt/win32/3218 HelloSWT.java swtgif.o -lswt

で上手くいった。違いは”-lswt”と”.o”の順番である。

Manpage of GCCを見ると、

リンクは、オプション -c, -S, -E を指定して抑制しないかぎり(もしくはコンパイルエラーによってすべての処理が中断しないかぎり)、常に最終ステージで実行されます。リンクのステージにおいては、ソースファイルに対応した全ての .o ファイルと、 -l で指定したライブラリと、認識されなかったファイル名 (名前に .o のついたオブジェクトファイルや .a のついたアーカイブを含む) は、コマンドラインに並べられた順番でリンカに渡されます。

と、書いてあった。知るか、そんなん…

SWTで縦横比を確保したままのウィンドウサイズ変更

SWTを使ってGUIを構成するスタンドアロンのJavaのローカルアプリケーションを作成していて気になったのが「縦横比を確保したままウィンドウサイズの変更」ができるかどうか。

SWTでは基本的にウィンドウサイズのリサイズはaddControlListener(ControlAdapter)とcontrolResized(ControlEvent)によって可能である。

この方法では、ウィンドウの端っこをマウスカーソルが矢印に変化したときにドラッグすると、ウィンドウサイズの変更ができるが、ドラッグが終了しないとアプリケーションの処理が入らない。つまりウィンドウサイズの変更をしようとしているその瞬間にアプリケーションの制御がかけられない。よってドラッグ中に縦横比の制御がかけられない。

win32apiの方面から調べてみたが、ウィンドウサイズ変更後の動きはWM_SIZEが関係していて、ウィンドウサイズ変更中の動きはWM_SIZINGが関係しているらしいことまでは分かった(縦横の比率を一定にしてサイズ変更)。

SWTのソースコードに対してWM_SIZEでgrep検索かけると出てくる。が、WM_SIZINGでgrep検索をかけても出てこない。つまり、SWTではWM_SIZINGの制御は行っていない。自分でWM_SIZINGを書くしかない。

SWTに対してWM_SIZINGを組み込むことを考慮してWM_SIZEがどのようなロジックで動作しているのか見てみた。

org/eclipse/swt/widgets/Control.java
int windowProc (int hwnd, int msg, int wParam, int lParam) 中の
switch (msg) {
case OS.WM_SIZE: result = WM_SIZE (wParam, lParam); break;
}

によってwindowProcを返す。


org/eclipse/swt/widgets/Control.java
LRESULT WM_SIZE (int wParam, int lParam) {
sendEvent (SWT.Resize);
// widget could be disposed at this point
return null;
}

でWM_SIZEのイベント(SWT.RESIZE)を送る。


org/eclipse/swt/internal/win32/OS.java
public static final int WM_SIZE = 0x5;

で、OS依存のコードであるWM_SIZEを定義するというところまではつかんだ。

後はWM_SIZINGのコードを書くだけだが…面倒だ…orz