Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CGrepAgent::SetGrepResult 出力形式がノーマルの場合の処理の高速化 #418

Merged
merged 25 commits into from
Sep 12, 2018
Merged

Conversation

beru
Copy link
Contributor

@beru beru commented Sep 8, 2018

Grep結果を構築する CGrepAgent::SetGrepResult メソッドにおいて出力形式がノーマルの場合に、マッチした行番号と桁番号を sprintf で文字列化する処理がありますが、プロファイラで確認したところその処理に少し時間が掛かっている事が分かりました。

その文字列化する処理を別途用意する事で高速化しました。場合によるかもしれませんが、Grep処理が 5% くらい速くなりました。

@beru beru added the 🚅 speed up 🚀 高速化 label Sep 8, 2018
p += s(nColumn, p);
*p++ = L')';
*p = NULL;
cmemBuf.AppendString(strWork);
Copy link
Contributor

@berryzplus berryzplus Sep 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ごめんなさい、既存の枠を使って速くする手段がありそうに思ってます。

既存の枠を使って簡単に書き換え:

cmemBuf.AppendStringF( L"(%I64d,%d)", nLine, nColumn );

auto_sprintf の余分なオーバーヘッドと文字列コピーのオーバーヘッドを排除できるのでこれだけでも数%の改善を見込める気がします。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Performance Profiler を使って計測してみました。

Win32 Releaseビルドで、リポジトリフォルダを以下の設定で Grep しました。

  • 条件:a
  • ファイル:*.cpp *.c *.h *.hpp *.hh *.cc
  • サブフォルダからも検索するにチェック

各3回、起動してからGrepして終了、という手順でProfile取っています。
Profileに起動処理も含めているので、Grep処理だけでいうとパーセンテージはもっと
大きくなります。

CGrepAgent::SetGrepResult の該当する処理の箇所のProfile結果を貼り付けます。

現時点の master (82724c0)

image
image
image

このPR (21326ab)

image
image
image

#418 (comment) 提案手法

image
image
image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この検証結果から分かることは、
ぼくの指摘内容に若干の効果があることと
beruさんのPRによる速度改善効果がケタ違いであることだと思います。

リポジトリ 平均値
master 63(3.71%)
ぼくの指摘 50(2.98%)
beruさんのPR 12くらい(1%未満)

比較してる処理内容が同じじゃないんで厳密な比較はできないんですがw

いちおう、改善効果があることは分かったうえのダメ出しであることをお伝えしときます。

このPRをリポジトリに入れると、似たようなテンプレ関数をあちこちにコピペでいれにゃならんハメになると思うからです。

コーディングの際はできるだけ Don't Repeat Yourself 原則 に気を遣い、Single Responsibility Principal を果たせるような構造を目指すのが理想だと思ってます。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このPRをリポジトリに入れると、似たようなテンプレ関数をあちこちにコピペでいれにゃならんハメになると思うからです。

それは自分も危惧していました。なので数値を文字列化する関数をどっか別のヘッダファイルに置いた方が良いんじゃないかとか少し思いましたし、そういう指摘が来るかもしれないと思ってました。

汎用化と特殊化による効率化って両立が難しいですね(poem

C++erだとstd::algorithmとファンクタを組み合わせて複雑な処理をコンパクトに書けるかもしれないですが、staticおじさんなのでベタにforループで書いておくれ…と思ったりします(再poem

コーディングの際はできるだけ Don't Repeat Yourself 原則 に気を遣い、Single Responsibility Principal を果たせるような構造を目指すのが理想だと思ってます。

日本の夏は湿度が高いのでその原則は適用しづらいです。

@@ -878,8 +878,36 @@ cancel_return:;
return -1;
}

// org : https://stackoverflow.com/a/12386915/4699324
template <typename T, typename ChT>
int s(T value, ChT *sp)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この関数名はだめだと思います。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int2dec に名前を変更しました。

if (i < 10)
*tp++ = (ChT)(i + '0');
else
*tp++ = (ChT)(i + 'a' - 10);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

16進数の対応は不要だと思います。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確かに不要ですね。レビューありがとうございます。

}

