<< 11月 2006 | Home | 1月 2007 >>
PR: 転職    転職    合宿免許    漫画    シルバー    ブライダルエステ    墓地・霊園    葬式   

JavaDocのi18n

こんな方法はどうだろう。欠点はJavaDocのエラーの行番号がずれること(javacコンパイルの時はFreeMarkarを通さないので無問題)。

群馬へ。

家内の実家に日帰りで里帰り。ガソリンが115円とかあったけど、タイミングが合わず。でも119円で入れてきた。こちらより10円近く安いな。あと灯油も20リッタで1300円とかだった。

野菜をいっぱいもらってきた。もう全然違うんだよね。ブロッコリとか味もさることながら、2-3日もたつと黄色くなってすぐにダメになる。スーパで買ってきたのなんて1週間以上青々としてるし。成長抑制剤、オソロシイ。

Ubuntu 辞典

ひとしきり探し回ってから、EBViewがデフォルトでインストール済みであることに気付く。何やってるんだか。これでEPWingが扱えるので、英辞郎だけEBStudioで変換。なんかすごく速くていいな。Windowsの方もEBStudioに乗り替えようかな。

デスクトップにもUbuntu

デスクトップにもUbuntuを入れてみた。nVidiaドライバは、普通にアプリの追加と削除から入れるだけ。あとは、nvidia-xconfig -d 24 --twinviewとするとデュアルディスプレイが使える設定になるので、/etc/X11/xorg.confをエディタで開いてセカンドディスプレイの位置をRightOfからLeftOfに変更。残念ながら片方だけ回転というのはできないようだ。しかし設定はずいぶんと簡単になったものだ。

サイズ0の配列

サイズ0のコレクションは、Collectionsに宣言されている(EMPTY_LIST, EMPTY_SET, EMPTY_MAP)。サイズ0の配列がArraysあたりに宣言されていないのはなぜだろう。サイズ0の配列ってイミュータブルとみなして良いよね? もっとも配列は型情報を持っているから面倒というのはあるが。Stringのコンスタントプールみたいに、型ごとにプールするだけの話だよなぁ。

リンク切れ通知ページがリンク切れ。

http://java.sun.com/docs/forms/sendusmail.html。Send It押すと404だったりするんですが...

デフラグ

仕事用のThinkPadがかなり遅くなってきた。まだ2か月くらいしか使ってないんだけど、ディスクアクセスが地を這うように遅い。デフラグしても、導入当初の速度には戻らないんだけど、かけないよりはマシか。

デスクトップの方は、ほとんど使っていないから、大丈夫かと思いきや、

こんなに空き領域が残っていても、激しく断片化するんだなぁ。デスクトップの方は、そんなに使っちゃいないんだけど、なんで、こんなに断片化するかな。

あ、そういえばNIOのテストで何度もファイルのコピーを繰り返したっけ。しかもマルチスレッド化とかしたし。あれが原因か ^^;

クリスマス

鳥の丸焼きをいただいた。普通、こういうのって大味で、味気ないものだけど、今回いただいたものは、すごくおいしかった。胸肉なんか、さっぱりしているのに、とってもジューシー。


夢久は訳も分からず、記念撮影。


るいもは、ちょっとおすそわけ。ひたすら突進してきて、大変なことに...

猫ページ

猫ページ更新完了。

Ubuntu Emacs

どうもフォントが気に入らない。デフォルトだと明朝だし。ipamonagothicにしてみたら、妙に字間が開くし。で、結局-nwでターミナルモードで使うのがいい感じだということに気づく。でもなぜか.emacsにset-foreground-colorしても無視される。あとset-terminal-encoding-systemも無視される。なんでだ。良く分からん。set-foreground-colorでwhiteにしても、なんか微妙に暗い。

暗いのは、ターミナルのプロファイルの設定の「色」のところでパレットの組み込みスキームを"XTerm"に変更したら直った。

finalフィールドって変更できるんだ。

リフレクション使えば、finalフィールドって変更できるんだね。

import java.lang.reflect.Field;

public class Test {
    final int i = 1;

    public static void main(String[] args) throws Exception {
        Test test = new Test();

        Field field = Test.class.getDeclaredField("i");
        field.setAccessible(true);
        field.set(test, 123);

        System.console().printf("i = %d%n", field.getInt(test));
        System.console().printf("i = %d%n", test.i);
    }
}
$ java Test
i = 123
i = 1

しかしfinalフィールドは、値がインライン展開されるから、リフレクションで取得した値と、普通にアクセスした値が異るという、イヤな結果に。むしろfinalフィールドの変更はリフレクション経由の場合もエラーにした方が良かったんじゃないか?

結局Meadow2に戻す。

やっぱりce-scrollには馴染めなかった。ところどころカーソルの動きがおかしくなるのと、致命的なのはEmacs全体に適用されてしまう点。文書以外のバッファでは通常のカーソル移動でないと困るんだよね。特に自分の場合、マクロを多用するので。やっぱりphysical-line-modeは良くできている。

ATOKキーボード

この赤いキー、一瞬Panicキーかと思った(古っ)。

キー配列ではまる。

何かのタイミングでキーボードが英語配列になってしまった。デバイスマネージャのキーボードドライバを日本語 PS/2 キーボード(106/109 キー Ctrl+英数)に変更して、ほとんどのアプリケーションは問題無くなったのだが、なぜかMS Officeだけは英語配列のまま。そんなに使用頻度は高くないので、だましだまし使っていたのだが、そろそろ我慢できなくなってきて調べてみた。

結局ここの情報で直った。レジストリエディタで、HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard\Layouts\00000411下のLayout Fileをkbdjpn.dllに修正。

SimpleDateFormatのk

人の書いたソースを見ていたら、SimpleDateFormatの書式に"kk:mm"というのがあって、kってなんだろうと調べてみたら時間を1-24で表現する書式のようだ。

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2006);
        cal.set(Calendar.MONTH, Calendar.DECEMBER);
        cal.set(Calendar.DAY_OF_MONTH, 31);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        Date date = cal.getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd kk:mm");
        System.out.println(sdf.format(date));

        sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm");
        System.out.println(sdf.format(date));
2006/12/31 24:00
2006/12/31 00:00

なんか日付との整合性が合わないな。これって本当は2006/12/30 24:00じゃないの? kを使う時は日付を使用してはいけないのかな。

50万hit

カウンタが50万を越えた。もっともほとんどはRSSリーダからのポーリングによるものと思われるので、実際のPVはずっと少ないんだろうけど。

というわけで、これからもよろしくお願いいたします。

ファイルコピー

SHISHI@東京さんからヒントをいただいたので、ちょっとNIO版を書き換えてみた。

public class CopyByNio2 {
    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();

        String copyFrom = args[0];
        String copyTo = args[1];
        int bufferSize = 32 * 1024;
        if (args.length > 2) {
            bufferSize = Integer.parseInt(args[2]) * 1024;
        }
        if (bufferSize <= 0)
            throw new IllegalArgumentException("Invalid buffer size(=" + bufferSize + ").");

        FileChannel in = null;
        FileChannel out = null;
        try {
            in = new FileInputStream(copyFrom).getChannel();
            out = new FileOutputStream(copyTo).getChannel();
            long size = in.size();
            long offset = 0;
            while (size > 0) {
                long writtenSize = in.transferTo(offset, size, out);
                offset += writtenSize;
                size -= writtenSize;
            }
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
        finally {
            if (in != null) {
                try {in.close();}
                catch (IOException ex) {ex.printStackTrace();}
            }
            if (out != null) {
                try {out.close();}
                catch (IOException ex) {ex.printStackTrace();}
            }

            System.console().printf("Elapsed %,d%n",System.currentTimeMillis() - startTime);
        }
    }
}

