LoginSignup
1
0

More than 1 year has passed since last update.

【C#/ASP.NET】Web APIのベンチマークを計測する

Last updated at Posted at 2021-06-06

概要

クライアントが「Web APIをコールし、サーバから応答を得るまでの時間」を計測した。
具体的には、HttpClientとBenchmarkDotNetを使って、処理時間の集計(平均値・最小値・最大値を算出)し、集計結果をHTMLでエクスポートとした。
計測の手順と実装を掲載する。

動作環境

クライアント

.NET Framework4.6.1
Nugetパッケージ
 ・BenchmarkDotNet 0.13.0
 ・NewtonsoftJson 13.0.1

サーバー

ASP.NET Web API
.NET Framework4.6.1

計測予定のWebAPIの一覧

今回はGET/PUT/POST/DELETEを準備する。
下記表のWeb APIをサーバ側に実装する(自動生成コードをそのまま利用する)。

HTTPメソッド URL
GET http://localhost:19691/api/values
POST http://localhost:19691/api/values
PUT http://localhost:19691/api/values/{id}
DELETE http://localhost:19691/api/values/{id}

アプリケーションを作成する。

クライアントを作成する

コンソールアプリケーションでソリューションを作成して、下記手順を実行する。

1. BenchmarkDotNetを適用する。

「BenchmarkDotNet」をNugetパッケージでインストールする。

2. 計測対象のメソッドを作成する。

「BenchmarkDotNet」で計測する対象メソッド、その他オプションは「属性」で設定する。
各属性の意味はコメントで補足説明する。

WebApiClient
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using Newtonsoft.Json;

namespace BenchMark
{
    [HtmlExporter]//Htmlエクスポート
    public class WebApiClient
    {
        private static readonly HttpClient Client = new HttpClient();
        private static string _jsonString;
        private static StringContent _data;

        [GlobalSetup]//初回セットアップ
        public void GlobalSetUp()
        {
            _jsonString = JsonConvert.SerializeObject("TestMessage");
            _data = new StringContent(_jsonString, Encoding.UTF8, mediaType: "application/json");
        }

        [Benchmark]//計測対象のメソッドに指定
        public async Task GetAsync()
        {
            var response = await Client.GetAsync("http://localhost:19691/api/values");
            response.EnsureSuccessStatusCode();
        }

        [Benchmark]
        public async Task PutAsync()
        {
            var response = await Client.PutAsync("http://localhost:19691/api/values/5", _data);
            response.EnsureSuccessStatusCode();
        }

        [Benchmark]
        public async Task PostAsync()
        {
            var response = await Client.PostAsync("http://localhost:19691/api/values", _data);
            response.EnsureSuccessStatusCode();
        }

        [Benchmark]
        public async Task DeleteAsync()
        {
            var response = await Client.DeleteAsync("http://localhost:19691/api/values/5");
            response.EnsureSuccessStatusCode();
        }
    }
}

3. メイン関数から計測対象をコールする。

Program.cs
using System.Threading.Tasks;
using BenchmarkDotNet.Running;
namespace BenchMark
{
    class Program
    {
        static void Main(string[] args)
        {
            //CheckOperation().GetAwaiter().GetResult();

            //計測を開始する
            BenchmarkRunner.Run<WebApiClient>();
        }

        /// <summary>
        /// ベンチマーク測定前の動作確認用
        /// </summary>
        static async Task CheckOperation()
        {
            var client = new WebApiClient();
            client.GlobalSetUp();
            await client.GetAsync();
            await client.PutAsync();
            await client.PostAsync();
            await client.DeleteAsync();
        }
    }
}

サーバを作成する。

自動生成コード使って、Web APIを準備する。

1. Web アプリケーションでソリューションを作成

image.png

Web APIを選ぶ。
image.png

2. Web APIが自動生成されたことを確認する。

「ソリューションエクスプローラー」
→「Controllers」
  ValuesControllers.csを開く。