int len = tp - tmp;
if (value < 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

符号なしを前提にすることでもっと速くなると思います。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

確かにそうなのですが(行番号と桁番号で負数が無い事はコメントでも書かれている)

  • 変数の型は符号有り
  • 文字列化のループに比べるとそこまでコストが高くない

という事でそのままでも良いのではないかと思います。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while (tp > tmp) の部分のループは負の値をサポートするために必要になっています。
この関数は汎用性を捨てることで、速度を稼ぐために存在しています。

速度を稼ぐのが目的なら、必要のない汎用性は捨てるべきだと思います。
またテンプレートにする必要もないと思います。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while (tp > tmp) の部分のループって(下位の桁から文字列化して一時変数に出力しているので)本当の出力先に文字列を反転して書き出している処理という認識です。

負の値のサポートは確かに必要ない筈なので関数の入り口で assert で負じゃない事を確認して、不要な処理は省いた方が良いかもしれないですね。

数値の型が 行番号が LONGLONG で 桁番号が int で別々なので template 関数にしています。文字の型は wchar_t 固定なのでそこは template 引数にする必要は無いとは思います。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あと、符号ありの仕様のままにするにしても、整数部分の変換をする前に先に符号の判定を
行って最初に '-' を出力するようにすれば、while (tp > tmp) のループは削除できます。

Copy link
Contributor Author

@beru beru Sep 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あと、符号ありの仕様のままにするにしても、整数部分の変換をする前に先に符号の判定を
行って最初に '-' を出力するようにすれば、while (tp > tmp) のループは削除できます。

負の場合にマイナス文字を先に書き出す事自体は良いと思いますが、 while (tp > tmp) のループは文字列の反転に必要です。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ややこしくなりますが、

例えば 64bi の変数を 10進数で出力したときの最大桁数以上のバッファを用意した上で
後ろから先頭にデータを詰めていって、先頭アドレスのポインタを返せば無駄に
コピーしなくてよくなります。

あと、value の値が 0 のときに正しく動作しません。
while 文ではなく do - while 文にしたら動くようになると思います。

@berryzplus さんも書いているように同様の最適化をすると思うので、高速化のために
同様の文字列関数が作られていくことになるかもしれないので、ユーティリティを
入れるためのファイルを用意して、再利用できるようにした方がいいです。

実装を見て、関数仕様を想像して、というスタンスのようですが、
明確にどんな関数仕様なのかをコメントで明示した方がいいと思います。
WIP の PR なので後でやるというのなら、省略するのもありですが、
WIP ではない PR ならそこら辺は記載してほしいです。

value の値が 0 のときに正しく動作しないことを書いたように
どんな場合にどんな結果になるのかが確認、デグレ確認できるように
単体テストを書いた方がいいと思います。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

例えば 64bi の変数を 10進数で出力したときの最大桁数以上のバッファを用意した上で
後ろから先頭にデータを詰めていって、先頭アドレスのポインタを返せば無駄に
コピーしなくてよくなります。

間違いです。これは無理でした。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@berryzplus さんも書いているように同様の最適化をすると思うので、高速化のために
同様の文字列関数が作られていくことになるかもしれないので、ユーティリティを
入れるためのファイルを用意して、再利用できるようにした方がいいです。

他のところでも使いたくなったら、後のPRで対応すれば良いかなと思っていましたがこのPRで整備した方が良いでしょうか?

実装を見て、関数仕様を想像して、というスタンスのようですが、
明確にどんな関数仕様なのかをコメントで明示した方がいいと思います。
WIP の PR なので後でやるというのなら、省略するのもありですが、
WIP ではない PR ならそこら辺は記載してほしいです。

コメントについては記載が面倒で書いていませんでした。しかし他の人がレビューする手間を考えるときちんと書いておかないと恨まれそうですね…。

Copy link
Contributor Author

@beru beru Sep 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 の場合に正しく文字列化されるように指摘通りに do while ループに変えて修正しました。

#418 (comment) にも書きましたが、

std::numeric_limits<int32_t>::min()
std::numeric_limits<int64_t>::min()

等の時に正しく動作しない事が分かりました。あと数値の型が uint32_tuint64_t の場合にコンパイルエラーが出る事も分かりました。

今回の CGrepAgent::SetGrepResult から呼び出すケースでは問題になりませんが、共通ヘッダにおいて他からも使うとなると(コーナーケースですが)対処した方が良いかもしれません。

あと単体テストを書くとなると、sakura_core/CGrepAgent.cpp に置いたままだと参照出来ないので他のファイルに移すことになり、他のファイルに移すと他からも呼べるようになる(なってしまう…)ので細かい不具合を直した方が良いかもしれません。

T v = abs(value);

while (v) {
T i = v % 10;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

変数名の付け方が、いけてないと思います。
変数名を見ただけで意味がわかる、あるいはコメントで補足するようにしてほしいです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while ループ内でローカル変数を宣言しないようにしました。
10進数限定という事もあり式だけで処理内容が自明なのでローカル変数を使う意味がないので。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

関数仕様のコメントがほしいです。
引数、戻り値の仕様、あと printf でできるところを敢えて自前実装する理由がほしいです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コメントを追加しました。

@@ -921,8 +949,14 @@ void CGrepAgent::SetGrepResult(
cmemBuf.AppendString( L"・" );
}
cmemBuf.AppendStringT( pszFilePath );
::auto_sprintf( strWork, L"(%I64d,%d)", nLine, nColumn );
cmemBuf.AppendString( strWork );
wchar_t* p = strWork;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

速いけどわかりにくいコードをインライン関数を使うなどして、速度を落とさないようにしながら、隠蔽化してほしいです。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

また速いけどわかりにくいコードを書くときは、遅いけどわかりやすいコードも
同時に書いて、両者が一致することを確認する単体テストを書く、あるいは
Debug 版に限って両方実行して、両者が一致することを確認するのが定石です。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lineColumnToString 関数を用意してそこで処理するようにしました。
デバッグビルド時には元のコードと処理結果が同じかどうか確認するようにしました。

@m-tmatma
Copy link
Member

m-tmatma commented Sep 8, 2018

説明欄にもっとわかりやすい説明を書いてほしいです。

*p++ = L',';
p += int2dec(nColumn, p);
*p++ = L')';
*p = NULL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NULL は意味が違います。
NULL は NULL ポインタを表します。NULL 文字ではありません。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null character ('\0') に記述を変更しました。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

二カ所あるうちの一カ所しか直っていないです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lineColumnToString 関数の中にも同様の記述がありましたが、指摘いただいた通り対応が漏れていたので修正しました。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NULLは #define NULL 0 で、 const int の定数値なので '\0' と同じ意味だと思います。
ただ、あえて '\0'L'\0'` と書くことで、人間による誤読を防ぐ効果があるような気がします。

厳密には windows プログラミングで多用される NULL は多くの場合 nullptr に書換えすべき・・・
という主張もときどき見かけますね。

Copy link
Contributor Author

@beru beru Sep 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

値は同じでも表記を使い分けた方が良いのはその通りですね。

NULL を C++11 から入った nullptr に書き換えた方が良いというのはまぁそうなんですけど見返りが null というか void というか…。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NULLは #define NULL 0 で、 const int の定数値なので '\0' と同じ意味だと思います。

C++ ではそうですが、

C では #define NULL ((void*)0) でした。
C++ だと C の定義だといろいろ不都合があるというのでその定義になっているだけで
意味が変わったのではないです。

@berryzplus
Copy link
Contributor

なんかペアプログラミングみたくなってますねww

数値を文字列化するテンプレ関数の置き場所は sakura_core/util 配下のどっかとかでどうでしょう。
今回のコードでは問題にならないですが、wchar* の残りサイズを意識しない作りになってるのがやや気になっています。assertするためだけの引数でいいので残りサイズをチェックしたほうがいいのかな、と。

あと、変更対象の処理のすぐ下に WZ風向け でほぼ同じコードがあるんですが、これは対象にしなくていい感じなんですかね?

@beru
Copy link
Contributor Author

beru commented Sep 8, 2018

なんかペアプログラミングみたくなってますねww

そうですね、細かくレビューして頂いて助かってます。

数値を文字列化するテンプレ関数の置き場所は sakura_core/util 配下のどっかとかでどうでしょう。

他の箇所でも使う為にこのPRで整備した方が良いですか?他のところでも使いたくなったら、後のPRで対応すれば(先延ばしすれば)良いかなと思っていました。

今回のコードでは問題にならないですが、wchar* の残りサイズを意識しない作りになってるのがやや気になっています。assertするためだけの引数でいいので残りサイズをチェックしたほうがいいのかな、と。

呼び出し元で処理内容に応じて十分な大きさのバッファを用意して使う前提で考えていました。もし考慮が漏れて不具合が生じたら誰かにデバッグを楽しんでもらえればと…。

あと、変更対象の処理のすぐ下に WZ風向け でほぼ同じコードがあるんですが、これは対象にしなくていい感じなんですかね?

誰か使ってる人いるんでしょうか?

@berryzplus
Copy link
Contributor

数値を文字列化するテンプレ関数の置き場所は sakura_core/util 配下のどっかとかでどうでしょう。

他の箇所でも使う為にこのPRで整備した方が良いですか?他のところでも使いたくなったら、後のPRで対応すれば(先延ばしすれば)良いかなと思っていました。

先延ばしでもいいです。
気にしているのは、ありがちな処理が局所化された状態でツリーに入ることです。
単体テストがあれば文句はないんですが、そこまでやりたいですか?って話でw

もし考慮が漏れて不具合が生じたら誰かにデバッグを楽しんでもらえればと…。

レガシーですね。

日本語訳: 負の遺産

あと、変更対象の処理のすぐ下に WZ風向け でほぼ同じコードがあるんですが、これは対象にしなくていい感じなんですかね?

誰か使ってる人いるんでしょうか?

「自分は使わないので(検証できないので)対応しない」で理屈は通るので対応しなくて大丈夫です。
別件として、どっかで廃止のissue立てますか・・・。

@@ -909,7 +967,7 @@ void CGrepAgent::SetGrepResult(
{

CNativeW cmemBuf(L"");
wchar_t strWork[64];
wchar_t strWork[128];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

このバッファサイズを変更した根拠って指摘ですか? (指摘見返せばいいのかも知れませんけどw

L"(%I64d,%d)" を書式化するために必要なバッファは、
1 + 20 + 1 + 10 + 1 = 33 なので 64 で十分足りる気がしています。

http://logrepo.blogspot.com/2010/08/264-2-64.html

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

指摘ではなくて自分の変更です。もし溢れて暴走したら嫌だなぁと思って計算せずにこれぐらい増やしておけば大丈夫だろうと思って変えておきました。大は小を兼ねるという事で 1024 ぐらいにした方が良かったですね。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e6cc577 で配列のサイズを元に戻しました。

@beru
Copy link
Contributor Author

beru commented Sep 8, 2018

先延ばしでもいいです。
気にしているのは、ありがちな処理が局所化された状態でツリーに入ることです。
単体テストがあれば文句はないんですが、そこまでやりたいですか?って話でw

@berryzplus さんの許可は頂けたので後は @m-tmatma さんが許可していただければ、 数値を文字列化するテンプレ関数をどっか別の場所に移すのは先延ばしに出来ればと思います。

単体テストを書くとなると参照できるようにする為に引っ越しする必要が有ります。

std::numeric_limits<int32_t>::min()
std::numeric_limits<int64_t>::min()

等で正しく文字列化されない不具合があるのと、uint32_t とか uint64_t だと abs 呼び出しで
error C2668: 'abs': ambiguous call to overloaded function とコンパイラが文句を言ってくる事が分かりました。

レガシーですね。

変更を局所的に隔離する事で品質を担保しましょう。きっと将来もっと良い実装に誰かが置き換えてくれるに違いありません。

別件として、どっかで廃止のissue立てますか・・・。

それをすてるなんてとんでもない!

@m-tmatma
Copy link
Member

m-tmatma commented Sep 8, 2018

レガシーですね。

日本語訳: 負の遺産

少なくともコンピュータ業界では主にマイナスな意味で使われますが、

最近は違ういい意味でも使われるみたいです。
https://kotobank.jp/word/%E3%83%AC%E3%82%AC%E3%82%B7%E3%83%BC-669968

@beru
Copy link
Contributor Author

beru commented Sep 8, 2018

今回のコードでは問題にならないですが、wchar* の残りサイズを意識しない作りになってるのがやや気になっています。assertするためだけの引数でいいので残りサイズをチェックしたほうがいいのかな、と。

まぁそこまで親切設計にしないでも良いかなと思います。引数が増えるとコメントも書かないといけませんし。

@beru
Copy link
Contributor Author

beru commented Sep 8, 2018

d1f7b3b

  • int2dec 関数を記述するファイルを sakura_core/CGrepAgent.cpp から sakura_core/util/string_ex2.h に移して将来的に他でも使えるようにしました。
  • int2dec 関数の単体テストを記述しました。

}

while (tp > tmp)
*sp++ = *--tp;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この部分、++ と -- は別の文に分けた方がいいと思います。
行数を節約するよりも意図が明確であるようにした方がいいです。
またコードのブロック単位で何をしようとしているかのコメントが欲しいです

114 行目はまあいいかなと思いますが。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

load と store の記述行を分けるようにしました。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

各所にコメント追加しました。

ChT tmp[64];
ChT *tp = tmp;

bool isMin = (value == std::numeric_limits<T>::min());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これ何ですか?

Copy link
Contributor Author

@beru beru Sep 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

過去のコメント でも記載しましたが、

std::numeric_limits<int32_t>::min()
std::numeric_limits<int64_t>::min()

を渡すと正常な結果を作れない問題に対する対策です。

abs に 符号付きの型の負数の最小値を渡すと、結果が表現できないのでC言語の仕様上は未定義のようです。なので最小値の場合は abs 前に 1 足す事で abs で処理出来るようにし、また10進数の文字列を生成後に1桁目の文字に 1 足す事で正しい値に直しています。

#include "../../sakura_core/util/string_ex2.h"

template <typename T>
void test_int2dec(T value, int lenAnswer, const wchar_t* strAnswer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

answer より expected というのが自然だと思います。
関数の期待値を指定するからです。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resultに一票。

answerはメッセージボックスとかのユーザ入力を格納するのによく使います。
expectedはテストコードで期待値を渡すときによく使います。
resultは出力値を表すときによく使います。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ああ、testだからexpectedがいいのかw

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EXPECT_EQ マクロとか使っているので expected が適してるっぽいですね。

EXPECT_STREQ(buff, strAnswer);
}

TEST(test, zero)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test という名前ですが、
int2dec あるいは それを含む値にしたらいいと思います。
名前から何のテストかわからないです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tests/unittests/test-sample.cpp の記述をコピペしていました。

https://github.com/google/googletest/blob/master/googletest/docs/primer.md#simple-tests

指摘いただいた通りちゃんと名前つけた方が良いですね。

test_int2dec<int32_t>(std::numeric_limits<int32_t>::max(), 10, L"2147483647");
test_int2dec<int64_t>(std::numeric_limits<int64_t>::max(), 19, L"9223372036854775807");
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

値が 1, 12, 123, 1234, 12345 とか通常の正常値の値のテストもほしいです。
↑ 上記は変換後の桁数が 1 桁、2桁、... という観点です。

同様に上記でマイナスの場合もあった方がいいです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TEST(int2dec_test, group_sequence) で追加しました。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

負数の試験を 8b5a134 で追加しました。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。
group_sequence で同じテストがされるようになって
plus_minus_1 のテストがいらなくなったので削除お願いします。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

65204a1 で対応しました。

#define NOMINMAX
#include <Windows.h>
#include <tchar.h>
#include "../../sakura_core/basis/primitive.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#422 で sakura_core のパスまでをインクルードディレクトリ指定できるようにしました。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます。お陰で ../../sakura_core/ は削れるようになったので削っておきました。


// reverse digits
while (tp > tmp) {
ChT d = *--tp;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そういう意味ではないです。
*--tp*sp++ です。

以下のように分けるという意味です。

tp--;
*sp = *tp;
sp++;

++ と -- は独立して使わないと意味を理解するのにすこし時間がかかりますし
コードを書いた人以外がメンテするのが難しくなります。

本当は以下も分けた方がいいと思いますが、イディオム的な書き方なのでまあいいかということです。

*sp++ = '-';

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7d18d13 で対応しました。

*/
static inline
wchar_t* lineColumnToString(
wchar_t* strWork, /*!< [out] 出力先 */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

この関数に書込み可能バッファを付ける話ってどうなりました?

template <size_t nCapacity>
static inline  
wchar_t* lineColumnToString(  
    wchar_t( &strWork )[nCapacity],

とすれば引数を増やさなくても nCapacity でデバッグアサート仕込めると思うんですが。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4e09445 で対応しました。

#include <Windows.h>
#include <tchar.h>
#include "basis/primitive.h"
class CNativeA;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CNativeA と CNativeW の先行宣言はここに書くべきことではないですね。

string_ex2.h の以下の箇所で、CNativeA と CNativeW が参照されているのだから
別 PR で、string_ex2.h の不具合として CNativeA と CNativeW の先行宣言を string_ex2.h に足すべきですね。

int AddLastChar( TCHAR*, int, TCHAR );/* 2003.06.24 Moca 最後の文字が指定された文字でないときは付加する */
int LimitStringLengthA( const ACHAR*, int, int, CNativeA& );/* データを指定「文字数」以内に切り詰める */
int LimitStringLengthW( const WCHAR*, int, int, CNativeW& );/* データを指定「文字数」以内に切り詰める */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string_ex2.h の不具合なのかというと、そうでもないと思いますが string_ex2.h 側で対処されていると #include する側は楽ですね。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

string_ex2.h の不具合

<string.h>LimitStringLength なんて関数ありましたっけ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

以下では CEol に対しては先行宣言しているのに、 CNativeA と CNativeW に対しては
漏れているので対応が一貫していないので不具合という認識です。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#423 で先行宣言足しときました。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<string.h> に LimitStringLength なんて関数ありましたっけ?

<string.h> には無いですが、 sakura_core/util/string_ex2.cpp に実装があります。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#423 で先行宣言足しときました。

rebase して tests/unittests/test-int2dec.cpp には先行宣言は書かないようにしました。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

util/string_ex.hにCNativeWの先行宣言を追加した理屈でいくと
basis/primitive.hのインクルードも「util/string_ex.hに追加すべき」となる気がします。
string_ex.hはprimitive.hのdefine ACHARに依存していて、
ACHARを先行定義しないとコンパイル通りません。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

全部を完璧に対応する必要はないと思っています。
対応をお願いしてる部分に対処いただければそこで一旦終わりと認識いただいて大丈夫です。
ACHARの件は対応不要です。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PRどうぞどうぞ

static_assert(std::is_signed_v<T>, "T must be signed type.");

// temporary buffer
ChT tmp[64];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ほぼ同じなんですけどこれも出力バッファサイズあったほうがいいです。

template <typename T, typename ChT, size_t capacity>  
int int2dec(  
    T value,	//!< [in] the integer value to stringify  
    ChT ( &sp )[capacity]		//!< [out] the destination string to store the stringified result  
)

宣言が上記のようになってれば ChT tmp[capacity]; と書けるような。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そうすると固定長配列を使う事が前提になるので今 lineColumnToString で呼び出しているような使い方が出来なくなりませんか?

チェック機能付きのオーバーロードとか用意する手もあると思いますが、現状では使ってなくて現時点では不要です。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

そうすると固定長配列を使う事が前提になるので今 lineColumnToString で呼び出しているような使い方が出来なくなりませんか?

確認しました。対応不要です。

} while (v);

// postadjuist the lowermost digit letter
tmp[0] += isMin;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

あれ? bool isMinだった気が・・・。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

整数型とbool型で直接演算してええの?という疑問はありますがコンパイラが警告出してないし処理結果も正しいようなので別にいいかなと判断しました。

bool の値が C++規格上 1 or 0 になる事が決まっているとどっかで読んだ気がしたのも一因です。
https://stackoverflow.com/a/4276239/4699324

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

コードの意図が理解できませんでした。年かなぁ...orz

   tmp[0] += (isMin ? 1 : 0); // 符号付き最小値は -1 された値になってしまうので調整する

こういうことですよね?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

自分で書いててなんですがちょっとコードが分かりにくいですよね。3日後の自分も @berryzplus さんと同じ印象を抱いていると思います。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

できれば修正をお願いします。
コメントまでコピるかどうかの判断はお任せします。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#418 (comment)

のコメントに解説を書きましたので参照お願いします。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

了解です。加算する値が 1 or 0 であることが明確になるようにする修正はお願いしたいです。

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

加算する値が 1 or 0 であることが明確になるようにする修正はお願いしたいです。

修正というのは具体的にはどういう内容をリクエストされていますか?
解説のコメントを入れる事ですか?
それとも型を bool から int に変えたり、余計な bool ? 1 : 0 を記述する事ですか?

それらは不要と判断してあえて記載しませんでした。必要だという事を示す明確な根拠は特に求めてはいませんが、リクエスト内容は明確にしていただきたいです。

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tmp[0] += (isMin ? 1 : 0);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7adde4c で bool 型のローカル変数を当該関数から追放しました。

Copy link
Member

@m-tmatma m-tmatma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

いっぱい対応ありがとうございます。

可能であれば、現バージョンで再度プロファイルを取って、貼り付けていただけますか?
#418 (comment)

@m-tmatma
Copy link
Member

@m-tmatma
Copy link
Member

https://ci.appveyor.com/project/sakuraeditor/sakura/build/1.0.776 が失敗していたので
https://ci.appveyor.com/project/sakuraeditor/sakura/build/1.0.777 でリビルド開始しました。

以下参照
#151 (comment)

@beru
Copy link
Contributor Author

beru commented Sep 12, 2018

可能であれば、現バージョンで再度プロファイルを取って、貼り付けていただけますか?

再度プロファイルを取ってみました。grepの検索条件は以前と同様です。

このPR (2cabcc7)
image
image
image

現時点のmaster (9b07706)
image
image
image

grep の実行時間も計測して比較した方が本当は良いんですが、少し手間なので諦めます。

@beru
Copy link
Contributor Author

beru commented Sep 12, 2018

レビューありがとうございました。Merge します。
もし問題が見つかった場合は別のPRで対処する事にしましょう。

@beru beru merged commit e754540 into sakura-editor:master Sep 12, 2018
@ds14050 ds14050 added the 🚅 speed up 🚀 高速化 label Sep 18, 2018
@beru beru deleted the SetGrepResult branch October 8, 2018 14:59
@m-tmatma m-tmatma added this to the next release milestone Oct 21, 2018
HoppingTappy pushed a commit to HoppingTappy/sakura that referenced this pull request Jun 11, 2019
CGrepAgent::SetGrepResult 出力形式がノーマルの場合の処理の高速化
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants