Dartに絶望FlutterでGUIは有り

     Qiitaのどなたかの記事でDartはJavaScriptより実行速度が倍程速いと書かれているのを見かけて、期待しながら今リリースしているCoffeeScript(JavaScript)製の5五将棋アプリのGUI以外の部分をDartで書き直して比較したのですが、テストの結果からDartの方が遅いことが分かりました。Flutter(Dart)でマンカラアプリを作ってみてGUIの作り易さに感動した1だけに非常に失望しました。
     今のアプリよりも実行速度が遅いのならFlutterで将棋関連のアプリを作り直す意味がないので、どうしようかと思い、以前の記事で書いたマンカラアプリなら行数も少ないのでとりあえずこれを題材にTypeScriptとC++で書き直して比較してみました。

    比較の元となるDartの実行結果

     6×2列のマンカラカラハの先読みプログラムの実行結果です。何をやっているかは以前の記事を参照してください。

    $ dart mancala.dart
    [0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2]
    === result = 1, 5, i = 1
    === result = 0, 5, i = 2
    === result = 3, 5, i = 3
    === result = 4, 5, i = 4
    === result = 5, 5, i = 5
    === result = 4, 5, i = 6
    === result = 5, 5, i = 7
    === result = 4, 5, i = 8
    === result = 4, 5, i = 9
    === result = 4, 5, i = 10
    === result = 3, 5, i = 11
    === result = 5, 5, i = 12
    === result = 4, 5, i = 13
    === result = 5, 5, i = 14
    === result = 6, 5, i = 15
    === result = 2, 6, i = 16
    === result = 3, 6, i = 17
    === result = 999, 5, i = 18
    4040941
    [999, 5]
    
    

     18手で先手必勝を読み切るまでに4040秒(1時間強)

    まずはTypeScript

     好きなCoffeeScriptはマイナーになってしまったので、Dartの存在を知る前から今の将棋関連アプリをいずれTypeScriptに書き換えるべきかなと思っていたのでまずはこれで試しました。

    $ ts-node mancala.ts
    [ 0, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2 ]
    result = [ 1, 5, [length]: 2 ], i = 1
    result = [ 0, 5, [length]: 2 ], i = 2
    result = [ 3, 5, [length]: 2 ], i = 3
    result = [ 4, 5, [length]: 2 ], i = 4
    result = [ 5, 5, [length]: 2 ], i = 5
    result = [ 4, 5, [length]: 2 ], i = 6
    result = [ 5, 5, [length]: 2 ], i = 7
    result = [ 4, 5, [length]: 2 ], i = 8
    result = [ 4, 5, [length]: 2 ], i = 9
    result = [ 4, 5, [length]: 2 ], i = 10
    result = [ 3, 5, [length]: 2 ], i = 11
    result = [ 5, 5, [length]: 2 ], i = 12
    result = [ 4, 5, [length]: 2 ], i = 13
    result = [ 5, 5, [length]: 2 ], i = 14
    result = [ 6, 5, [length]: 2 ], i = 15
    result = [ 2, 6, [length]: 2 ], i = 16
    result = [ 3, 6, [length]: 2 ], i = 17
    result = [ 999, 5, [length]: 2 ], i = 18
    ms = 2862324
    [ 999, 5 ]
    

     同じ結果を得るまでに2862秒(1時間弱)で、やはりDartよりJSの方が速いようです。将棋の場合これ以上に明確な差がありました。

    C++はやはり最強

     苦労してC++で将棋関連アプリを書き直しても、そのままではスマホアプリに出来ないので今までは避けていました。でもFlutterでGUI部分を作って思考部分だけC++で作ればいいんじゃないかなんて考えて試してみました2
     C言語を使うのが久しぶりでよく調べずに一度間違った記事をアップしてしまったのですが、以下がC++の結果です3

    $ g++ mancala.cpp -O2 -o mancala.out
    $ ./mancala.out
    0,2,2,2,2,2,2,0,2,2,2,2,2,2,
    === result = 1, 5, i = 1
    === result = 0, 5, i = 2
    === result = 3, 5, i = 3
    === result = 4, 5, i = 4
    === result = 5, 5, i = 5
    === result = 4, 5, i = 6
    === result = 5, 5, i = 7
    === result = 4, 5, i = 8
    === result = 4, 5, i = 9
    === result = 4, 5, i = 10
    === result = 3, 5, i = 11
    === result = 5, 5, i = 12
    === result = 4, 5, i = 13
    === result = 5, 5, i = 14
    === result = 6, 5, i = 15
    === result = 2, 6, i = 16
    === result = 3, 6, i = 17
    === result = 999, 5, i = 18
    700673.273000[ms]
    999, 5
    

     結果は、700秒(約11分)!!やはり最強でした。

     プログラムを他の言語に移植すると言っても同じオブジェクト指向言語であればほとんどコードは一対一に書き換え可能で、写経に近いものがあります4。元々のDartのプログラムにはまだまだ改良の余地があると思いますが、拙いコードであってもバグがあったとしても、今回比較した3つのプログラムは行数も少なく同じ処理をしていますので、拙いコードもバグも同じまま、実行時間だけを比較していると言えると思います5。実行結果も同じです。

    マンカラの必勝法は?

     今回、マンカラの先読みプログラムをC++に移植したのは、以前のマンカラの記事続編の課題である、マンカラカラハ(6×2列で種子4つ)の必勝法を見つける目論見も兼ねていたのですが、C++版で実行時間が短縮されたと言っても、この程度では必勝法を見つけることが出来るかどうかは分かりません。1時間掛かった作業が10分で可能になったと言っても、もし読み切るのに1年以上掛かる作業だとしたら、やはり数ヶ月以上掛かることには変わりませんから。


    1. アニメーションなんてほとんど経験ないのにネットでググりながら進めたら簡単に作れました。 

    2. 昔、GUIはVisualBasicで作って内部処理はVisualC++で作る(DLL)なんて仕事をよくしていました。 

    3. コンパイルオプション(-O、または-O2)を付加することで末尾最適化してくれるそうです。そう言えば昔はスタックサイズやらいろいろコンパイルオプションを付けなければ上手くいかなかった記憶があります。自分がC言語から遠ざかっている間にコンパイラも進化しているようです。 

    4. プログラムの行数もほぼ同じ、コードもほぼ一対一で書式だけが違う感じで、C++だけクラス変数の初期化部分が少し違う程度です。 

    5. 実際に微妙なバグがあったので出力内容は現在では違う内容になってます。アプリの方は修正済みです。