VisualStudio2017のネイティブメモリ診断機能が使えなくなった時の対処法

VisualStudio 2017便利ですね。

なんと、ネイティブメモリの解析が出来てしまいます。
スナップショット取って比較したり出来るので、メモリリークも簡単に見つかります。

以下の記事は2015ですが、概要はだいたい同じだと思います。
qiita.com

さて、本題ですが、私の環境でネイティブメモリ診断機能を使用していたときに遭遇したエラーと対処方法を忘備録として残しておきます。

【現象】
デフォルトではネイティブメモリの診断機能は無効になっているため、
デバッガーでアプリケーションを起動して有効にした後にデバッガーを再起動する必要があります。
再起動後、診断ツールの「メモリ使用量」にこんなメッセージが出ていました。

既に処理中のヒープセッションが存在するため、ネイティブメモリのプロファイルセッションを開始できません。Windowsは、コンピューターごとに1つのアクティブヒープセッションしかサポートしません。ほかのVisual Studioインスタンスまたはほかのパフォーマンス分析ツールを閉じてください。

なんのこっちゃ。

【対処法】
タスクマネージャーを開いて下のやつをkillってください。
C:\Program Files (x86)\Microsoft Visual Studio\Shared\Common\DiagnosticsHub.Collection.Service\StandardCollector.Service.exe

その後、再びデバッガーを起動すれば診断ツールが復活していることでしょう。
(少なくとも私の環境では復活しました)

誰かのお役に立てば幸いです。

それではまた。

std::tr2::sys::pathクラスの内容出力系関数の比較

今回はC++の話です。

たまに使おうとするといつも使い方を忘れているstd::tr2::sys::pathクラスについて、
文字列出力関係の関数と出力結果をまとめておきます。


パスの連結や比較なども機能として用意してあるようです。以下にまとめてあります。
が、この記事だと出力系がわかりにくかったので。。。
path クラス (C++ 標準テンプレート ライブラリ)


以下のパスを入力として与えてそれぞれの関数で出力した結果は以下の通りです。
(Windowsを想定しているので「\\」で区切っています)

C:\\TestDir1\\TestDir2\\TestFileName.bmp
関数 出力 区切り文字 説明(違ってたら指摘お願いしますm(_ _)m)
basename() TestFileName - ファイル名(拡張子無し)
branch_path() C:/TestDir1/TestDir2 / ファイルのあるディレクトリまでのパス
directory_string() C:\TestDir1\TestDir2\TestFileName.bmp \ フルパス
extension() .bmp - 拡張子部分
external_directory_string() C:\TestDir1\TestDir2\TestFileName.bmp \ フルパス
external_file_string() C:\TestDir1\TestDir2\TestFileName.bmp \ フルパス
filename() TestFileName.bmp - ファイル名(拡張子有り)
file_string() C:\TestDir1\TestDir2\TestFileName.bmp \ フルパス
leaf() TestFileName.bmp - ファイル名(拡張子有り)
parent_path().string() C:/TestDir1/TestDir2 / ファイルのあるディレクトリまでのパス
relative_path() TestDir1/TestDir2/TestFileName.bmp / ドライブ文字以外?(相対?)
remove_filename() C:/TestDir1/TestDir2 / ファイル名以外
remove_leaf() C:/TestDir1 / leaf()以外?(そうなってないけど。。。)
root_directory() / / ルートディレクトリ名
root_name() C: - ルート名
root_path() C:/ / ルートディレクトリパス
stem() TestDir1 -
string() C:/TestDir1 /


なんだかよくわからない結果ですね。。。
同じ出力結果もちらほらとでています。
Linuxなどで出力した結果を比較するともっとわかりやすくなるのかもしれません。
時間があるときに試してみたいと思います。

わかりやすいリファレンスの場所をご存知の方がいらっしゃれば是非教えてください!

VisualStudio2017で拡張機能をインストールしたら落ちる時の対処法

どーも。panjaです。

さっそくVS2017インストールしてみました。
いろいろ環境を作っていたのですが、ある拡張機能をインストールして再起動するとソリューションを開く際に落ちるようになってしまったので、対処法を残しておきます。
同じような現象で困っている人の助けになれば幸いです。