あってるかな? 一応コピーされたファイルの内容を確認したので、大丈夫そうだけど... 結果は0.5秒くらい速くなったけど、この程度だと大差無しかなぁ。というか前回のテストでは25秒くらいだったのが、今回はどれも10秒くらいで終わるのは、どういうわけだろう。前回は、なぜかキャッシュが効いていなかったようだ。バックグランドで動いていたアプリケーションのせいだろうか。

続ファイルコピー

そういえばwrite back cacheの影響があるなと思い、コピー先をUSB 1.1のメモリに変えてみた。約6.3MBのファイルコピー。

Stream

1024512256128643216
7.798.028.529.5311.5516.0325.15

NIO
1024512256128643216
7.787.998.529.5311.5516.1325.32

やっぱり大差無いな。もっとも今回の例だとUSBへの書き込みが圧倒的なbottle neckだから差が出なくて当然か。しかし随分とバッファサイズが影響するもんだ。USBへの書き込みの開始終了に、何かオーバーヘッドがあるんだろうか。

読み込みと書き込みが遅いデバイスならば、読み込みと書き込みを別スレッドに分けてオーバーラップさせてやったら、速くなるんじゃないだろうか。というわけでマルチスレッド版コピーを試してみた。

import java.io.*;
import java.util.concurrent.*;

public class MultiThreadedCopyByStream {
    static class Packet {
        final int size;
        final byte[] buf;
        Packet(int size, byte[] buf) {
            this.size = size;
            this.buf = buf;
        }
    }

    static BlockingQueue queue = new LinkedBlockingQueue(8); 

    static class Donor extends Thread {
        final String copyFrom;
        final int bufSize;

        Donor(String copyFrom, int bufSize) {
            this.copyFrom = copyFrom;
            this.bufSize = bufSize;
        }

        @Override public void run() {
            InputStream in = null;
            try {
                in = new FileInputStream(copyFrom);
                while (true) {
                    byte[] buf = new byte[bufSize];
                    System.console().printf("%,d, Reading data%n", System.currentTimeMillis() - startTime);
                    int readLength = in.read(buf);
                    System.console().printf("%,d, Reading data done%n", System.currentTimeMillis() - startTime);
                    if (readLength == -1) {
                        try {
                            queue.put(new Packet(-1, null));
                        }
                        catch (InterruptedException ex) {
                            throw new RuntimeException(ex);
                        }
                        break;
                    }
                    try {
                        queue.put(new Packet(readLength, buf));
                    }
                    catch (InterruptedException ex) {
                        throw new RuntimeException(ex);
                    }
                }
            }
            catch (IOException ex) {
                ex.printStackTrace();
            }
            finally {
                if (in != null) {
                    try {in.close();}
                    catch (IOException ex) {ex.printStackTrace();}
                }
            }
        }
    }

    static class Acceptor extends Thread {
        final String copyTo;

        Acceptor(String copyTo) {
            this.copyTo = copyTo;
        }

        @Override public void run() {
            startTime = System.currentTimeMillis();

            OutputStream out = null;
            try {
                out = new FileOutputStream(copyTo);
                while (true) {
                    Packet packet = null;
                    try {
                        packet = queue.take();
                    }
                    catch (InterruptedException ex) {
                        throw new RuntimeException(ex);
                    }
                    if (packet.size == -1) break;
                    System.console().printf("%,d, Writing data%n", System.currentTimeMillis() - startTime);
                    out.write(packet.buf, 0, packet.size);
                    System.console().printf("%,d, Writing data done%n", System.currentTimeMillis() - startTime);
                }
            }
            catch (IOException ex) {
                ex.printStackTrace();
            }
            finally {
                if (out != null) {
                    try {out.close();}
                    catch (IOException ex) {ex.printStackTrace();}
                }

                System.console().printf("Elapsed %,d%n",System.currentTimeMillis() - startTime);
            }
        }
    }

