D言語 Advent Calendar 2015の最初の記事です.今回も1年の更新を振り返って行きます.今年はコンパイラのD言語実装への置き換えなど,大きなマイルストーンが消化された年でした.
今年リリースされたdmdは2.067,2.068,2.069の3つです.それらの変更やコミュニティ関係に関してまとめます.
公式プロジェクト
言語仕様
pragma(inline)の追加
プログラマが関数のinlineを制御出来ます.コンパイラに任せるpragma(inline)
,inline化を抑制するpragma(inline, false)
,inline化を強制するpragma(inline, true)
(できない時はコンパイルエラー),など.
-inline
がない時でもpragma(inline, true)
はinline化するべきですが,その部分はまだ未実装となっています.
ヒープに確保されたstructのデストラクタが実行されるように
題名の通りで,今までnewしたstructがGCによって回収される時にデストラクタが呼ばれてなかったんですが,呼ばれるようになりました.まぁヒープに取らないといけないようなやつは皆classを使っていたんですが,PODであるstructも呼ばれるようになったので,利用の幅が広がった感じです.
Invalidなcastの判定がフロントエンドでされるように
今までcastの判定に関してはバックエンド側のコード生成の所でやられてたんですが,フロントエンドで行われるようになりました.それによって非互換な挙動があります.以下がchangelogの例.まぁこの手のコードはあんまり出てこないとは思いますが,気になる方はチェックしましょう,
pragma(msg, is(typeof({ void* x; auto y = cast(void delegate())x; })));
// Since 2.067: it prints 'true'
// From 2.068: it prints 'false'
void test() { void* x; auto y = cast(void delegate())x; }
// Since 2.067: it had reported internal compiler error "Error: e2ir: cannot cast ..."
// From 2.068: it reports proper frontend error.
asmでの属性サポート
今までasm
を使っていると関数そのものはpureな実装でもpureとかに出来なかったんですが,asm
にこれらの属性をつけてコンパイラに知らせることにより,asm
を使っている関数でも適切に属性をつけられるようになりました.なので無理して@trusted
にするとかの必要性がなくなりました.
asm pure nothrow @nogc @trusted
{
// コンパイラは属性のチェックをしないので,実装者が保証する必要がある
}
以上の他,Sealed referencesの機能が実装されたり,with
がテンポラリオブジェクトの寿命を無視してしまう問題が解決されたりと,より安全になりました.
またtemplate関係でも,属性のinferがauto returnの時に行われるようになったり,deductionが賢くなったりと,よりコードが書きやすくなりました.
dmd
フロントエンドのD言語化
dmdのフロントエンドのD言語化とD foundationの記事で言及しましたが,フロントエンドがC++からD言語になりました.目に見えて遅くなってる感じはしないので,最初の置き換えにしては十分だと思ってます.D言語が高速化されるとコンパイルも高速化されるということで,今後より開発は加速すると思いますし,パッチも投げやすくなったと思います.
gdc/ldcもフロントエンドはdmdのを使っているので,様々な環境でメリットが享受できると思います.
Objective-Cとのインテグレーション
個人的に使う予定がないので全然追ってません!興味のある方は上のページを読みましょう.
-unittestが指定されなかった時の高速化
今までコンパイラは律儀にunittestブロックもパースして構文チェックなど色々としてたんですが,-unittest
がついてない時はその辺をスキップするようになりました.なので,プロダクション向けのビルドなどでコンパイル速度が向上しました
-profile=gcフラグ
-profile=gc
をつけてコンパイルすると,GCによるアロケーションに関して,アプリケーション終了時にログで出してくれるようになりました.思ったよりメモリアロケーションに時間を使ってるな,って思ったらこれをつけて走らせてみましょう.以下のようなログがはかれます.
bytes allocated, type, function, file:line
171 immutable(char)[] example.concat example.d:4
24 closure D main example.d:18
16 example.Klass D main example.d:20
druntime
GCの高速化
ヒープ伸長のアルゴリズムや,ヒープの探索を効率化することで,GC全体のパフォーマンスが改善されました.以下はdruntimeにあるベンチマークスクリプト群の結果です.GCはバージョンを追う毎にコツコツとパフォーマンスが改善されている感じです.
組み込みAAの高速化
実装が,今までのSeparate chainingから,Quadratic probingを使ったOpen Addressingに変更されました.Martinのベンチマークによると,基本的にはパフォーマンスが向上したようです.メモリ傾向とかに違いは出てくるので,気になる方は自分のプロジェクトで上のGCともどもチェックしましょう.
volatileStore / volatileLoad
core.bitopに追加された命令です.同一スレッドでコンパイラによる削除やre-orderを抑制するために使います.以下はchangelogに載っている例です.
void example(uint* address, uint value)
{
import core.bitop;
// store value
volatileStore(address, value);
// wait until value takes affect
while (volatileLoad(address) != value)
{ }
}
将来的にはvolatile
は予約語から削除され,core.volatileで置き換える予定です.
phobos
std.experimental
いずれphobosに入るんだけど,レビュー段階では洗い出し切れないユースケースやAPIの問題について,experimentalパッケージとしてユーザに提供して使ってもらうことになりました.
現在loggerとallocatorの二つが入ってます.allocatorについては別の日のAdvent Calendarで書きます.loggerについても書くかも.
さらなる関数群のRange化
PhobosはRangeを中心に構築されており,その対応がされていなかったものも更に対応されました.引数としてRangeを受け取るようになったのが増えたのはもちろん,以下のようにRangeを返すことでメモリアロケーションを回避する実装も増えたりしました.
setExtension("foo.jpg", ".png"); // 新しく生成された文字列を返す
withExtension("foo.jpg", ".png"); // chain Rangeでラップされた結果を返す.chainをイテレートするだけなので,メモリアロケーションは起きない
curlの動的ローディング化
いままではstd.net.curlを使うためには,libcurlを明示的にlinkしないと行けなかったんですが,シンボル周りのバージョン問題や,dmd本体のリンクオーダー周りでいくつかトラブルがあったので(これ自体は別の方法で修正済み),それらを回避するために実行時に動的にロードするようになりました.
Windowsでの注意事項とかあるので,Windowsでcurlを使う人はwikiのCurl on Windowsのページを参照してみてください.
追加された便利ユーティリティ
- std.range.enumerate
Rubyでのeach_with_index
です.Rangeにインデックスを付与してくれます.引数はインデックスの初期値です.
foreach (lineNum, line; stdin.byLine().enumerate(1))
stdout.writefln("line #%s: %s", lineNum, line);
- std.exception.handle
Rangeを処理する過程でエラーが起きた時に特別な処理を挟むためのRangeです.以下はchangelogの例ですが,invalidな文字があった時に文字を置き換える,と行ったことが出来ます.
auto str = "hello\xFFworld"; // 0xFFはUTF-8としてはinvalid
auto handled = str.handle!(UTFException, RangePrimitive.access, (e, r) => ' '); // UTFExceptionが起きたら空白で置き換える
assert(handled.equal("hello world"));
- std.algorithm.mutation.moveEmpalce
moveのEmplace版.moveは安全にmoveするために対象をdestory
するんですが,未初期化なオブジェクトをdestroy
するのは危険なため,初期化しないと行けないという二度手間がありました.それらを回避するためにdestroy
しない版が追加されたという感じです.パフォーマンスも向上します.
コミュニティやその他のプロジェクト
D Foundationの設立
こちらもすでに言及しましたが,AndreiがD言語を加速させるためにFacebookをやめてD Foundationを立ち上げました.Visionをたてたり,今まで結構属人的だったものを,まとめてコミュニティを活性化させていこうという感じです.
D言語の本
11月に出ました.Cとかの言語を知っている人向けに書かれていて,入門的な内容から始まって,CTFEとかRangeとか,プロダクションでよく使われる機能まで説明しているようです.
2015年に出ると思ったら2016年1月になってました.プレオーダー状態ですが,vibe.dを使ってのWebアプリケーション開発について書かれています.
DConf 2015
D言語でストレージシステム書いてる人がいたり,Ciscoの中のネットワークソフトウェアのツールで使っている人がいたり,D言語使ってる人増えてるなーという感じですね.スライドやyoutubeに動画があがったりしているので,気になるトークは見てみましょう.
DConf 2016もあります.
vibe.d
相変わらず開発は活発です.最近libhttp2やBotanなどのパッケージが増えていて,それらを使ってのHTTP2サポートも進んでいるようです.もうD言語でのデファクトになってます.
DUBパッケージ
elasticsearchやGELなどのライブラリとか,プロダクションで使われてるようなライブラリが増えてます.見てると非同期IO系のモジュールがちょくちょく出ているので,そろそろvibe.dの足回りとなるデファクトが決まって欲しいところです.libasyncが今のところ有力か.
まとめ
dmd/druntime/phobosに関しては全部を列挙しているわけではないので,気になる方はchangelogを漁ってください.D Foundationが出来てAndreiがD言語に注力するようになったので,2016年は今まで以上に加速するんじゃないかと思います.
パッケージも色々と増えてるし,プロダクションでの利用も増えてる感じなので,今後コミュニティがもっと活発化するといいなぁと思いつつ,俺もちょくちょく便利ライブラリを体裁整えて公開しないとなぁと思っているところです.