原因の拡張機能は以下のものです。
Productivity Power Tools 2017
blogs.msdn.microsoft.com

上の記事にも書いてありますが、「拡張機能と更新プログラム」から「Productivity Power Tools 2017」をインストールすると次回起動時に以下の拡張機能群が自動でインストールされるように変わったようです。(VS2015までの同様の拡張機能は一つの拡張機能に機能がてんこ盛りというものでした。)
その中のいくつかの機能を有効にするとソリューションが開けなくなりました。

インストールされる機能一覧は以下の通りです。
表中の「落ちる原因?」列が「◯」になっているものを全て無効化するとソリューションを開けるようになりました。

名前 概要(違っていたら教えてくださいm(__)m) 落ちる原因?
Align Assignments Ctrl + Alt + ]で「=」の位置を揃えてくれます ×
Copy as HTML 選択したテキストをHTML形式でクリップボードにコピーしてくれるらしいです ×
Ctrl+Click Go To Definition Ctrl+クリックで定義に移動します ×
Custom Document Well Visual Studio のドキュメント タブの動作を設定できるようにします*1 ×
Double-Click Maximize 検索ウィンドウなどをダブルクリックすると最大化できるようになります
Editor Guidelines 縦線を表示してインデントをわかりやすくしてくれます
Fix Mixed Tabs タブとスペースが混在している場合に教えてくれるようです
Match Margin キャレットの位置と同じテキストを強調表示してスクロールバーにもわかりやすく表示してくれます ×
Middle Click Scroll マウスの真ん中のボタンクリックでスクロールできるようになります
Peek Help F1を押すと表示されるヘルプをインラインで表示させるためのショートカットキーを設定できるようです
Power Commands for Visual Studio その他の(?)便利機能の詰め合わせのようです ×
Quick Launch Tasks クイック起動ツールのアクセス性を向上させ、タスクを設定する機能を追加します*2 ×
Shrink Empty Lines 意味のある行をより多く表示できるようにテキストや数字を含まない行を縮小します
Solution Error Visualizer ソリューションエクスプローラーでエラーや警告を強調表示してくれるようです
Time Stamp Margin デバッグ出力ウィンドウにタイム スタンプを表示する余白を追加します

また、今回開けなかったソリューションの概要は以下の通りです。
この辺りがかなり関係していそうな気がします。
・もともとはVS2013で作成したソリューション
・(Productivity Power Tools 2017を入れる前に)VS2017で開いた際にアップグレードはしていない
C#C++/CLIC++のプロジェクトを含む
・使用しているサードパーティ製ライブラリ:Boost、XercesC++、GoogleTestなど