    public static void main(String[] args) {
        String copyFrom = args[0];
        String copyTo = args[1];
        int bufferSize = 32 * 1024;
        if (args.length > 2) {
            bufferSize = Integer.parseInt(args[2]) * 1024;
        }
        if (bufferSize <= 0)
            throw new IllegalArgumentException("Invalid buffer size(=" + bufferSize + ").");

        new Donor(copyFrom, bufferSize).start();
        new Acceptor(copyTo).start();
    }

    static volatile long startTime;
}

concurrentパッケージを使うと簡単だ。読み込みがローカルドライブだと差がでないだろうから、無線LAN越しのリモートファイルにしてみた。バッファサイズは1MB。

マルチスレッドシングルスレッド(Stream)シングルスレッド(NIO)
8.249.149.16
微妙。確かに効果はあるんだけど、大した違いじゃない。処理のタイムスタンプを見てみると、

32, Reading data
516, Reading data done
516, Writing data
516, Reading data
1,407, Reading data done
1,407, Reading data
1,407, Reading data done
1,422, Reading data
1,735, Writing data done
1,735, Writing data
1,875, Reading data done
1,875, Reading data
2,344, Reading data done
2,360, Reading data
2,938, Reading data done
2,938, Reading data
2,938, Reading data done
2,938, Writing data done
2,938, Reading data
2,938, Writing data
2,954, Reading data done
4,172, Writing data done
4,172, Writing data
5,407, Writing data done
5,407, Writing data
6,625, Writing data done
6,625, Writing data
7,860, Writing data done
7,860, Writing data
8,219, Writing data done

読み込みが、ほぼ一瞬で終わっている。どうもOSに違いレイヤで、データの先読みをしているっぽい。面白いのがcmdのcopyによる結果が8.17secで高速なところ。copyも内部はマルチスレッド化しているんだろうか?

JDK 6.0

昔、ASCIIの実践Javaで、artonさんがStreamとNIOでファイルコピーの比較を掲載していたのだけど、あの頃は1.4だったので6.0ならば、どうかなと思って、やってみた。環境は、Core 2 Duo(3.4Gにover clock)で、Windows XP、DiskはSATA(3Gbps) Seagateの7200rpmのもの。ローカルファイル(サイズ670MB)のコピー時間を計ってみた。3回測定し、平均値から大きく逸脱しているものは除いて平均をとってみた。単位は秒。

Stream:

1k2k4k8k16k32k64k
26.126.026.226.026.328.728.4

Nio:
1k2k4k8k16k32k64k
26.426.126.324.826.326.328.0

う〜ん、今回もNIOとStreamでは大差無しかな。というかバッファサイズって1kもあれば十分なんだね。でもディスクアクセスの音を聞いていると、どうもバッファサイズは効いていないような気もする。もっとOSに近いレイヤでバッファリングがかかっていて、アプリケーションでバッファリングしても、これだけCPUが速い時代になると無意味なのかもしれない。何しろCPU使用率は、どのケースも有意差無しだったし。しかしバッファサイズが大きいとなんで遅くなるんだろう。Streamが32kで、ちょっと遅くなるのに対しNioは64kからちょっと遅くなるという傾向も興味深い。

ちなみにcmdでふつーにcopyしたら、27.8秒だった。cmdのcopyもバッファサイズが大きいのかな。

使用したプログラム:

--- CopyByStream.java ---
import java.io.*;

public class CopyByStream {
    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();

        String copyFrom = args[0];
        String copyTo = args[1];
        int bufferSize = 32 * 1024;
        if (args.length > 2) {
            bufferSize = Integer.parseInt(args[2]) * 1024;
        }
        if (bufferSize <= 0)
            throw new IllegalArgumentException("Invalid buffer size(=" + bufferSize + ").");
        byte[] buf = new byte[bufferSize];

        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(copyFrom);
            out = new FileOutputStream(copyTo);
            
