ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

C言語とC++言語コミュのWSAStartup()のオーバーヘッド

  • mixiチェック
  • このエントリーをはてなブックマークに追加
DNSの正引き、逆引きを行う以下のような2つの関数

namespace mydns
{
  unsigned long ResolveIpaddr(const std::string &);
  std::string ResolveName(unsigned long);
}

をエクスポートするようなDLLを作っていまして、
それぞれの関数の中では、getaddrinfo()/getnameinfo()を呼び出しており、
その前後でWSAStartup()/WSACleanup()を呼び出すような実装にしています。

http://www.kt.rim.or.jp/~ksk/wskfaq-ja/articles/lame-list.html で、
「14. 一連の Winsock 処理を実行するたびに毎回 WSAStartup() と WSACleanup() を呼び出す。
間違いの包囲網を突破してる。 」と書いてあるように、
必要以上の処理をしていることはわかっているのですが、
実際のところ、WSAStartup()を呼び出すオーバーヘッドって、
どのくらい大きいものなのでしょうか?

なお、このDLLはマルチスレッド環境で使用されることともあり、
WSAStartup()関数自体がスレッドセーフなのかどうかも気になっています。

コメント(8)

自分の環境で測定すればいいんじゃないの
sock/vuelaさん>
「論より証拠」ですね。測定してみました。

測定方法:
WSAStartup();
getaddrinfo();
WSACleanup();
を10,000回ループさせた。

結果:
WSAStartup(); - 649ms (33.9%)
getaddrinfo(); - 1,123ms (58.6%)
WSACleanup(); - 76ms (4.0%)

かなり大きい (^^;

ResolveIpaddr()かResolveName()が初めてコールされたときだけ、
WSAStartup()が呼び出されるように、

class WinsockInit
{
public:
  WinsockInit() { WSAStartup(); }
  ~WinsockInit() { WSACleanup(); }

private:
  WinsockInit(const WinsockInit &);
  void operator =(const WinsockInit &);
};

のようなクラスを作って(エラー処理は省略)、

unsigned long ResolveIpaddr(const std::string &name)
{
  static const WinsockInit init;
  getaddrinfo();
}

のようなことを考えたのですが、initの初期化がスレッドセーフじゃないし、
WSACleanup()がmain()の外側で呼ばれてしまうのもNGかと。
行き詰まってしまいました。
ちなみに、DLLユーザーにWinsockの初期化などを意識させないで、
DNSの名前解決ができるようにするのが目的なので、
「自分でWSAStartup()/WSACleanup()を呼んでくれ」とか、
上記WinsockInitのようなクラスをエクスポートして、
「ResolveIpaddr()/ResolveNam()を呼び出す前にWinsockInitを作ってくれ」
というのはNGです。
自作のDLLにDllMain()を実装し、そこで初期化と後始末をするのはどうでしょうか?
http://msdn.microsoft.com/en-us/library/ms682583.aspx
DLLMain()でWSAStartup()/WSACleanup()を呼ぶのは御法度のようです。
http://msdn.microsoft.com/en-us/library/aa290048.aspx
---
The following operations are specifically identified as being unsafe inside a DllMain function under most circumstances:

* Calling the LoadLibrary, LoadLibraryEx, or FreeLibrary functions directly or indirectly.
* Calling the registry functions.
* Calling imported functions other than those located in Kernel32.dll.
* Communication with other threads or processes.
---
うさぴょんの育ての親>
言われてみれば...確かに。
DNSクライアントサービス(dnscache)を止めて再測定したところ、

WSAStartup(); - 677ms (10.1%)
getaddrinfo(); - 5,829ms (87.0%)
WSACleanup(); - 85ms (1.3%)

となりました。
これくらいなら無視できるオーバーヘッドと見なせますね。
ご助言ありがとうございました!

あとは、WSAStartup()/WSACleanup()自体がスレッドセーフなのかどうかか。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

C言語とC++言語 更新情報

C言語とC++言語のメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。

人気コミュニティランキング