mirror of
https://github.com/HowardHinnant/date.git
synced 2024-12-27 00:14:07 +08:00
Optimize initialization of tz database
* Defer expensive parts of the initialization * The deferment can be turned off with -DLAZY_INIT=0
This commit is contained in:
parent
e8f95dddb7
commit
e79634f61d
43
tz.cpp
43
tz.cpp
@ -1249,6 +1249,9 @@ Zone::zonelet::zonelet(const zonelet& i)
|
||||
}
|
||||
|
||||
Zone::Zone(const std::string& s)
|
||||
#if LAZY_INIT
|
||||
: adjusted_(new std::once_flag{})
|
||||
#endif
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -1566,24 +1569,22 @@ Zone::adjust_infos(const std::vector<Rule>& rules)
|
||||
const zonelet* prev_zonelet = nullptr;
|
||||
for (auto& z : zonelets_)
|
||||
{
|
||||
std::pair<const Rule*, const Rule*> eqr{};
|
||||
std::istringstream in;
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
// Classify info as rule-based, has save, or neither
|
||||
if (!z.u.rule_.empty())
|
||||
{
|
||||
// Find out if this zonelet has a rule or a save
|
||||
auto i = std::lower_bound(rules.begin(), rules.end(), z.u.rule_,
|
||||
[](const Rule& r, const std::string& nm)
|
||||
{
|
||||
return r.name() < nm;
|
||||
});
|
||||
if (i == rules.end() || i->name() != z.u.rule_)
|
||||
eqr = std::equal_range(rules.data(), rules.data() + rules.size(), z.u.rule_);
|
||||
if (eqr.first == eqr.second)
|
||||
{
|
||||
// The rule doesn't exist. Assume this is a save
|
||||
try
|
||||
{
|
||||
using namespace std::chrono;
|
||||
using string = std::string;
|
||||
std::istringstream in(z.u.rule_);
|
||||
in.exceptions(std::ios::failbit | std::ios::badbit);
|
||||
in.str(z.u.rule_);
|
||||
auto tmp = duration_cast<minutes>(parse_signed_time(in));
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
z.u.rule_.~string();
|
||||
@ -1608,13 +1609,6 @@ Zone::adjust_infos(const std::vector<Rule>& rules)
|
||||
z.tag_ = zonelet::is_empty;
|
||||
}
|
||||
|
||||
std::pair<const Rule*, const Rule*> eqr{};
|
||||
if (z.tag_ == zonelet::has_rule)
|
||||
{
|
||||
eqr = std::equal_range(rules.data(), rules.data() + rules.size(), z.u.rule_);
|
||||
assert(eqr.first != eqr.second);
|
||||
}
|
||||
|
||||
minutes final_save{0};
|
||||
if (z.tag_ == zonelet::has_save)
|
||||
{
|
||||
@ -1750,6 +1744,12 @@ Zone::get_info(std::chrono::system_clock::time_point tp, tz timezone) const
|
||||
" is out of range:[" + std::to_string(static_cast<int>(min_year)) + ", "
|
||||
+ std::to_string(static_cast<int>(max_year)) + "]");
|
||||
auto tps = floor<seconds>(tp);
|
||||
#if LAZY_INIT
|
||||
std::call_once(*adjusted_, [this]()
|
||||
{
|
||||
const_cast<Zone*>(this)->adjust_infos(get_tzdb().rules);
|
||||
});
|
||||
#endif
|
||||
auto i = std::upper_bound(zonelets_.begin(), zonelets_.end(), tps,
|
||||
[timezone](second_point t, const zonelet& zl)
|
||||
{
|
||||
@ -1803,6 +1803,12 @@ operator<<(std::ostream& os, const Zone& z)
|
||||
detail::save_stream _(os);
|
||||
os.fill(' ');
|
||||
os.flags(std::ios::dec | std::ios::left);
|
||||
#if LAZY_INIT
|
||||
std::call_once(*z.adjusted_, [&z]()
|
||||
{
|
||||
const_cast<Zone&>(z).adjust_infos(get_tzdb().rules);
|
||||
});
|
||||
#endif
|
||||
os.width(35);
|
||||
os << z.name_;
|
||||
std::string indent;
|
||||
@ -1909,9 +1915,8 @@ init_tzdb()
|
||||
std::ifstream infile(path + "Makefile");
|
||||
while (infile)
|
||||
{
|
||||
std::string version;
|
||||
infile >> version;
|
||||
if (version == "VERSION=")
|
||||
infile >> line;
|
||||
if (line == "VERSION=")
|
||||
{
|
||||
infile >> db.version;
|
||||
break;
|
||||
@ -1966,8 +1971,10 @@ init_tzdb()
|
||||
std::sort(db.rules.begin(), db.rules.end());
|
||||
Rule::split_overlaps(db.rules);
|
||||
std::sort(db.zones.begin(), db.zones.end());
|
||||
#if !LAZY_INIT
|
||||
for (auto& z : db.zones)
|
||||
z.adjust_infos(db.rules);
|
||||
#endif
|
||||
db.zones.shrink_to_fit();
|
||||
std::sort(db.links.begin(), db.links.end());
|
||||
db.links.shrink_to_fit();
|
||||
|
18
tz.h
18
tz.h
@ -50,6 +50,10 @@ Technically any OS may use the mapping process but currently only Windows does u
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LAZY_INIT
|
||||
# define LAZY_INIT 1
|
||||
#endif
|
||||
|
||||
#include "date.h"
|
||||
|
||||
#include <algorithm>
|
||||
@ -200,6 +204,9 @@ private:
|
||||
|
||||
std::string name_;
|
||||
std::vector<zonelet> zonelets_;
|
||||
#if LAZY_INIT
|
||||
std::unique_ptr<std::once_flag> adjusted_;
|
||||
#endif
|
||||
|
||||
public:
|
||||
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
@ -207,15 +214,20 @@ public:
|
||||
Zone& operator=(Zone&&) = default;
|
||||
#else // defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
Zone(Zone&& src)
|
||||
:
|
||||
name_(std::move(src.name_)),
|
||||
zonelets_(std::move(src.zonelets_))
|
||||
: name_(std::move(src.name_))
|
||||
, zonelets_(std::move(src.zonelets_))
|
||||
#if LAZY_INIT
|
||||
, adjusted_(std::move(src.adjusted_))
|
||||
#endif
|
||||
{}
|
||||
|
||||
Zone& operator=(Zone&& src)
|
||||
{
|
||||
name_ = std::move(src.name_);
|
||||
zonelets_ = std::move(src.zonelets_);
|
||||
#if LAZY_INIT
|
||||
adjusted_ = std::move(src.adjusted_);
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
#endif // !defined(_MSC_VER) || (_MSC_VER >= 1900)
|
||||
|
Loading…
x
Reference in New Issue
Block a user