Windows AzureのTableストレージに関するホワイトペーパー「Windows Azure Table – テーブルストレージのプログラミング」(http://www.microsoft.com/japan/windowsazure/whitepapers/)では、ストレージのパフォーマンス向上のために、Expect100ContinueおよびUseNagleAlgorithmをfalseにすることが推奨されている(p67-68あたり)。
ただ実際のところ、この設定がどの程度パフォーマンスに影響を及ぼすか不明だったため、試してみた。
計測プログラムのソースコード(一部)
以下のプログラムを用いて、今回のパフォーマンス計測を行った。計測する処理は、1件のエンティティを作成するパターン(simple)と10件のエンティティをEntity Group Transactionを用いて作成するパターンの二通りを計測する。
またコード中のWorkUnit.Inspect内部では、引数で与えられたラムダ式部分のパフォーマンス計測を行っている。
public override void Run() { var account = CloudStorageAccount.Parse( RoleEnvironment.GetConfigurationSettingValue("Cirrus.DemoApp.ConnectionString")); var client = account.CreateCloudTableClient(); client.CreateTableIfNotExist("Person"); while ( true ) { FabricContext.NewContext(); //毎ループごとにコンテキストを新しくする { var ctx = GetTargetContext(client, 1); WorkUnit.Inspect("simple", () => { ctx.SaveChangesWithRetries(); }); } { var ctx = GetTargetContext(client, 10); WorkUnit.Inspect("batch", () => { ctx.SaveChangesWithRetries(System.Data.Services.Client.SaveChangesOptions.Batch); }); } } } public TableServiceContext GetTargetContext(CloudTableClient client, int count) { var ctx = client.GetDataServiceContext(); for ( int i = 0; i < count; i++ ) { ctx.AddObject("Person", new Person() { PartitionKey = "Partition", RowKey = Guid.NewGuid().ToString("N"), Name = "はまちちゃん", Profile = "ぼくはまちちゃん!こんにちはこんにちは!!", Age = 15, Birthday = DateTime.UtcNow }); } return ctx; } public override bool OnStart() { ServicePointManager.UseNagleAlgorithm = true; ServicePointManager.Expect100Continue = true; ServicePointManager.DefaultConnectionLimit = 12; var wadConnectionString = "Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString"; var account = CloudStorageAccount.Parse( RoleEnvironment.GetConfigurationSettingValue(wadConnectionString)); var roleInstanceDiagnosticManager = account.CreateRoleInstanceDiagnosticManager( RoleEnvironment.DeploymentId, RoleEnvironment.CurrentRoleInstance.Role.Name, RoleEnvironment.CurrentRoleInstance.Id); var config = roleInstanceDiagnosticManager.GetCurrentConfiguration(); if ( null == config ) { config = DiagnosticMonitor.GetDefaultInitialConfiguration(); } config.Logs.ScheduledTransferPeriod = TimeSpan.FromSeconds(10); config.Logs.ScheduledTransferLogLevelFilter = LogLevel.Undefined; roleInstanceDiagnosticManager.SetCurrentConfiguration(config); return base.OnStart(); }
1件のエンティティ追加に関するパフォーマンス測定結果
ベースライン
まずはベースラインとして、Expect100ContinueおよびUseNagleAlgorithmを両方共trueにした場合のパフォーマンスを測ってみると、以下の結果が得られた。
平均値や90%ラインなどは10分単位で集計した値(単位は全てms)。
Time | Avg | 80% | 90% | 95% | Min | Max |
20110404-0400 | 208.475 | 228 | 255 | 302 | 113 | 754 |
20110404-0410 | 213.608 | 232 | 271 | 310 | 118 | 747 |
20110404-0420 | 207.101 | 226 | 247 | 287 | 114 | 742 |
見てわかる通り、1件のエンティティ作成にかかる時間が平均200msもかかっており、非常に遅い。
Expect100Continue=falseの測定結果
引き続き、Expect100Continueをfalseにした場合の測定を行う。
測定に使用したソースコードは上記ソースコードにおいて、ServicePointManager.Expect100Continue=trueの部分をfalseに書き換えたものである。
Time | Avg | 80% | 90% | 95% | Min | Max |
20110404-0400 | 218.12 | 237 | 270 | 307 | 121 | 1572 |
20110404-0410 | 217.817 | 234 | 266 | 298 | 122 | 841 |
20110404-0420 | 215.147 | 234 | 263 | 301 | 120 | 1417 |
この結果をベースラインと比較すると、パフォーマンスが劣化しているもしくはほとんど変わらない程度の結果となり、少なくともパフォーマンスの向上は確認できなかった。
UseNagleAlgorithm=falseの測定結果
引き続き今度は、UseNagleAlgorithmをfalseにした場合のパフォーマンス測定を行う。
測定に使用したソースコードは上記で示したソース中のServicePointManager.UseNagleAlgorithm=trueの部分をfalseに書き換えたのみである。
Time | Avg | 80% | 90% | 95% | Min | Max |
20110404-0400 | 38.974 | 38 | 54 | 93 | 18 | 682 |
20110404-0410 | 38.227 | 38 | 52 | 80 | 17 | 685 |
20110404-0420 | 37.488 | 39 | 51 | 78 | 17 | 682 |
ベースラインおよびExpected100Continue=falseの場合の測定結果と比較すると、かなりのパフォーマンス向上が確認できた(ベースラインと比較して、1件あたり1/5程度の時間)。このパフォーマンス向上の原因は、元のベースラインの場合ではNagleアルゴリズムによるWAITがあったが、UseNagleAlgorithm=falseとしたことでNagleアルゴリズムが適用されなくなったためと考えられる。
まとめ
以上の結果をまとめると、
- 小さなリクエストではNagleアルゴリズムによるパフォーマンス劣化が発生する
- UseNagleAlgorithmをfalseに設定することによって、上記のパフォーマンス劣化を回避できる
- Expected100Continueによるパフォーマンス向上は確認できず
といった結論が得られた。
エンティティグループトランザクションを利用した場合の結果については別記事にて。
0 件のコメント:
コメントを投稿