ラベル 時間計測 の投稿を表示しています。 すべての投稿を表示
ラベル 時間計測 の投稿を表示しています。 すべての投稿を表示

2017年8月11日金曜日

HTTPS コネクション時の libcurl による連続GETリクエストの高速化の検討

HTTPS コネクション時の libcurl による連続GETリクエストを高速化するための検証用の例題です。

libcurl による GET 取得時の高速化手段として以下のサイトでまとめられています。
https://moz.com/devblog/high-performance-libcurl-tips
(c-ares/PowerDNS 等により DNSのリスポンスを良くするとか libcurl-multi による並列処理化等、上記サイトには書かれていませんが TCP FAST OPEN に対応しているサーバーであれば libcurl からオプションを指定して利用できます)

一方、HTTPS でのリクエストでは証明書の検証等で、単純なデータやり取り以外の部分で内部的に処理が食われてしまうことがあります。
下記の例題では HTTPS にてデータ取得を行うサイトが信頼のあるサイトであることを前提とし、証明書の検証を行っていません。

例題では以下の3つの手法にてサイトからのデータ取得をループし、取得時間を計測しています。
CURL_RequestText1:毎回CURLハンドラを初期化し、データ取得を行う例
CURL_RequestText2:毎回CURLハンドラを初期化し、内部的に確保されているコネクションの再利用等は行わずデータ取得を行う例(CURLOPT_FORBID_REUSE/CURLOPT_FRESH_CONNECT)
CURL_RequestText3:CURLハンドラを予め準備しておき、繰り返し利用する間は再利用する例
結果では、1/2 はサイトにより多少の変化はあるもののあまり差はなく(2の方が若干早い印象)、3 は 1 の半分程度の時間でデータ取得が行われています(この例題では記載していませんが、POST 時の応答も高速化されていました)。
TCP FAST OPEN(CURLOPT_TCP_FASTOPEN)の影響があるかどうかどうかを見てみましたが、特に影響はありませんでした。

HTTPS 接続が正常に機能しているサイトではほぼ 3 の設定で高速化される印象ですが、ブラウザ接続した際に「信頼できる運営者情報はありません」等のアラートが出るサイトでは全く変化はありませんでした(証明書の検証を行っていないにも関わらず)。
新しいサーバーでテストする際等には証明書を正しく入れてもらうようにお願いするしかない状況です(libcurl の設定では対処できない)。

今回テストしたのはサーバーからの応答を取得後に別の応答を取得する必要がある場合の処理です。
URLが異なる複数の結果を予め取得しておく場合には libcurl-multi や CURL ハンドラを複数準備して別スレッドで並行して結果を取得すれば容易に高速化することは可能かと思います(スレッドで用いる場合は CURLOPT_NOSIGNAL を指定)。 実行結果

2011年5月7日土曜日

経過時刻の計算/出力(クラス化)

経過時刻の計算/出力例です。

開始時間・終了時間を設定し、計画時刻を出力します。

時刻は "20041125172211" のように、
2004:年,11:月,25:日,17:時,22:分,11:秒
を記した文字列で出力されます。

開始時間または終了時間が設定されていない場合、開始時間と終了時間の設定が逆の場合、"Illegal WorkTime" と表示されます。


実行結果

2011年4月9日土曜日

経過時刻の計算/出力

経過時刻の計算/出力例です。

計算が数日にも及んでしまう際、何日経過したかを書式付で出力します。
計算例では、"20041125172211"のように、
2004:年,11:月,25:日,17:時,22:分,11:秒
を記したテキストから経過時刻を計算しています。

strftime 関数により、struct tm 形式の時刻を"20041125172211"のような形に自由に整形することができます。


実行結果

2011年4月8日金曜日

実行時間計測の方法

実行時間を計測する方法は各種存在していますが、例題では 4 種類の方法により計測しています。

clock/getrusage では、呼び出したプロセスの CPU 時間やリソース使用量が利用されるため、sleep/usleep 関数により CPU の利用を停止すると、その間の経過時間は計測されないので注意が必要です。

比較的長い時間の処理で、かつ I/O 等も含めたプログラム全体の処理を測定するには、時刻から経過時間を計測する gettimeofday を用いる方法が無難な方法になります。

times はシステムが起動した時間からのクロック数を返すため、gettimeofday と同様プログラムが CPU を利用しない間も、システム側が利用しているクロックを取得し、経過時間を取得することができます。


プログラム中の一部の処理において CPU 時間を測る場合、短い時間測定には getrusage を利用し、長い場合には、clock を使うのが良いかと思われます。

実際には、I/O 等も含めたプログラム全体の測定することが多いため、gettimeofday を利用することをお勧めします。

clock() : プログラムの使用したプロセス時間の近似値を返す(clock_t 単位の CPU 時間)。
times() : 過去のある時点から経過したクロック数を返す (clock_t 単位の CPU 時間)。
gettimeofday() : 時刻を取得する。
getrusage() : 資源の使用量を取得する。


例題では、Intel プロセッサにおける RDTSC (read-time stamp counter) を利用してクロック数を計測するための関数も用意しています。
これは、インラインアセンブラを利用し、CPU 内のカウンタを直接取得するような方法になります。


実行結果

2011年4月6日水曜日

重複なしの乱数発生

重複なしの乱数を発生するための例題です。

重複なしの乱数発生について、本来ならば一度発生した乱数を配列に登録していき、すでに登録されている乱数が発生されればその乱数は破棄する等の手順をとりますが、そうすると、必要な乱数の数よりも多い計算回数を必要とします。

そこで、乱数発生の数を必要な数と同じにし、判定の手順も必要としないアルゴリズムを考えてみました。

下記の例題にて、
int round_tbl[RAND_N]; // 変換テーブル
は、発生した乱数を使われていない値に変換するためのテーブルであり、必要な乱数の数(RAND_N)を次第に減らしていくために利用しています。
全ての値が発生すれば、必要な乱数の数は 0 になります。

このアルゴリズムでは、変換テーブル用の配列の準備が必要となります(その分のメモリが必要)。
乱数を発生する数は、必要な乱数の数と同じであり、不必要な乱数を破棄することはありませんので、高速なアルゴリズムになります。

例題では、通常のアルゴリズムと比較した時間も表示しています。
10000 の数を発生する際には16倍程度高速になっています。

図解begin
 _______________
|0|1|2|3|・・|n−1| → n個の配列
  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
最大 n の乱数を発生 val=2 → 配列から 2番目の値を抜き出し、抜けた分を詰める
 ______________
|0|1|3|4|・|n−1| → n-1個の配列
  ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
最大 n-1 の乱数を発生し、上記と同じように発した値の配列を抜き出し、抜けた分を詰める

以下、配列がなくなるまで繰り返す
図解end

クラス化し、必要な値だけ取り出すように変更した例は こちら

実行結果