hidekatsu-izuno 日々の記録

プログラミング、経済政策など伊津野英克が興味あることについて適当に語ります(旧サイト:A.R.N [日記])

Rust 言語で JNI ライブラリを作る

Java にはプラットフォーム固有のライブラリを利用するために JNI (Java Native Interface) という機構が用意されている。この機構の問題点は、どこのプラットフォームにバイナリを持っていっても同じように動くという Java の最大の利点を失わせてしまうことにもちろんある。それはそうなのだけれど、最大の問題は様々な環境用のバイナリを用意するにはそれぞれコンパイル環境を用意する必要があり、現実的には難しいという点にある。

そこで考えたのだが、Rust はクロスコンパイルができるようになったと聞いた覚えがある。ということは単一環境(例えば、普段デスクトップとして使っているWindows PC)からでも各環境に対応した共有ライブラリが生成できるのではなかろうか。

まずは、Rust で JNI ができるのか調べてみた。すると出てきたのが次のサイト。

nitschinger.at

問題なくできるようだ。さらに調べたところ、

github.com

を使えば、jni.h の定義を Rust 用にいちいち手動変換する必要もないこともわかった。

Rust 付属のパッケージマネージャーは npm と似た仕組みになっているので、簡単にライブラリを追加できる。Cargo.toml に次の記述を追加する。

[lib]
crate-type = ["cdylib"]

[dependencies]
jni-sys = "0.1"

はじめは、crate-type = ["dylib"] と指定していたのだけれど、JNIで呼び出す場合は、Rust からの呼び出しは必要ないので、外部呼び出し専用の cdylib で構わない。これを指定するだけでファイルサイズが 2.2MB から 22KB になる。

さて、前述のサイトの add メソッドを jni-sys を使用して書き直すとこうなるになる。

extern crate jni_sys;

use jni_sys::*;

#[no_mangle]
#[allow(unused_variables, non_snake_case)]
pub extern fn Java_RustTest_add(jre: *mut JNIEnv, class: jclass, v1: jint, v2: jint) -> jint {
    v1 + v2
}

あとは普通に cargo build --release するだけでいい。予想以上に簡単。

この記述を見ればわかるように、プラットフォームに依存する記述はないため、この時点で少なくともマルチプラットフォームに対応できていることになる。

あとは、クロスコンパイル……と行きたいところなのだけれど、残念ながら現時点ではうまく行っていない。どうもランタイム環境は必要となるらしく、Windows 上で Linux バイナリを作るのは難しいようだ(Windows Subsystem for Linux を使えばできるはずだけれども)。 とほほ。

当初の思惑とは外れたとはいえ、予想外に簡単に JNI が実現できたことがわかったのは良かった。あとは SQLite とか各種ライブラリが Rust に移植されてくるといろんなことができるようになって面白くなるのだけど、そういう未来は来るのだろうか。

プロジェクトマネージャーが本当に気にすべきこと

仕事柄、プロジェクト管理についてはいつも関心を向けているのだけど、私自身があまりプロジェクト全体を管理する立場にないこともあり(基本、アーキなので)、なかなか考えをまとめる機会もなかった。たまたま、本屋でパラパラと PMBOK の本を眺めていて思ったことがあったので、書き留めてみることにする。

PMBOK 自体は辞典的な定義付けという意味では理解できるところは多いのだけど、実践的という観点からするとあまりにも表面的な内容に思えあまり意味があるように思えない。

例えば(といいつつ本題に入るのだけれど)、PMBOK には9つの知識領域というものがあり、これを管理すれば網羅的だよ、という言い方がされる。具体的には次のものが管理対象として挙げられている。

  • スコープ
  • タイム
  • コスト
  • 品質
  • 人的資源
  • コミュニケーション
  • リスク
  • 調達
  • ステークホルダー

たしかに嘘ではない。嘘ではないだが、正直ピンとこない。実際にPMになったとき、これを見ても何をすればいいのかがよくわからないのではないだろうか。

私が思うに、本当の管理対象はこうだ。

  • 顧客
  • 体制
  • タスク
  • 品質

一見して、QCDのCとD、通常最も重視されるコストと納期がないじゃないか、と即座にツッコミが入ると思うのだけれども、外したのには理由がある。

第一に、コストと納期は結果に過ぎない、と考えているからだ。管理してなんとかなものであれば、超優秀なPMを雇えば100円で明日までに100万人月のプロジェクトを成功させることだって可能なはずだが、もちろんそんなことは起きない。