「Editor Guidelines」を無効化しなければならないので、インデントがわかりづらくなったのがかなりイタいです。
「Indent Guides」という別の拡張機能もあるようですが、残念ながらVS2017には未だ対応していないようです。同じことが実現できる拡張機能をご存知の方、ぜひぜひ教えてください(`・ω・´)ゞ

*1:よくわかっていません

*2:よくわかっていません

Modern UI for WPFのデフォルトAccentColor変更方法と追加方法

どーも。panjaです。

最近、WPFを触っています。
Modern UI for WPF(MUI)を使ってみています。
今回はMUIの小ネタです。

MUIではメインウィンドウのテーマとアクセントカラー(ニッコリマークの背景色)がデフォルトで変更可能になっています。
f:id:panda531531:20170125231757p:plain
上の画像では、テーマがLight、アクセントカラーはcyan(R:0x1b,G:0xa1,B:0xe2)になっています。
初期状態ではテーマは「Light、Dark」、アクセントカラーは「lime、green、emerald、teal、cyancobalt、indigo、violet、pink、magenta、crimson、red、orange、amber、yellow、brown、olive、steel、mauve、taupe」から選択可能です。


今回はこのアクセントカラーの初期値の変更方法と色の追加方法を紹介します。

デフォルトAccentColorの変更方法

  1. GitHubからダウンロードしてきたMUI本体?のソリューション(FirstFloor.ModernUI.sln)を開く
  2. 「Shared\Assets\ModernUI.xaml」を開く
  3. 33、34行目の内容の「#」以下を好きな値に変更する
<!-- default accent colors and brushes -->
<Color x:Key="AccentColor">#1ba1e2</Color>

※16進で「#rrggbb」という並びになっているようです。
4. ソリューションをビルドする
5. お好きなプロジェクトにビルドして出来たバイナリへの参照を追加する

今回はデフォルトのAccentColorをemerald(#008a00)に変更してみました。
変更後してアプリ起動直後に以下のようになっていれば成功です。
f:id:panda531531:20170127004428p:plain
戻るボタンの枠やメインウィンドウの枠も一緒にemeraldになっていますね。

AccentColorの追加方法

  1. MUIのテンプレートを使ってプロジェクトを作成する
  2. 「Pages/Settings/AppearanceViewModel.cs」を開く
  3. 以下に好きな値を追加する
// 20 accent colors from Windows Phone 8
private Color[] accentColors = new Color[]{
    Color.FromRgb(0xa4, 0xc4, 0x00),   // lime
    Color.FromRgb(0x60, 0xa9, 0x17),   // green
    Color.FromRgb(0x00, 0x8a, 0x00),   // emerald
    Color.FromRgb(0x00, 0xab, 0xa9),   // teal
    Color.FromRgb(0x1b, 0xa1, 0xe2),   // cyan
    Color.FromRgb(0x00, 0x50, 0xef),   // cobalt
    Color.FromRgb(0x6a, 0x00, 0xff),   // indigo
    Color.FromRgb(0xaa, 0x00, 0xff),   // violet
    Color.FromRgb(0xf4, 0x72, 0xd0),   // pink
    Color.FromRgb(0xd8, 0x00, 0x73),   // magenta
    Color.FromRgb(0xa2, 0x00, 0x25),   // crimson
    Color.FromRgb(0xe5, 0x14, 0x00),   // red
    Color.FromRgb(0xfa, 0x68, 0x00),   // orange
    Color.FromRgb(0xf0, 0xa3, 0x0a),   // amber
    Color.FromRgb(0xe3, 0xc8, 0x00),   // yellow
    Color.FromRgb(0x82, 0x5a, 0x2c),   // brown
    Color.FromRgb(0x6d, 0x87, 0x64),   // olive
    Color.FromRgb(0x64, 0x76, 0x87),   // steel
    Color.FromRgb(0x76, 0x60, 0x8a),   // mauve
    Color.FromRgb(0x87, 0x79, 0x4e),   // taupe
};

今回はmaroon(#800000)を追加してみました。

Color.FromRgb(0x80, 0x00, 0x00),   // maroon

アプリを起動して「SETTINGS」ページを見てみると色が追加されていることがわかります。
f:id:panda531531:20170127004438p:plain


C++などと違ってフレームワークに乗っかれば簡単に追加できるのでいいですね!

Modern UI for WPFのデフォルトレイアウトを変更する方法

どーも。panjaです。

最近WPFを触っています。
WPFはWinFormsに変わるユーザーインターフェースシステムでなんかかっこいいことが出来そうな感じのものです。
Windows Presentation Foundation - Wikipedia

UIのライブラリ(違う?フレームワーク?)としてModern UI for WPF(MUI)を使用しています。
github.com

あるアプリの作成にMUIを使用していたのですが、どーにもデフォルトのレイアウトが気に入らない!と思ったので変更する方法を調べてみました。
今回はその結果を紹介してみます。

手順は以下の通りです。

  1. Modern UI for WPF(MUI)をダウンロードしてきます。GitHub - firstfloorsoftware/mui: Modern UI for WPF
  2. ダウンロードしたものの中に「FirstFloor.ModernUI.sln」が入っているので開きます。
  3. 「$(SolutionDir)¥FirstFloor.ModernUI¥Themes¥ModernWindow.xaml」を開きます。
  4. 29行目(2017/01/25現在)の
<ControlTemplate TargetType="controls:ModernWindow">

から197行目の

</ControlTemplate>

の中でMUIのテンプレートプロジェクトのメインウィンドウであるModernWindowのレイアウトを決定しているので、変更したい項目を探し出して好きなように変更する。
5. ソリューションをビルドする

これでOKです。
あとは、新しいテンプレートを使用したいプロジェクトの参照に先ほどビルドしたFirstFloor.ModernUI.dll追加すれば使用できるようになります。



以下に、私が実際に行った変更を載せておきます。
具体的には下の画像の赤枠のスペースを無くす変更を行いました。
(青色のRectangleを目一杯広げたページを表示しています。赤枠はGimpで追加しました。)
f:id:panda531531:20170125232135p:plain


ここに表示されるページに関する変更は「ModernWindow.xaml」の160、161行目

<!-- content frame -->
<controls:ModernFrame x:Name="ContentFrame" Grid.Row="3" Grid.RowSpan="2" Margin="42,8,16,16" Source="{Binding ContentSource, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" ContentLoader="{TemplateBinding ContentLoader}"/>

で行います。
赤枠のスペースを無くすためには、ここに設定してある「Margin="42,8,16,16"」を好きな値に変更してあげれば変更完了です。
今回は「Margin="5,0,5,5"」に変更しました。
結果は以下のようになりました。
f:id:panda531531:20170125231757p:plain

はい。変更できました。



まだまだわからないことだらけのWPF
今後も忘備録的にまとめていきたいと思います。
内容に誤りなどありましたら是非コメントよろしくお願いします。

Jenkinsのビルドログにご用心

どーも。

今回はJenkinsのビルドログファイルについてです。

普段の開発では、社内サーバー上でJenkinsを動かしています。
試行錯誤を繰り返しながら、やっとこさある程度安定して動作するようになりました。

Jenkinsについて知らない方はこのスライドなんかを呼んでみるといいかもしれません。

www.slideshare.net

現時点の構成としては、Subversionのpost-commitフック内でjobを走らせています。
job内ではビルド、テスト実行、CppCheckによる静的解析、SourceMonitorによるメトリクス計測、Doxygenによるドキュメント発行、結果のメール送信などを行っています。
とにかく出来ることを詰め込みまくった感じです。
(もっとこんなこと出来るよってのがあったら是非教えてください)

また、同じく社内サーバー上で動かしているRedmineとの連携も出来るようにしています。



さて、本題です。

Jenkins、Redmineなどを動かしている社内サーバーのストレージが一杯になってしまうということが先日起きてしまいました。
もともとCIサーバーになどするつもりの無いサーバーを勝手に(一応許可はもらってましたが)ごちょごちょしたツケが回ってきたようです。

開発が進むにつれてコード量も多くなってきていたのでその辺が原因だろうなーと思ったので、可能な限りシンボリックリンクを貼って中間生成物をそっちに吐いてみたりしました。
一旦はそれで問題なかったのですが、しばらくすると現象が再現してしまいました。

どうにかならんかなーと色々調査していたら以下の記事を発見!
qiita.com
「古いビルドの破棄」、、、たしかにあった気がするな。


ということでビルドログがどれくらい残っているか確認してみました。
ちなみにこの時点でのjobのビルド数は3500くらいでした。
ビルドログの場所はここでした↓。
%JENKINS_HOME%¥jobs¥(job名)¥log

早速サイズを確認してみると、、、70GB!
Cドライブが200GBしかないので35%をビルドログが占めていたことになります。

というわけで原因がわかったので、古いログをバックアップしてjobの設定で最大100ビルド(最長30日)分のビルドログしか残さないように変更しました。

「古いビルドの破棄」のオプションはデフォルトでONにしておいてくれてもいいような気がするんですがどうなんでしょうね。
また一つ勉強になりました。

clcacheを使ってVisualStudio2013のビルド(コンパイル)高速化

どーも。panjaです。

関西もだいぶ寒くなってきましたね。
体調を崩さないように手洗いうがいをしっかりしましょう。

さて、今回はccacheの亜種のclcacheについてです。

ccacheとは

まずはccacheについて。
ccache — Overview

Wikipediaさんによると、(ccache - Wikipedia)

ccacheとは、CまたはC++コンパイラが出力するデータをキャッシュするソフトウェア開発ツールである。その目的は、2回目以降のソフトウェアビルドにおいてはコンパイルを避け、出力結果を再利用することにある。これは再コンパイル速度を劇的に改善する。

ということです。
C、C++Objective-CObjective-C++に対応しています。
「遅いビルドは悪!」とレガシーコード改善ガイド(7.2章)にも記述があるように、なんとかビルドの高速化が出来ないかと思っていた矢先に出会いました。

しかし、、、こいつは普段VisualStudioで開発している私とは仲良くなれないやつだったのです。
VC++コンパイラcl.exeでは使えないとのことでした。(GCC系のコンパイラしか対応していない)


VC++で使えるやつないかー、と探して見つけたのが今回の本題clcacheです。

clcacheとは

ではclcacheについて書いていきます。
github.com

clchacheはGitHubで公開されているVC++用のコンパイラキャッシュです。

上記4つの情報を基にハッシュを生成して、2度目以降のコンパイル時の判定に使用しているようです。

GitHub上ではclcache.pyというpythonスクリプトファイルが公開されており、このファイルをpyinstallerを使ってexe化して使うというのが基本的な流れになります。

実際の流れは以下のような感じです。

(事前準備)
Python(ver3.3以上)をインストールしておく
・以下のコマンドでpyinstallerをインストールしておく

pip install pyinstaller


(手順)
1. GitHub - frerich/clcache: A compiler cache for MSVC, much like ccache for gcc から任意の場所にcloneしてくる(もしくはzipでダウンロードして展開する)
2. 以下のコマンドでclcache.pyの内容をexe化する(clcache.exeというファイルが./dist/以下に生成されます)

pyinstaller --onefile clcache.py

3. 任意の場所に(例えばC:¥clcache¥bin¥)にclcache.exeをコピーしcl.exeにリネームする
4. この場所にパスを通す(システム環境変数のPathの最初に追加)*2
5. 必要なら再起動する

以上で使えるようになっているはずです。
GitHub - frerich/clcache: A compiler cache for MSVC, much like ccache for gcc の「Installation for Visual Studio」という項目に別の方法が記載されていますが、私の場合はこの方法では上手くいきませんでした。環境によって結果は異なると思いますので注意してください。)

おもむろにVisualStudioを立ち上げてソリューションをリビルドしましょう。
1回目は今まで通り時間がかかります。





はい、終わりました。

適当に編集をして再度ビルドすると、、、


なんということでしょう~
すぐに終わりました(か?)

結果

ではどれくらい早くなったのか見てみましょう。

あるファイルを1行だけ改行させてビルドした結果です。
最適化手法によっても変わるのかな−と思ったので「最適化無効(/Od)」、「実行時間優先(/O2)」、「最大限の最適化(/Ox)」の3種類で試してみました。

clcacheを使わない場合はこんな感じでした。

最適化手法 コンパイル時間①*3 リンク時間*4 合計
無効(/Od) 40sec 80sec 120sec
実行時間優先(/O2) 40sec 110sec 150sec
最大限の最適化(/Ox) 37sec 110sec 147sec

はい。
コンパイルよりリンクに時間かかってますねぇ。。。。
今回はコンパイル時間を短縮するのが目的なのでこの問題はまた後で考えることにします。


clcacheを使った場合はこんな感じ。

最適化手法 コンパイル時間② リンク時間 合計 ②/①
無効(/Od) 22sec 74sec 96sec 0.55
実行時間優先(/O2) 36sec 100sec 136sec 0.9
最大限の最適化(/Ox) 37sec 98sec 135sec 1

はい。

なんだか微妙な結果です。
他のページに書いてあるような劇的な効果はありませんでした。
それどころか最大限の最適化を行った場合はあっても無くても同じという結果になりました。
まぁ最適化をしない場合には半分くらいにはなっているのでこの場合は有効と言えそうです。

まとめ

最適化を行わない場合はclcacheを使用してコンパイル時間が短くなることが確認できました。
ただ、他のページに紹介してあるような劇的な効果は今回は得られませんでした。

普段の開発ではclcacheを有効にしておいて、最適化は無効にしておくのが良さそうです。(もちろんリリース時に有効にする必要があります)
実験方法も悪いような気がしますし、継続的に効果を確認していきたいと思います。



リンク時間はどうやって短くできるんだろうか。。。

*1:The `normalized' command line

*2:本物のcl.exeをシステムが見つけてしまう前にこのcl.exeを見つけるための設定だと思います

*3:cl.exeが動いている時間を測りました

*4:link.exeが動いている時間を測りました