デベロッパー

デベロッパー

Visual StudioのWeb参照とカスタムクラスのパフォーマンスを比較する

Jamie Davis, John Jakovich, Sam Menard
2010年5月4日 / 10:00
 
 

はじめに

 私たち開発者はみな、何らかの仮定に基づいてプログラミングを行います。その仮定の中で最も大きなものは、「.NET Frameworkに付属するライブラリとツールは、決まったタスクを達成するための最善の方法である」ということです。例えばほとんどの開発者は、Webサイトのユーザーアカウントを管理するためには、ユーザーアカウントストアを自作するよりも、ASP.NETのMembershipシステムを使った方がよいと当然のように思っています。Webサービスに接続するときのWeb参照の追加についても、同様のことが言えます。私たちは当然のように、Web参照を追加することで、Webサービスの呼び出し、パラメータのシリアライズなどの低レベルの詳細を処理するプロキシクラスを自動生成するマークアップを生成しています。

 最近、.NET FrameworkおよびWebサービスに関する私たちの基本的な仮定の1つについて、顧客から質問を受けました。それは「Webサービスに接続するために、なぜVisual Studioが作成したプロキシクラスを使用しなければならないのか?」というものでした。このプロジェクトでは、Webサービスを呼び出してデータを取得し、それからソートと若干の書式設定をしたうえでWebページに表示していました。しかし顧客は、HttpWebRequestクラスでWebサービスを直接呼び出し、XML出力を取得し、XmlDocumentオブジェクトにロードし、それからXSLTを使用してその結果をHTMLに出力する方が効率的ではないかと仮説を立てました。確かに、その方がVisual Studioの自動生成プロキシクラスを使用するより速いようにも思えます。

 この質問を受ける前は、プロキシクラスの自作を考えたことはありませんでした。これまではいつも、Visual Studioが自動生成したプロキシクラスを利用してきたのです。これらの自動生成プロキシクラスが非効率的ということはあるでしょうか? WebサービスのXMLを直接取得して構文解析する方が効率的でしょうか? これを確実に知るためには、顧客の仮説をテストしてみるしかありませんでした。

 この記事では、この仮説をテストするために行った実験を詳しく解説します。最後まで読んで、結果を確認してください。

Webサービスを呼び出すための2つのアプローチ

 Visual Studioの[Web参照の追加]オプションは、Webサービスを呼び出すための便利なツールです。このツールでは、WebサービスのWSDLファイルのURLを指定できます。これはXML形式のファイルであり、Webサービスによって提示されたメソッドと通信プロトコル、およびWebサービスとの対話に欠かせないその他の低レベル情報を記述しています。このWSDLファイルから、Visual StudioはWebサービスのメソッドを「ラップ」するプロキシクラスを自動的に生成します。要するに、プロキシクラスはWebサービスの各メソッドに対するメソッドを持っています。プロキシクラスのメソッドは、プロジェクト内のその他のクラスのメソッドを呼び出すのと同じ感覚で呼び出すことができます。しかしその舞台裏では、プロキシクラスはメソッドの入力パラメータをXMLにシリアライズし、WebサービスへのHTTP要求を行い、HTML応答で返されたXMLをデシリアライズしています。Webサービスの詳しい解説はこの記事の範囲を超えるので、Webサービスの基礎について詳しく知りたい場合は記事「An Extensive Examination of Web Services」を参照ください。

 プロキシクラスによってWebサービスとの対話は大幅に簡略化されますが、Webサービスとの通信にプロキシクラスを使用しなければならない理由はありません。代わりに、.NET FrameworkのSystem.Net名前空間内のクラスを使用してWebサービスにHTTP要求を行い、System.Xml名前空間内のクラスを使用して応答を構文解析することもできます。これが、顧客から提案されたアプローチでした。つまり、HttpWebRequestクラスを使用してWebサービスを呼び出し、XSLTを使用してXML応答をHTMLに変換し、そしてブラウザに発行できます。この提案の背後にあるのは、自動生成されたプロキシクラスにはオーバーヘッドがあり、これはより直接的な手段によって解消可能であるという仮定です。

