Help us understand the problem. What is going on with this article?

D言語 Language Update 2015

More than 3 years have passed since last update.

D言語 Advent Calendar 2015の最初の記事です.今回も1年の更新を振り返って行きます.今年はコンパイラのD言語実装への置き換えなど,大きなマイルストーンが消化された年でした.

今年リリースされたdmdは2.067,2.068,2.069の3つです.それらの変更やコミュニティ関係に関してまとめます.

公式プロジェクト

言語仕様

pragma(inline)の追加

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とのインテグレーション

Interfacing to 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はバージョンを追う毎にコツコツとパフォーマンスが改善されている感じです.

GC Benchmark

組み込みAAの高速化

実装が,今までのSeparate chainingから,Quadratic probingを使ったOpen Addressingに変更されました.Martinのベンチマークによると,基本的にはパフォーマンスが向上したようです.メモリ傾向とかに違いは出てくるので,気になる方は自分のプロジェクトで上のGCともどもチェックしましょう.

AA Benchmark

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パッケージとしてユーザに提供して使ってもらうことになりました.

現在loggerallocatorの二つが入ってます.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年は今まで以上に加速するんじゃないかと思います.
パッケージも色々と増えてるし,プロダクションでの利用も増えてる感じなので,今後コミュニティがもっと活発化するといいなぁと思いつつ,俺もちょくちょく便利ライブラリを体裁整えて公開しないとなぁと思っているところです.

treasuredata
Customer Data Platformの開発・提供をしています。
https://www.treasuredata.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away