2011年11月16日
川俣晶の縁側ソフトウェアMagSite2開発日誌 total 2132 count

C#で列挙はやはり大切

Written By: 川俣 晶連絡先

「MagSite2を書いていて痛感したよ」

「何を?」

「その前に質問だ。MagSite1の構造を決定したときと、MagSite2を書いている今、最大の違いは何だと思う?」

「そうだな。当時はVisual Studio .NET 2002とC#1だけど、今はVisual Studio 2010とC#4ってことかい?」

「そうじゃない」

「えっ。そういう話じゃないの?」

「違うよ」

「じゃあ、何?」

「データ資産の蓄積の有無と、利用ノウハウの蓄積の差だ」

「それにどんな意味があるの?」

「うん。MagSite1の構造を決定したとき、1万アイテムまで扱えることを一応の性能上の目標に据えた。そのために、けっこう無理なテクニックも多く行使していた」

「うん。1万は多いようだけど、10年使えばあっさり溜まる量だね」

「1日3回更新して10年経てばあっさり1万を超えてしまう」

「じゃあ、MagSite2の目標は次の10年扱えるようにするために、上限アップ?」

「いいや」

「上限を上げないってことは、過去の切り捨て?」

「そうじゃない、実は1万を扱う必要なんて無かったんだ」

「どういうこと?」

「利用ノウハウが溜まって分かったことは、1年前のアイテムにはほとんど意味が無い。まあ意味があるケースもあるので、残しておくことには意味があるが別にランキングに出す意味も無い。ランキングに出さないということは、ソートされるリストとして扱う意味も無いことを意味する。CPUもメモリも大幅に負担が減る」

「じゃあ、どうするの?」

「ランキングに出すのは過去1年分でいいだろ、と割り切った。あとは、ただ単にそこにあるだけだ。カウント数は数えるがあくまで数えるだけだ。ソートの対象にはしない」

「読者はそれでいいの?」

「大多数の読者は、せいぜい数日以内の更新アイテムしか読まない。ならば、5年前のアイテムのためにスローダウンしてもあまり意味が無いだろ」

「うーむ」

「そう思ったときに意味があったのが配列より列挙という概念だ」

「列挙はプログラミングが面倒だろ?」

「今時のC#ならそうでもない」

「なぜ列挙にするといいの?」

「配列で返すと全部アイテムをリストアップしないと戻れない。しかし、列挙ならすぐ戻れる。たとえば、IDが新しい順に並んでいるとき、先頭から列挙すると最初のアイテムが一瞬で返される。まあ実際は年単位で分割してソートしてるんだけどね」

「最初のアイテムが一瞬で戻っても処理が終わるまでの時間が延びたら意味が無いじゃん」

「延びないよ」

「どうして?」

「必要な情報が得られた時点で列挙は打ち切り可能なんだ。全部リストアップしないで終わってしまうことも可だ」

「そうか。だから、今年と去年ぐらいのフォルダを調べてほとんど用が足りるから5年前10年前のフォルダまで調べないわけだね」

「そうだ。だから、ソースの[]をIEnumerable<T>に置き換える作業がガンガン進んでいるぞ。列挙で返せば凝ったことをしなくても性能アップだからな」

「でも、ここにToArrayって書いてあるよ」

「書き換え途上には互換性を維持する必要もあるから入っているだけだ。いずれ除去するさ」