テスト1:WebサービスのXMLデータを取得する

 このプロジェクトでは、Webサービスを呼び出してビジネスパートナーからのデータを取得および表示します。具体的には特定のURLを要求することによって、またPOSTヘッダーを通じて日付範囲を指定することによって、このWebサービスを呼び出します。Webサービスは対象のデータを取得し、それをXMLにシリアライズされたADO.NET DataSetとして返します。

 顧客から質問を受ける前は、Visual Studioが自動生成したプロキシクラスを使用して、このWebサービスにアクセスしていました。プロキシクラスは、入力として2つの日付値を取り、DataSetを返す単一のメソッドを含んでいます。以下のコードは、どうやってWebサービスを呼び出してこのデータを取得するかを示しています。プロキシクラスが、Webサービスを呼び出すという実装の複雑さをすべて隠蔽していることに注目してください。私たちは単にプロキシクラスのメソッド(この例ではGetData)を呼び出すだけでよく、後はプロキシクラスが2つの日付値をシリアライズし、HTTP要求を行い、結果のXMLをADO.NET DataSetに変換するという低レベル作業のすべてを処理してくれます。

// Get data for 2009...
WebReferenceProxy proxy = new WebReferenceProxy();
DataSet performances = proxy.GetData("1/1/2009", "12/31/2009");
 GetDataメソッドの実行が終わると、Webサービス呼び出しが完了したことになり、Webサービスから取得されたデータを含むDataSetオブジェクトが返されます。この時点で、グリッドへの結果表示、結果のディスク保存、結果のソートなどを行うことができます。

 しかし、顧客の考えは、自動生成されたプロキシクラスを使用せず、代わりにHttpWebRequestクラスを使用して直接的にWebサービス呼び出しを行い、Webサービスによって返されたXMLペイロードをXmlDocumentオブジェクトに入れる方が効率的ではないか、というものでした。この仮説をテストするために、それだけを行うSoapCallという名前の小さく軽量なクラスを作成しました。以下は、SoapCallクラスの関連のあるコード行を示したものです。

//Prepare objects and create Web Service parameters
ASCIIEncoding encoding = new ASCIIEncoding();
StringBuilder parameters = new StringBuilder();
parameters.Append("sStartDate=1/1/2008&");
parameters.Append("sEndDate=1/1/2009&");

byte[] payload = encoding.GetBytes(parameters.ToString());
string Url = @"http://<WebServiceUrl>/GetPerformances";
//Call the Web Service
System.Net.HttpWebRequest wr = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(Url);
wr.Method = "POST";
wr.KeepAlive = false;
wr.ContentType = "application/x-www-form-urlencoded";
wr.ContentLength = payload.Length;

//Retrieve the response
System.Net.HttpWebResponse webResponse;
System.IO.Stream wrStream = wr.GetRequestStream();
wrStream.Write(payload, 0, payload.Length);
wrStream.Close();
webResponse = (System.Net.HttpWebResponse)wr.GetResponse();

//Put the response stream in an XML document
Stream baseStream = webResponse.GetResponseStream();
System.IO.StreamReader sr = new System.IO.StreamReader(baseStream);
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
xmlDoc.LoadXml(sr.ReadToEnd()); 
 言うまでもなく、Webサービスを直接呼び出すには、プロキシクラスを使用する場合よりずっと多くのコードが必要です。それがプロキシクラスを使用する利点の1つです。プロキシクラスは、入力パラメータのパッケージ化、HTTP要求の発行、応答の構文解析といった処理を行うために必要なすべての低レベルコードをカプセル化しているため、コーディング時間の大幅な節約に貢献します。

 上記の赤字でハイライトされた1つ目の行は、HttpWebRequestオブジェクトのGetResponseメソッドの呼び出しを示しています。このメソッドは、実際にHTTP要求を送信し、HTTP応答をStreamとして返します。ハイライトされた2つ目の行では、応答をXmlDocumentオブジェクトにロードしています。WebサービスのXML応答がXmlDocumentにロードされたら、それに対してデータの列挙、(XPathによる)フィルタリング、(XSLTによる)表示用HTMLへの変換など、さまざまな面白い処理を行えます。