不必要にコストを使っている(プロジェクトの経費で毎日銀座を飲み歩いている、とか)、不必要に期間を費やしている(メンバーが皆、毎日新聞を読みに会社に来ている、とか)というのであれば、管理せざるを得ないとは思うが、そんなことはめったになく、皆最大限に努力しているにも関わらずうまくいかないというのがだいたいのところだろう。

第二に、コストと納期はプロジェクトが始まる前には概ね決着しているということもある。標準工期という概念はあるにしろ、特に業務システムは決算期の切り替え時期やシステム更改の時期があるため、納期は顧客から指定される場合がほとんどとなる。コストについても、近年はコンペや相見積りが必須となる場合が多く、PMがアサインされる頃にはコストの枠は決まってしまっていて変えることは困難だ。

プロジェクトマネージャーの仕事とは、あらかじめ決められたコスト、納期を実現するために別の何かを管理するということなのではないかな、と思うわけだ。

ついでに言えば、リスクも管理対象ではない。というのも、コストも期間も限られている中、起こるかどうかわからないことに対処することは事実上不可能だからだ。リスクに対処するにはそれ相応のお金を積むしかなく、お金を積むのであれば見積り時点で考慮する必要がある。コストが管理対象でないことは前述の通り。

さて、本筋に戻ろう。まず「顧客」である。顧客を管理すると言うと大変失礼な言い方になってしまうが、例えば JUAS のソフトウェアメトリクス調査を見ると、工期遅延理由の半分は要件あるいは開発規模の増大に起因するという結果が出ていたりする。このことを踏まえれば、顧客は発注者であると同時に最大のプロジェクト失敗要因という言い方もできる。もちろん、逆の言い方をすれば、プロジェクトの成功を決めるのも顧客であるとも言えるわけだから、その関係を円滑にすることが重要でないわけがない。

PMBOKで言えば、ステークホルダー、スコープ、コミュニケーションが対応する。

次に「体制」。この体制は、ベンダーサイドの体制を意図している。昔、どこかで「あの男は優秀なPMだと思っていたから、今年の新人を全員投入してプロジェクトを任せたら炎上している」みたいな話を聞いたが、どんなにPMが優秀でも、メンバがまったく使い物にならないのではプロジェクトの成功はおぼつかない。むしろ、PMは並だが、メンバが優秀な人ばかり、という場合のほうがよほど成功しやすいだろう*1

きちんとした体制さえ組めれば、コミニュケーションは自然と改善するものではと個人的には思っている*2PMBOKで言えば、人的資源、コミニュケーション、調達が対応する(人的でない資源の調達は、実際のプロジェクトではそこまでボトルネックになるケースは少ないのではないかと考え一旦無視している)。

「顧客」と「体制」は人的側面の両面であるが、「タスク」と「品質」も構築対象の両面を表している。

「タスク」管理が重要なことはライフハック系の話で必ず言及されることから明らかであるが、プロジェクト管理の側面で言うと期限が重視されすぎなのではと感じる。個人的な経験から言えば、これはまったく間違っている。

タスクとその優先順位が明確になっていれさえすれば、あとは最善の努力でそれをこなすということが重要なのであって、期限自体はある種の目安に過ぎない。困難なタスクはどう期限を切ろうが簡単には終わらないし、そのようなタスクほどあらかじめ作業時間の見込みを立てるのは難しい。そのタスクができるだろうと踏んだ人に任せたら終わるまで待つしかなく、終わる見込みがなければ別の人に頼むしかない。期限は守れたが品質はボロボロというのでは、むしろプロジェクトの失敗に貢献しているとさえ言える。最近、CCPMという制約理論(TOC)に基づく進捗管理手法に言及されることがあるが、この観点からもなかなか良い手法なのではないかと思い始めている。

一方の「品質」は、成功の指標であるQCDのひとつではあるものの、他のふたつが客観的で明白な指標であるのに品質はあまり明確ではなく、見えにくいという点がキモである。コストと期間が制約されている状況下では、その結果が品質の低下として現れるのは必然ではある。とはいえ、多少の品質劣化であれば、必ずしも大きな問題とはなるわけではない。業務的にカバーできる内容であれば、リリース後に修正してもよいわけだし、めったに使わない機能に存在する不具合の場合、誰も気付かないことだってありうる。また、システム開発の裁判においても、納品後も不具合が残ることは一般的であり、それ自体はプロジェクト中断の理由とはならないとされている。