            while (true) {
                int readLength = in.read(buf);
                if (readLength == -1) break;
                out.write(buf, 0, readLength);
            }
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
        finally {
            if (in != null) {
                try {in.close();}
                catch (IOException ex) {ex.printStackTrace();}
            }
            if (out != null) {
                try {out.close();}
                catch (IOException ex) {ex.printStackTrace();}
            }

            System.console().printf("Elapsed %,d%n",System.currentTimeMillis() - startTime);
        }
    }
}
--- CopyByNio.java ---
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;

public class CopyByNio {
    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();

        String copyFrom = args[0];
        String copyTo = args[1];
        int bufferSize = 32 * 1024;
        if (args.length > 2) {
            bufferSize = Integer.parseInt(args[2]) * 1024;
        }
        if (bufferSize <= 0)
            throw new IllegalArgumentException("Invalid buffer size(=" + bufferSize + ").");

        FileChannel in = null;
        FileChannel out = null;
        try {
            in = new FileInputStream(copyFrom).getChannel();
            out = new FileOutputStream(copyTo).getChannel();
            ByteBuffer buf = ByteBuffer.allocateDirect(bufferSize);
            while (true) {
                int readLength = in.read(buf);
                if (readLength == -1) break;
                buf.flip();
                out.write(buf);
                buf.rewind();
            }
        }
        catch (IOException ex) {
            ex.printStackTrace();
        }
        finally {
            if (in != null) {
                try {in.close();}
                catch (IOException ex) {ex.printStackTrace();}
            }
            if (out != null) {
                try {out.close();}
                catch (IOException ex) {ex.printStackTrace();}
            }

            System.console().printf("Elapsed %,d%n",System.currentTimeMillis() - startTime);
        }
    }
}

チャーリーくん家

チャーリーくんの家に遊びに行ってきた。チャーリーくんは夢久の兄弟。兄弟だけあって、仕草や容姿がとても似ている。





このまぶしそうな顔なんか、そっくり。








これは、お友達のNeneちゃん。なんかずっと怒っていたんだけど、なんで、そんなに怒っているのかは、良く分からず ^^;














どうも、私は、普段のチャーリー君の席に座ってしまっていたようで、そのせいか、ちょっとご機嫌斜めだったかも。ごめんね。

トラックバックspam

また来た。さてJavaScriptを解析しているのかを調べるため、ちょっと罠をしかけてみた。結果次第で対策を考える予定。

File.list(FilenameFilter)

File.traverse(FilenameListener)みたいのが欲しいなぁ。連番ファイルの最大が欲しいみたいな時は、別にリストなんていらないので。ファイル数が多いとメモリ消費がばかにならない。

あ、そっか、FilenameFilterで常にfalseを返すようにすればいいのか。

小桃の絵

ついに来た。感動。

ムンク

Googleがムンクになってる。ムンクの誕生日らしい。

猫ページ

猫ページ更新完了。

かじはらさんの個展

かじはらさんの個展に行ってきた。小桃の絵はやっぱり素晴しい。本猫よりずっとカワイイ。^^;

今年も、にゃんだらのプリントを買ってきた。











うちの猫っぽいけど、違うかなぁ。

Ubuntu AirH"でprinにつなぐ。

ちょっと悩んだけど、できてみればあっけない。

--- /etc/ppp/peers/provider ---
hide-password 
noauth
connect "/usr/sbin/chat -v -f /etc/chatscripts/provider"
debug
/dev/ttyS2
115200
defaultroute
noipdefault 
user "prin"
remotename provider
ipparam provider
--- /etc/ppp/pap-secrets ---
最後に以下の行を追加。

prin provider prin
--- /etc/chatscripts/provider ---
以下の行だけ残して、他は行頭に#を入れてコメントアウト

