グレインの備忘録

プログラミング関係とかをつらつらと。

リンクが倍速くなるらしい「lld」を試す

最近、ビルトインのldによるリンクの遅さが気になってきた。

そこで、もっと高速なリンク方法がないか探してみたところ、いくつかの新しいリンカに辿り着いた。

GNU goldよりも2倍早いlld

高速なリンカとしてはGNU goldが割と有名らしいが、それよりも更に高速なlldというものを見つけた。

https://lld.llvm.org/

このページ曰く「GNU goldの2倍高速で」動作するらしい。

lldのインストール

Ubuntu 16.04 (Xenial Xerus) にはパッケージがあるようなので入れてみる

sudo apt -y install lld-4.0

これでld.lldが利用可能になる。

ついでに、ldのシンボリックリンク切り替えの設定もしておく。

参考: qiita.com

sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.lld" 30
sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.gold" 20
sudo update-alternatives --install "/usr/bin/ld" "ld" "/usr/bin/ld.bfd" 10

これで登録は完了で、あとは

sudo update-alternatives --config ld

とすることでldの切り替えができる。

実際に使ってみた感じとしてはやはり数倍早くなっている感じだ。
少し待たされるようなジョブも一瞬で終わるようになった。
おそらくconfigureの速度を大きく改善するであろう。

構造体のDictionaryでは直接値を変更できない

コンテナの返値が値型か参照型かに気をつけましょうねという話。

シチュエーション

例えば、以下のようなコードを書いてみたとする。

public class Program
{
    struct MyStruct
    {
        public int val1;
        public int val2;
    }
    
    public static void Main()
    {
        var dic = new Dictionary<int, MyStruct>();
        
        dic[0].val1 = 1;
        dic[0].val2 = 2;
    }
}

自前の構造体をDictionaryに格納し、その値を変更するコードである。

しかし、これはコンパイルエラーになる。

error CS1612: 変数ではないため、'Dictionary.this[int]' の戻り値を変更できません

Dictionary内の要素に値を代入することができていないようだ。

dic[0]の返値は参照型ではなく値型

実は、これはMyStructが値型であることが原因である。

つまり、dic[0]というのは、dic内の0番目の要素のコピーであって、それに対していかなる操作を行ってもdic内の要素には一切影響しない。

上記のように[]で参照したものの値を直接書き換えたいならば、MyStructをclassにするしかない。

public class Program
{
    class MyStruct
    {
        public int val1;
        public int val2;
    }
    
    public static void Main()
    {
        var dic = new Dictionary<int, MyStruct>();
        
        dic.Add(0, new MyStruct());

        dic[0].val1 = 1;
        dic[0].val2 = 2;
    }
}

これならdic[0]はdic内の0番目の要素への参照となり、正しく動く。


C++ならコンテナは必ず参照型を返してくれるので、原因が分かるのに時間がかかった。

コンテナのイテレータを保持するのは避けよう

STLとかのコンテナが吐き出すイテレータをポインタ代わりに持っとくのはやめましょうねというお話。

コンテナへの非const操作はイテレータを破壊する(可能性がある)

「可能性がある」だから余計厄介だったりする。

テストケースではうまく動いても実環境では動かなかったり。

詳しい話はこちらのページに投げさせていただく。

qiita.com

neosnippetに自分のスニペットを追加する

前回の記事ではneosnippetを導入したが、自作のスニペットを使いたくなったので方法をメモ。

neosnippetの設定

まずは、スニペットファイルの保存先を指定する。

プラグイン起動時の設定に一行追加する。

let g:neosnippet#snippets_directory = ~/.vim/dein/repos/github.com/Shougo/neosnippet-snippets/snippets/'

したら再起動する。

スニペットの編集

まずは、スニペットを追加したいタイプのファイルを開く。

そして、「:NeoSnippetEdit」とコマンドを入力する。

すると、スニペットの編集画面が開く。