ValuesControllers.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;

namespace HttpServerBenchMark.Controllers
{
    public class ValuesController : ApiController
    {
        // GET api/values
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/values/5
        public string Get( int id )
        {
            return "value";
        }

        // POST api/values
        public void Post( [FromBody]string value )
        {
        }

        // PUT api/values/5
        public void Put( int id, [FromBody]string value )
        {
        }

        // DELETE api/values/5
        public void Delete( int id )
        {
        }
    }
}

パフォーマンス計測

1. サーバーを実行する。

2. クライアントを実行する。

※Releaseビルドで実行すること。
計測が完了することを待つ。

計測開始時のターミナル出力

// Validating benchmarks:
// ***** BenchmarkRunner: Start   *****
// ***** Found 4 benchmark(s) in total *****
// ***** Building 1 exe(s) in Parallel: Start   *****
:
:

計測終了時のターミナル出力

// ***** BenchmarkRunner: End *****
// ** Remained 0 benchmark(s) to run **
Run time: 00:01:59 (119.94 sec), executed benchmarks: 4

Global total time: 00:02:02 (122.68 sec), executed benchmarks: 4

3. 集計結果を確認する。

ターミナル出力で「Summary」を探して確認する。

結果サマリーを確認する

// * Summary *

BenchmarkDotNet=v0.13.0, OS=Windows 10.0.19043.985 (21H1/May2021Update)
Intel Core i7-7700HQ CPU 2.80GHz (Kaby Lake), 1 CPU, 8 logical and 4 physical cores
  [Host]     : .NET Framework 4.8 (4.8.4341.0), X86 LegacyJIT
  DefaultJob : .NET Framework 4.8 (4.8.4341.0), X86 LegacyJIT

|      Method |     Mean |     Error |    StdDev |   Median |
|------------ |---------:|----------:|----------:|---------:|
|    GetAsync | 1.921 ms | 0.1567 ms | 0.4469 ms | 1.749 ms |
|    PutAsync | 1.495 ms | 0.0319 ms | 0.0926 ms | 1.494 ms |
|   PostAsync | 1.472 ms | 0.0291 ms | 0.0638 ms | 1.474 ms |
| DeleteAsync | 1.281 ms | 0.0256 ms | 0.0455 ms | 1.293 ms |

ファイルのExportを確認する。

今回はHTMLファイル出力しているため、ターミナルでExport先を確認する。

// ***** BenchmarkRunner: Finish  *****

// * Export *
  BenchmarkDotNet.Artifacts\results\BenchMark.WebApiClient-report.csv
  BenchmarkDotNet.Artifacts\results\BenchMark.WebApiClient-report-github.md
  BenchmarkDotNet.Artifacts\results\BenchMark.WebApiClient-report.html

ファイルエクスプローラで下記パスに移動する。
ソリューションのパス\bin\Release\BenchmarkDotNet.Artifacts
下記画像のファイルが存在する。
「BenchMark.WebApiClient-20210606-231210.log(※)」に、ターミナル出力と同様の内容が記録されている。
※ソリューション名-クラス名-実行日時.logって命名の様子。

image.png

ソリューションのパス\bin\Release\BenchmarkDotNet.Artifacts\resultsに移動する。
BenchmarkDotNet.Artifacts\results\BenchMark.WebApiClient-report.htmlを開く。
下図のようにサマリーと同様の内容が表示される。

image.png

logファイルとResultフォルダを控えておけば、報告資料や調査結果にそのまま利用できそう。

参考

No リンク 説明
1 【.NET/C#】メソッドのパフォーマンスを簡単に集計するライブラリの紹介 過去に書いたQuiitaの記事。内容はBenchmarkDotNetの紹介と使い方に関して記載した。
2 BenchmarkDotNetの公式ドキュメント 公式ドキュメントのリンク。
3 Github:本記事のソース 本記事のソースをGithubに公開してます。
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0