'' AT&FZ&C1E0V1&D2X4\V1\X1S0=0S7=60&K3
OK-AT-OK ATDTxxxxxxxxxx##64
CONNECT ''

ダイヤルアップ開始はsudo pon provider。ログはplogで確認できる。接続断はpoff。なんかpap-secretsがグループアクセスできちゃうよってWarningが出るので、chmodでグループアクセスを禁止した。でも、prinだと、これって共通だから別に隠さなくてもいい気はする。

トラックバックspam襲来。

はて、どうやってトラックバック先のURLを探り当てているんだろう。とりあえずトラックバック先をaddoTorakkuBakku.actionにして様子見 ^^;

FindBugs、Google codeに移動。

いつのまにかGoogle codeに移行していた。しかしGoogleはデザインがシンプルで良いね。SourceForgeの方のCVSも残っている模様。

Linux用Opera

なんかキーバインドをすごく細かく設定できていいんだけど、惜しい。SCIMと相性が悪いようで、全く日本語入力ができない。残念だなぁ。

ubuntu PCMCIA

pccardctlで制御できる。pccardctl lsで一覧が出るので、抜く時はpccardctl eject 0とか指定して停止する。

HTMLメール

なんか、USの方がHTMLに対しておおらかな気がする。Amazon USがバリバリHTMLメール送ってくるんで、配信停止にした。

ubuntu Emacsでファイルの最後に飛ぶ

"Shift + Alt + >"だと、なんか文字化けする。なぜなんだろう。と思ったら、ブラウザ上でやるとカタカナモードになるようだ。IMまわりのキーバインドに割り当てられているのかな。

あった。システム->設定->キーボードの中のレイアウトのオプションで、"Group Shift/Lock behavior"で、Alt+Shift changes groupのチェックを外したら直った。

ubuntu Emacsでutf-8

ここからMule-UCSをインストール。.emacsに、

(require 'un-define)

Ubuntu svn

ssh+svnでアクセスできるようにする。

mkdir ~/.ssh/
cd ~/.ssh/
ssh-keygen -t dsa
cat ~/.ssh/id_dsa.pub | ssh userid@host "cat - >> ~/.ssh/authorized_keys"

パスフレーズを何度も聞かれるので、

ssh-agent
ssh-add

ubuntu Emacs設定

とりあえずSKK。
Apel:ftp://ftp.jpl.org/pub/elisp/apel/。展開してsudo make install。
SKK:http://openlab.ring.gr.jp/skk/maintrunk/legacy/。展開して、sudo make、sudo make install。
辞書:http://openlab.ring.gr.jp/skk/dic/。SKK-JISYO.Lを~に展開。

--- .emacs ---
;; Add pahts to SKK and APEL

(defvar system-load-path load-path)
(setq my-load-path '("/usr/share/skk" 
		     "/usr/local/share/emacs/site-lisp/skk" 
		     "/usr/local/share/emacs/site-lisp/apel"
                 "/usr/local/share/emacs/21.4/site-lisp/emu"))
(setq load-path (append my-load-path system-load-path))

;; Configure for SKK

(require 'skk-autoloads)
(global-set-key "\C-x\C-j" 'skk-mode)
;; Specify dictionary location
(setq skk-large-jisyo "~/SKK-JISYO.L")

(add-hook 'isearch-mode-hook
	  (function (lambda ()
		      (and (boundp 'skk-mode) skk-mode
			   (skk-isearch-mode-setup)))))

(add-hook 'isearch-mode-end-hook
	  (function
	   (lambda ()
	     (and (boundp 'skk-mode) skk-mode (skk-isearch-mode-cleanup))
	     (and (boundp 'skk-mode-invoked) skk-mode-invoked
		  (skk-set-cursor-properly)))))
このサイトの掲載内容は私自身の見解であり、必ずしもIBMの立場、戦略、意見を代表するものではありません。
日本アイ・ビー・エム 花井 志生 Since 1997.6.8