問題はユーザの利用を妨げるほど著しく品質が悪い場合だ。開発がわからないプロジェクトマネージャーのつまづきポイントがここにある。タスクとスケジュールだけを管理し、品質をまったく見ずに進めた結果、完成したと思われていたはずのものが実は完成していないというオチがおとずれる。どんなボタンを押しても例外が発生するという明らかな不具合から、すべての金額計算が浮動小数点型で行われているといった細かい問題もある。魂は細部に宿るではないけれど、ミクロだが致命的な問題は見えづらいがゆえに、納期直前に発覚する事が多く致命傷になることもある。途中でソースコードレビューを行ったからといって、すべての不具合が検出できるわけではもちろんないが、成果物の品質水準や開発者のレベルはある程度わかる*3

まぁ、私自身はプロジェクト管理の経験が豊富とは言えないので、今まで傍から見てきた感想と思っていただきたい。

TOC/CCPM標準ハンドブック クリティカルチェーン・プロジェクトマネジメント入門

TOC/CCPM標準ハンドブック クリティカルチェーン・プロジェクトマネジメント入門

 

 

*1:前述のJUASの調査によれば、ベンダー側PMの能力はソフトウェアの品質に大きく影響するという結果が出ているので、PMが重要でないと言いたいわけではもちろんない

*2:宮﨑駿は、人間関係もふまえアニメーターの座席を自ら決めるそうだが、それはやりすぎな気がするし万人におすすめするような手法とも思えない。

*3:よく品質は自動チェックツールで判断すればよいのでは、という話が出るのだが、自動チェックツールはコンピュータでしか気付けないような不具合の発見に得意な反面、さきほどの浮動小数点型の利用といった業務的な観点での不具合は見つけてくれないため、実際のところ品質の判定には使えない気がする。むしろコーディング規約の違反に開発者のスキルレベルが現れやすい感がある。

最強の圧縮アルゴリズム ZStandard を試す

以前「続・圧縮アルゴリズム(実測)」というエントリにて、各種圧縮コマンドの特徴を調べたが、このたび facebook より最強と名高い ZStandard がリリースされたので、追加で実測してみた。

以下はその結果。圧縮率はほぼ GZip 同等にも関わらず、圧縮時間は1/5、伸張時間も1/2、使用メモリ量は増えるもののさほどでもない。たしかに、これはなかなかの優れもの。高圧縮モードで使えば、bzip2並の圧縮率になるというのも良い。試していないけれども、あらかじめ辞書を作っておくと、圧縮率を更に上げることもできるようだ(どういう教育データを用意すればいいのかよくわからなかった)。

圧縮プログラム圧縮後
サイズ
圧縮時間圧縮時
最大メモリ量
伸張時間伸長時
最大メモリ量
lzip(best) 0.69 31.6 164.17 2.52 17.45
xz 0.69 23.87 106.96 2.45 12.23
lzip 0.71 19.65 102.26 2.48 12.41
brotli 0.72 94.97 72.48 0.59 7.29
bzip2 0.79 4.2 7.98 5.14 5.61
zstd(best) 0.81 17.34 66.1 0.55 12.29
xz(fast) 0.85 1.66 4.05 2.47 1.66
zopfli 0.89 2200.87 75.25 0.92 1
gzip(best) 0.95 6.49 0.96 0.97 1
lzip(fast) 0.97 3.26 14.47 2.58 2.86
gzip 1 1 1 1 1
lzfse 1 1.73 30.17 0.61 24.84
zstd 1.08 0.26 3.19 0.53 2.75
zstd(fast) 1.11 0.19 1.82 0.55 2.08
gzip(fast) 1.18 0.47 1 1.06 1
lzop(best) 1.21 12.04 1.84 0.38 1.2
lz4(best) 1.29 1.4 6.52 0.36 7.3
snzip 1.49 0.22 1.39 0.41 1.61
lzop 1.5 0.22 1.44 0.42 1.2
lzop(fast) 1.5 0.2 1.59 0.45 1.2
lz4 1.61 0.2 6.37 0.35 7.56

こうやって比較すると、Apple の新圧縮フォーマット lzfse は早くもお払い箱感がある。

才能か努力か

Twitter で話題になっていた「超一流になるのは才能か努力か?」が届いたので読み始めたところ、これがべらぼうに面白い。最近やってる社内勉強会でそのうち話そうかという気になり、勢いでプレゼン資料まで作ってしまった。

