Windows7のネットワークが異様に遅い問題
こっちにも書いとこう。
-
-
- -
-
家庭内の共有ファイルアクセスも遅くてこまるし頻繁にネットワークが切断される(というかタイムアウトしてる?)のでどうにかせにゃなーと検索してみた。64bit版でアプリケーション自体の速度は問題ない(ややメモリが使いすぎな感があるが)けどネットワークは本当に遅い。くだりが平均20k、早くても50k…Visual Studio試用版のネットワークインストールが半日たっても終わらない…
チェックサムは、ネットワークを介して転送されるデータの完全性をチェックするシンプルなエラー検出方式です。TCP/IP/UDPなどの通信プロトコルでは、この方式が実装され、受信データがネットワーク上で破損していないかどうかの確認に使用されます。IPv4データグラムの送信元は、データに基づいてチェックサムの値を計算し、それをフレームに埋め込みます。受信側もチェックサムを独自に計算し、その結果に基づいてデータの完全性を確認します。同様に、IPデータグラムのペイロードになるTCP/UDPデータについても、チェックサムが計算され、その値がTCP/UDPフレームに埋め込まれます。
一般に、Fast Ethernetシステムでは、この計算はCPU上で実行されるドライバ・ソフトウェアによって実行されます。しかし、Gigabit Ethernetや10Gbpsの通信速度によるデータ転送では、ソフトウェア・ドライバによるチェックサムの計算はCPUにとって大きな負担になります。このことがホストの最大の課題のひとつであり、アプリケーション処理にまわすCPUサイクルが減少する原因になっています。その結果、ネットワークのフル活用が不可能になり、パフォーマンスが低下してしまうのです。
ということなのだが10Gbpsもあるはずがない家のネットワークではチェックサムオフロード機能はいらんだろう…だいたいデュアルコアなんだからCPUもうちょっと働けむしろ(´∀` )オマエガナーと思ったのでとりあえずIPv6だけ切ってみた。
- [コントロールパネル]-[ネットワークと共有センター]-[アダプターの設定の変更]と進んで、ローカルエリア接続の右クリックメニューからプロパティを開く。
- ついでなのでインターネットプロトコルバージョン6のチェックをはずして(個人的にはこれはおまじない程度だと思っている)OKののちもう一度同じようにプロパティを開く。
- [構成]でネットワークアダプタのプロパティを開いて詳細設定タブをクリック
- TCP チェックサムオフロード(IPv6), UDPチェックサムオフロード(IPv6),一括送信オフロード v2(IPv6)をすべて無効にしてOK
ネットワークが一度切断されるけどすぐに再接続される。
転送速度をみると20k->1800k
ちょwwwwwおまwwwwwwwwwwwwwwwww
IPv4のほうもはずしてみたんだけどそしたら900kくらいになったのではずさなくてもいいのかも。XPでははずしてなかったし(というかデフォルトにしていた)Vistaでも問題がない(もちろんデフォルトまま)なので、そこら辺はネットワークカード上のチップとCPUのトレードオフになるあたりなのかも。
IPv6がどうも悪者扱いされているようだが、別に悪いわけじゃないんだけどなぁ。おまじないではなく正しい対処法が広まってほしい。
http://blog.penchi.jp/archives/558.html
http://www.akakagemaru.info/port/windows7ipv6.html
これはネットワークがブツブツ途切れる場合の対処法。ネットワークの切り替えが頻繁に行われるための切断もありうるので、特にブラウジングをしているわけでもないのにネットワークが切断と再接続を繰り返している場合は上記のリンク先の対処法をするのが正しい。
一方でページのロード含め、ネットワーク使用中に切断される場合は、ネットワークの太さに対してデータが大きすぎるために待ち時間が発生していると考えたほうがよい。この場合IPv6を切っても意味がない。なぜならそこが原因ではないからだ。特にブラウジングをしていないときにネットワークが切断される現象が起きないのなら、余計な計算や処理をしているために待ち時間が発生してタイムアウト→切断→再接続になっていると思われる。
のでここで書いてある方法か
http://netserc.blog63.fc2.com/blog-entry-231.html
ここら辺を参考にするのがよいかと。
この記事がもう少しいろんな人に読まれるといいんだがなぁ。
templateのパラメータ引数に制限を設ける
templateはどんな型でも取れちゃうけど取れると困る場合がある。C++0xだとコンセプトっていうのがあるらしいけどC++0xなにそれおいしいの?なので…
実行してからじゃないとわからないようなのだとバグを仕込んでいるのと変わりないので、できるだけコンパイルエラーで検出したいですね。
型はなんでもいいけどスカラかポインタかは区別したい
参照で入れる場合などは注意ということでしょうな。
int main(void){ int var; int* pVar; test(&var); test(&pVar); } class A{ public: template<class T> void test(T* p); }
確かにこれは区別がつかないけど困るな。というわけで制限をかける。
スカラ以外はだめだよという場合は、
template<class T> void test(T* p){//実装する}; template<class T> static inline void test(T**); //実装しない
これは別にメンバ関数でもOK。template
逆にすからはだめで配列だとOKという場合はどうすればいいのだろう?あんまないからいいのか…?
型を制限したいその1(特殊化)
テンプレートの特殊化については以下を参照のこと。
http://www.geocities.jp/ky_webid/cpp/language/037.html
特殊化自体は「この型だけは別の実装で!」とするための手法(型がそんなに多くないならインターフェイスつくって継承先で実装した方がよさげだ)なんだけど、これを使って特定の型だけに制限をかける。
template<class T, class U> struct check_type; template<class T, class U> void test(T var1, U* var2); //許可する型の組 template<> struct check_type<int, char*>{}; template<> struct check_type<unsigned int, char*>{}; template<class T, class U> void test(T var1, U* var2){ //型チェック (void)sizeof(check_type<T, U>); //実装 };
よく見てないでtest関数を特殊化しようとした馬鹿は僕だけで十分です。
TとUの組で知らないのが出てくるとどのcheck_typeかわからなくてエラーが出るんだねー。これである特定のだけはじけるとかできればいいのになぁ。
これは割と楽でいいんだけど、もっとたくさんある場合は全部書くの大変だし、継承関係あるのなら一気に調べたいという場合はその2へ。
型を制限したいその2
//テンプレートのパラメータ引数に入るはずのクラス class A{}; class B{}; class A1{}; class B1{}; class A2: public A {}; class B2: public B {}; /* C.h */ /* テンプレートメンバ関数を持ったクラス */ #define STATIC_ASSERT(p) typedef int static_assertion_faild[ p ? 1 : -1] typedef char correct_type; typedef struct { char dummy2[]; } incorrect_type; //分かりやすいコンパイルエラーを出力 //正しい correct_type type_check(const volatile A*, const volatile B*); correct_type type_check(const volatile A1*, const volatile B1*); //正しいもの以外は全部はじく incorrect_type type_check(...) class C { ... public: template<T, U> void func(T p1, U p2); } /* C.cpp */ template<T, U> void func(T p1, U p2){ STATIC_ASSERT((sizeof(type_check((T*)0, (U*)0)) == sizeof(correct_type)); //あとの処理 } void callFunc(){ A a; B b; A1 a1; B1 b1; A2 a2; B2 b2; Adummy ad; Bdummy bd; //コンパイルエラーでない func(a, b); func(a1, b1); func(a2, b2); //コンパイルエラー出る func(ad, bd); }
これはかっこいい!
これでcorrect_type以外の組み合わせの場合は弾いてくれる。volatileが付いてると継承クラスまでは許可するのかな。厳密にこれだけとするならvolatileはつけないほうがヨサゲ
http://proger.blog10.fc2.com/blog-entry-20.html
volatileについてはこちら。最適化を抑制するから子クラスからは継承元の公開されてるものは全部見えるので、同じものだよとわかってくれるっつーことか。
特に制限を書いてないけど制限できちゃうよという例
テンプレートパラメータが二つあるとできるぽい。
/* CMyList.h */ template<class T> class CMyList{ public: void copyNum(Func1 func_){ m_func = func_; }; private: Func1 m_func; }; /* Func.h */ class Func1 : public Func { public: &Func1 operator=(Func1 var){ m_num = var.m_num; return *this; }; private: int m_num; } /* CTest.h */ template<class T, class U> void test(CMyList<T>* list_, U fct); /* CTest.cpp */ template<class T, class U> void test(CMyList<T>* list_, U fct){ list_->copy(fct); } /* main */ int main(void){ CMyList<MyFactor> list; Func1 func1; Func func test(&list, func1); //OK //test(&list, func); //Compiler error }
間にテンプレートクラスがあるからかどうかはまた別問題として、テンプレートはビルド時だったかコンパイル時に展開するために、展開先が見つからないとエラーを出してくれる(今までのも全部それでエラーが出る)ので、このTとUの組み合わせが常に決まっているような場合はエラーが出力されます。この場合だとMyListのコピーメソッドのところでFunc1と決定しているのでそれ以外のが来ちゃうとエラーが出る。
こんなバカみたいな設計になんねーからとか思うあなたは正しいと思います。
こういうのはそうなったからラッキーなのであって、基本的には自分でアサーション出させるとかにした方がいいんだろうなぁ。うーむ。