テスト1:結果

 自動生成プロキシクラスとSoapCallクラスを使用するコードを実行しました。100回の繰り返しで、1回の要求ごとに210KBのXMLペイロードにアクセスします。勝ったのは.NETの自動生成プロキシクラスでした。テスト結果は、自動生成プロキシクラスを使用する方が、SoapCallメソッドよりも約50%速いことを示しています。

 パフォーマンスに差が出た1つの理由は、SoapCallクラス内でXmlDocumentオブジェクトを使用したことです。.NETのXPathDocumentクラスは、大きなXMLドキュメントの構文解析に対して、より効率的なアプローチを提供します。しかし、それを使用するには若干多くのコードが必要になります(特にXML名前空間を取り扱う場合)。要するに、これら2つのアプローチ間のパフォーマンスの差を縮めることは可能でしょうが、そうするとSoapCallクラス内のコードがかなり増えることになります。

テスト2:HTML生成

 このプロジェクトでは、Webサービスから取得されたデータはソートされ、若干の書式設定がされたうえでユーザーのブラウザに表示されます。自動生成プロキシクラスを使用する場合は、DataSetをソートしてからDataSet内の行を列挙処理し、Response.Write文を使用して、対象となるデータとHTMLマークアップを出力します。XmlDocumentアプローチの場合は、顧客の提案に従い、XSLTを使用してソートされたXMLデータをHTMLに変換することにしました。

 ご推察のとおり、Response.Write文を使用したデータ出力は、XSLTを使用してXMLをHTMLに変換するよりも高速です。下記のグラフは、各アプローチでの実行時間の違いを示したものです。データをソートする場合と、Webサービスに返された順番でデータを出力する場合の両方を示しています。両方のアプローチ間の時間の絶対差はごくわずか(1ミリ秒未満)です。従って、極端に負荷が高い環境でなければ、どちらのアプローチでも十分に有効です。ただ私たちは、DataSetをソートしてResponse.Writeでマークアップを出力する方法の方が好きです。なぜなら、DataSetを扱い、Response.Writeでクライアントにマークアップを出力する方がシンプルなため、XSLTを使用する場合よりもコードの読みやすさと保守性が向上する傾向があるからです。XSLTを使用する場合は、XSLTに精通し、また追加の構文を習得しなければなりません。

 これらのテスト結果から分かるのは、Visual Studioの[Web参照の追加]を使用して自動生成プロキシクラスを作成するのは、単に時間の節約になるだけでなく、カスタムクラスからWebサービスを直接呼び出してそのデータをXmlDocumentにロードするよりも実際に効率的であるということです。同様に、Response.Write文によってマークアップをブラウザに直接出力することは、XSLTを使用してXMLをHTMLに変換するより高速です。

 それでは、ハッピープログラミング!

参考資料

著者紹介

Jamie Davis(Jamie Davis)
John Jakovich(John Jakovich)
Sam Menard(Sam Menard)
【関連記事】
ASP.NET 4.0のGridViewの新しい並べ替えスタイル
ASP.NET 4.0におけるURLルーティング
マイクロソフト、アプリ開発環境「Visual Studio 2010」日本語版を4月20日から販売
MS、『Visual Studio 2010』と『.NET Framework 4』をリリース
アクティブコアの「レコメンドウエアハウス」が ASP.NET に正式対応

New Topics

Special Ad

ゆりかごからロケットまで、すべての乗り物をエンジョイ
ゆりかごからロケットまで、すべての乗り物をエンジョイ えん乗り」は、ゆりかごからロケットまで、すべての乗り物をエンジョイする、ニュース、コラム、動画などをお届けします! てんこ盛りをエンジョイするのは こちらから

Hot Topics

IT Job

Interviews / Specials

Popular

Access Ranking

Partner Sites