スニペットの構文は以下の通り。

snippet [識別子]
alias [略記法]
<インデント>スニペット内容
<インデント>スニペット内容
…

スニペット内容は基本は展開したい内容をそのまま書く。

また、Ctrl+Kで順にカーソルが移動できるような場所は「${数字:デフォルト値}」として書けばよい。

終わったら「:w」で保存する。


以上でスニペットの追加は完了である。

OOP初心者がブロック崩しを作ってみる その2

※この記事は「OOP初心者がブロック崩しを作ってみる その1」の続きです

衝突判定を考える

さて、衝突判定のやり方を考えよう。

衝突はボールとReflectorの間で起こる。とりあえず以下のようにクラス分けしてみる。

f:id:grainrigi:20170902161501p:plain

ReflectorCollectionにReflectorを全て格納しておいて、Ball側から参照、衝突判定を行う。

move関数はBallに速度に従っての移動を指示する関数で、移動するたびに衝突判定を行う。

BallとReflectorのgetRect関数はそれぞれの専有する範囲を返す。(衝突判定に使用)

衝突判定を外に出す

これでも悪くはないが、Ballが「移動する物体」と「衝突する物体」の2つの役割を持っているので、分割したい。

ということで、衝突判定は外に出し、Ballは速度に従って移動することに専念することにする。

f:id:grainrigi:20170902163639p:plain

CollisionManagerが衝突判定を担当する。

流れとしては、

  1. Ballのmove関数が呼ばれる
  2. Ballが速度に従って移動
  3. BallがexecuteCollisionを呼ぶ
  4. CollisionManagerが全Reflectorと衝突判定
  5. CollisionManagerがgiveImpulseを呼び、ボールに力積を与える

という感じ。

Observerパターンを適用する

結合度の面から言えば、BallとCollisionManagerがお互いの関数を直接呼び出しているのであまり良くない。

そもそも、CollisionManagerはボールの移動をトリガーとして衝突判定を行うのである。

したがって、CollisionManagerがボールの移動を監視すれば良い。

つまり、Observerパターンを適用する。

f:id:grainrigi:20170902171012p:plain

move関数で移動した後、observerに移動を通知する。

これで多少はすっきりした。

Reflectorが衝突を知るには

ブロックのように衝突の有無を情報として必要とするReflectorが存在するので、それを通知する必要がある。

それもCollisionManagerが担当するのが妥当であろう。

以上のことを加味してまとめたクラス図はこうなった。

f:id:grainrigi:20170902171952p:plain

衝突判定に関しては概ねこのような感じでいいだろう。

次回予告

次回「OOP初心者がブロック崩しを作ってみる その3」は、この大まかな設計を基に実際にコードを書いてみることにする。

バッファの内容を変数に読み込む方法

日本語で調べても一切情報が出てこなかったので焦った。

方法

:%y [レジスタ名]
:let content = @[レジスタ名]

一旦レジスタにヤンクしてから、その内容を変数に入れる。

@[レジスタ名]でレジスタの内容を参照できるようだ。

UMLをテキストで書ける「PlantUML」を試す

UML図を書くフリーのツールにはいろいろあるが、テキストコマンドで書けるものの一つに「PlantUML」がある。

テキストベースで書けると何がいいかというと、

などの点が挙げられる。

使い方等

PlantUML自体はJavaで書かれたテキストプロセッサであるが、Web上でこれを試せるサービスがある。

PlantUML Web Server

リファレンスはここにある。

PlantUML

クラス図・フローチャートのほかにも色々とかけるらしい。

使用例

テキスト

@startuml
start
:ボールを移動;

repeat
  :Reflectorを一つ取り出す;
  if (ボールと衝突したか?) then (yes)
    :ボールの移動方向を変える;
  else (no)
  endif
repeat while (Reflectorはあまだあるか?)

stop
@enduml

出力

f:id:grainrigi:20170830235007p:plain

これは積極的に使っていきたい。