7

localtime複数のスレッドから非常に頻繁に呼び出したいコードがあります。(関連する背景: これは、要求できるものの 1 つが文字列としての現地時間であり、1 秒あたり 100K の要求を処理できるようにしたいサーバーです。)

localtime_rUbuntu Linux 12.04 では、glibc 関数(「リエントラント ローカルタイム」) が を呼び出し__tz_convertており、これが引き続きグローバル ロックを使用することを発見しました。

(また、 FreeBSDlocaltime_r呼び出しtzsetごとに呼び出しを行うように見えます。これは、プログラムが実行した可能性があること、および/またはユーザーが今から最後に呼び出されたときまでsetenv("TZ")の間に の新しいバージョンをダウンロードしたことに偏執的であるためです。(これは逆です)ここで説明されている状況の; glibc はのすべての呼び出しを呼び出しているようです、混乱を招くだけです。)/etc/localtimelocaltime_rtzset localtimelocaltime_r

明らかに、これはパフォーマンスにとってひどいものです。私たちの目的のために、基本的に、サーバーが実行を開始したときに現在のタイムゾーンのルールを「スナップショット」し、その後そのスナップショットを永久に使用したいと考えています。したがって、夏時間のルールは引き続き尊重しますが (DST にいつ切り替えるかのルールはスナップショットの一部になるため)、ディスクに戻ったり、ミューテックスを取得したり、スレッドを引き起こすようなことをしたりすることは決してありません。封鎖する。(ダウンロードされた tzinfo の更新を尊重しなくても、 への変更を尊重しなくても/etc/localtime問題ありません。サーバーが実行中にタイムゾーンを物理的に変更するとは考えていません。)

しかし、タイムゾーンのルールを処理する方法に関する情報をオンラインで見つけることができません。それらを操作するためのユーザー空間 API があるかどうか、またはタイムゾーン データを自分で読み取るために数百行の glibc コードを再実装する必要があるかどうかです。 .

ユーザーに公開されていないように見えるため、__tz_convertを含む下流のすべてを再実装する必要がありますか? tzfile_readまたは、タイムゾーンのルールを操作するために使用できる POSIX インターフェイスやサードパーティ ライブラリはありますか?

( http://www.iana.org/time-zones/repository/tz-link.htmlを見たことがありますが、役に立つかどうかはわかりません。)

4

2 に答える 2

1

おそらく、この無料のオープンソースのタイムゾーン ライブラリが必要になるでしょう。

これには、ここLAZY_INITで完全に文書化されているという構成フラグがあります。デフォルトではオンになっており、個々のタイムゾーンに初めてアクセスするときに呼び出しが発生します。ただし、次のようにコンパイルできます。std::call_once

-DLAZY_INIT=0

そしてstd::call_once立ち去るようにとの呼びかけ。すべての単一のタイムゾーンがディスクから読み取られ、最初のアクセス時に完全に初期化されます (関数 local static を介して)。それ以降、物事は安定しており、ロックフリーで、ディスクへのアクセスはありません。当然、これにより事前の初期化時間が増加しますが、各タイムゾーンの「最初のアクセス」時間は減少します。

このライブラリは C++11/14 を必要とするため、その理由で適切でない場合があります。<chrono>これは、C++11ライブラリに基づいています (そして頻繁に使用しています) 。以下は、現在の現地時間を出力するサンプル コードです。

#include "tz.h"
#include <iostream>

int
main()
{
    using namespace date;
    auto local = make_zoned(current_zone(), std::chrono::system_clock::now());
    std::cout << local << '\n';
}

私のために出力するだけです:

2016-04-12 10:13:14.585945 EDT

このライブラリは、最新の高性能スレッド セーフ設計です。また、非常に柔軟で、完全に文書化されています。その機能は、C の単純な置き換えをはるかに超えていlocaltimeます。C API とは異なり、必要なIANA タイムゾーンを指定できます。次に例を示します。

    auto local = make_zoned("Europe/London", std::chrono::system_clock::now());

これにより、ロンドンの現在時刻が得られます。

2016-04-12 15:19:59.035533 BST

デフォルトでは、タイムスタンプの精度は の精度であることに注意してくださいstd::chrono::system_clock。別の精度が必要な場合は、簡単に実現できます。

using namespace date;
using namespace std::chrono;
auto local = make_zoned("Europe/London", std::chrono::system_clock::now());
std::cout << format("%F %H:%M %Z", local) << '\n';

2016-04-12 15:22 BST

詳細については、ドキュメントを参照してください。

于 2016-04-12T14:24:33.637 に答える