データベースサーバの非同期レプリケーション機能を実装したが、そのプロトコルと実装の詳細について述べつつ、妥当性について検証しよう。非常に細かくて重箱をつつく話になるが、神は委細に宿るとも言うし、ないがしろにできないことばかりだ。
DBサービスを作ろう その7 シャーディング最強説
シャーディングによってデータベースを分割することで、通常運用の並列処理性能を向上させることができる。それだけでなく、バックアップ作成などの、他のスレッドをブロックさせうる操作の影響を最小限に留めることができる。その運用方法について説明する。
続きを読むキャストに関わるGCCの謎挙動
GCCの不可解な挙動に悩まされている。以下のコードは、負数を出力しないことが期待されるが、-O2以上の最適化をすると負数が出力されてしまう。
#include <cstdint> #include <cstdio> int main(int argc, char** argv) { constexpr uint32_t modulo = 2039; for (int32_t i = 0; i < 65536; i++) { const int32_t result = static_cast<uint32_t>(i * i) % modulo; std::printf("%d\n", result); } return 0; }
上記で、i の値が46340を超えると、i * i の値がint32_tの範囲をオーバーフローして負数になる。その直後にuint32_tにキャストされると正数に変換され、その後に2039で割った余りになるので、結果は0から2038の間になるはずだ。それをint32_tにキャストしてもオーバーフローはしないはずだ。-O0と-O1では期待通りに動作する。しかし、-O2以上の最適化をすると、負数が生成される。-O2以上の最適化をする場合も、変数moduloの宣言にvolatileをつけると負数は生成されない。
gccのバージョンはgcc (Ubuntu 10.3.0-1ubuntu1~20.10) 10.3.0だ。バグなのか、仕様上で未定義の挙動を引き起こす記述をしてしまっているのか、わからない。キャストが無視されているのはアセンブリ出力を見るまでもなく明らかなのだが、なぜそうなるのかというか、仕様通りなのかどうかが知りたい。「最適化によってキャストが無視されることがある」という事実を認めるとすると、どのような場合にそれが起こるのか知っておかないと安心して暮らせないだろう。ご存知の人がいたら教えてほしい。
続きを読む