お気に入りの名著「頭のでき―決めるのは遺伝か、環境か」の内容とか経済学系の知識なんかもちょっとだけ加えてみたけれど、基本的には同書の内容の要約版になっている。要約紹介を実際に作ってみて気付いたけれども、この手の本はトピックだけだとエビデンスが欠如して信頼感が落ちてしまうところが難しい。実際に本文を読めば、裏付けとなる話がたくさん掲載されていて信頼を感じることができるけれども、要約だけだと怪しい啓蒙書に見えてしまうかもしれない。
表紙は地味だけど、刺激的な話が満載でまったく損をさせないとても面白い本なので、ぜひ買って読んで頂けたらと。
超一流になるのは才能か努力か?

超一流になるのは才能か努力か?

 

 

頭のでき―決めるのは遺伝か、環境か

頭のでき―決めるのは遺伝か、環境か

 

 

Embulk の実行可能 jar ファイルの面白さ

仕事でDBのマイグレーションに関わっていて、データの移行に適した良いツールないかなと探していたところ embulk というツールを見つけた。結構、流行っているということで調べ始めたところ、実行ファイルが面白い仕組みになっている事に気づいた。

embulk の Windows インストールは次のように記載されている。

PowerShell -Command "& {Invoke-WebRequest http://dl.embulk.org/embulk-latest.jar -OutFile embulk.bat}"

てっきり最近良く見るインストールスクリプトのダウンロード実行かと思ったら、そうではなく jar ファイルをダウンロードして bat ファイルとして保存しているだけだ。

昔から実行して展開できる形式の ZIP 圧縮ファイルはよく見たけれども、bat ファイルとはなるほどと思ってしまった。jar ファイルの内部形式である ZIP 圧縮フォルダはファイル末尾のエントリからの相対位置でエントリを記録することで、追記が可能なフォーマットになっている。このため、ファイルの先頭にZIP形式とはまったく関係のない任意のファイルを配置できる。

この方法を使えば、先頭から読むと bat ファイルのように実行でき、なおかつ jar ファイルとしても扱えるような特殊なファイルを作ることができる。*1

しかも、組み込むファイルは、ただのテキストファイルであるため、トリックを利用することでWindows バッチとしてもシェルスクリプトとしても実行できる jar ファイルにすることができる。

実際にバイナリエディタで開いてみると、embulk.jar の先頭は次のようになっている。

: <<BAT
@echo off

...

java %java_args% -jar %this% %jruby_args% %args%

...

exit /b

BAT

...

exec java $java_args -jar "$0" $jruby_args "$@"
exit 127

この方法を使えば、実行するだけで自動デプロイ可能な war ファイルなども作れる気がする。

*1:Windowsエクスプローラは先頭のPKを見てZIPファイルと判断しているようで拡張子を変えても展開することはできなかった。

なぜ相対的な人事評価制度は廃止されるべきなのか

先日、「悪いヤツほど出世する」という本を読んでいた時に、なるほど相対的な人事評価制度は廃止すべきという考えはもっともである、という結論に思い至った。*1

悪いヤツほど出世する

悪いヤツほど出世する

 

 以前、「評価は必要だ。だが、強制ランキングシステムはいらない」というエントリで書いたけれども、過去十数年にわたり流行ってきたスタック・ランキング制度*2は、実際に運用した結果として大きな問題が明らかになりアドビ、マイクロソフトIBMゴールドマン・サックスなどの大企業を筆頭に廃止する動きが進んでいる。

アメリカは成果主義だが日本は違う、あるいは日本も成果主義に移行しなければ、という風潮も過去のものになるかもしれない。とはいえ、スタック・ランキング廃止後の制度が日本型の年功序列終身雇用になるわけではない。それらの企業で変わりに導入された仕組みは概ね次のようなものだ。

  • 相対評価を廃止する
  • フィードバック頻度を短くする

後者のフィードバック頻度について特に疑問はない。通常の評価制度は昇給や年俸に合わせ年に1回行われるのが普通だ。とはいえ、私自身も経験があるが、年初計画していたプロジェクトと実際に関わったプロジェクトがまるで違う、などということは実際の業務では頻繁に起きる。それに、1年も立ってからこういう理由であなたの評価を最低です、と言うのであればもっと早く言ってよ、と思うのが人情だろう。

問題は前者の相対評価の廃止だ。相対評価は日本においても一般的なものだと思うので、それを廃止するとはいったいどうやって昇進を決めるんだろうと最初思ったのだが、やはり評価すべき人物や改善が必要な人物は上司などでピックアップして報告するようだ。旧来の評価制度との違いは、中間層についてはその能力の上下を評価しないという点にある。

相対評価の問題点はふたつある。ひとつは、社員間での競争が加熱し本来、協力関係こそが必要な組織力構築の障害になるという点。もうひとつは、人には自分は平均より優れているという「優越の錯覚」というバイアスがあるため、相対評価という客観評価をすることで多くの人々のモチベーションを下げてしまう点だ(なんと9割の人が自分は平均より上だと思っている!)。わざわざ、モチベーションを下げるために人事評価を行うというのは馬鹿げた話に思えるが、実際にほとんどの企業で行われれているのはそういうことだ。

評価すべき人物、改善が必要な人物をピックアップする時点で同じ問題は残るのではないか、とも思われるのだが、それについてはGoogleの「ワーク・ルールズ!」が参考となるのではと思う。相対評価を下すならば、誰が見ても歴然とした差がある場合にだけ境界を引けというのがGoogle推奨のやり方である。

「権力」を握る人の法則 (日経ビジネス人文庫)

「権力」を握る人の法則 (日経ビジネス人文庫)

 

 

*1:なお、この本自体はあまりお勧めできない。前著の「「権力」を握る人の法則 」の方がまだいい

*2:社員全員をランキングし上位 n% に高報酬を与え、下位 n %は強制的に退職させる仕組み

続・圧縮アルゴリズム(実測)

以前のエントリでは、文献をベースに圧縮アルゴリズムの違いを一覧化したが、この度、Windows Subsystem for Linux がようやく一般公開されたので、その環境上で実際に各種圧縮プログラムでの圧縮効率を実測してみた。

データとして使ったのは、郵便番号ダウンロードの全国一括データ(約12MB)。容量的にはたいしたことはないけれども、18種類の圧縮プログラムを10回実行し平均を取るとなると結構な時間がかかる。

値は前回と同じく gzip を基準に正規化したものを記載している(ちなみに gzip 圧縮後サイズは、約1.8MB で 15%ほどのサイズに圧縮されている)。

圧縮プログラム圧縮後
サイズ
圧縮時間圧縮時
最大メモリ量
伸張時間伸長時
最大メモリ量
lzip(best) 0.69 31.40 164.17 2.61 17.47
xz 0.69 23.68 106.96 2.45 12.24
lzip 0.71 19.44 102.77 2.58 12.43
brotli 0.72 94.01 72.48 0.63 7.31
bzip2 0.79 4.22 7.97 5.19 5.62
xz(fast) 0.85 1.67 4.05 2.50 1.66
zopfli 0.89 2191.20 75.25 1.00 1.00
gzip(best) 0.95 6.33 0.96 1.02 1.00
lzip(fast) 0.97 3.24 14.47 2.63 2.87
gzip 1.00 1.00 1.00 1.00 1.00
lzfse 1.00 1.70 30.17 0.66 24.88
gzip(fast) 1.18 0.47 1.00 1.14 1.00
lzop(best) 1.21 12.08 1.84 0.36 1.20
lz4(best) 1.29 1.38 6.52 0.34 7.31
snappy 1.49 0.21 1.39 0.41 1.61
lzop 1.50 0.16 1.44 0.44 1.20
lzop(fast) 1.50 0.14 1.59 0.47 1.20
lz4 1.61 0.22 6.37 0.25 7.57

こうしてみると、総合的に gzip のバランスの良さが目立つ。圧縮率も速度もメモリ量もそこそこというのは使い勝手を考えると大きなメリットだ。

圧縮率を重視するなら、LZMA 系の lzip, xz が優勢となる。圧縮速度、メモリ量などを考えると lzip よりも xz の方がよいように見える。

伸張速度を重視するなら、はやりの lz4 がやはり良いようだが、メモリ消費が激しいので、そのような用途では lzop や snappy の方が良いかもしれない。ただ、今回は試していないが、 lz4 もストリーム圧縮に対応したようなので、ライブラリを使えば回避できるかもしれない。

最近の圧縮アルゴリズムのはやりは、Web でのダウンロードを想定し、圧縮率と伸張速度を重視したものが増えている。たしかにその用途では brotli は魅力的に見える。gzip 互換の zopfli も魅力的ではあるが、1割の圧縮率向上のために2000倍の圧縮速度低下を受け入れるのはなかなか厳しい物がある。Apple の新圧縮アルゴリズム lzfse も今回計測対象に入れてみたが、圧縮率は gzip 並、圧縮速度もそう悪くなく、伸張は速いという特徴なので、どちらかと言うとストレージのリアルタイムでの圧縮・伸張が想定されているのかもしれない。

前回も書いたけれども、いずれの圧縮プログラム/アルゴリズムとも特徴があり、きちんと用途に応じたものを選ぶ必要があるのだ、ということを改めて感じた次第。