0

0

c# 高并发下的 TimeZoneInfo 缓存和性能问题

月夜之吻

月夜之吻

发布时间:2026-01-08 09:19:02

|

185人浏览过

|

来源于php中文网

原创

务必在应用启动时预热 TimeZoneInfo.FindSystemTimeZoneById,避免高并发下因首次解析时区数据库和锁竞争导致 5–20ms/次延迟;ID 大小写敏感,IANA 时区如 "Etc/GMT+8" 需用 CreateCustomTimeZone 构造并预缓存;慎用 TimeZoneInfo.Local,容器中需显式设 TZ 环境变量。

c# 高并发下的 timezoneinfo 缓存和性能问题

TimeZoneInfo.FindSystemTimeZoneById 在高并发下会变慢

TimeZoneInfo.FindSystemTimeZoneById 内部不是纯内存查找,它在首次调用时会触发系统时区数据库的解析(Windows 上读注册表或 ICU 数据,Linux/macOS 依赖 /usr/share/zoneinfo 文件结构),后续调用虽有缓存,但该缓存受内部 ConcurrentDictionary 保护,且存在锁竞争和键规范化开销。实测在 10K+ QPS 场景下,未预热时平均耗时可飙升至 5–20ms/次。

  • 务必在应用启动时主动调用一次 TimeZoneInfo.FindSystemTimeZoneById("UTC") 或常用 ID(如 "China Standard Time")完成初始化
  • 避免在请求处理路径中直接调用 FindSystemTimeZoneById —— 改为从预加载字典中取值:
    private static readonly ConcurrentDictionary<string, TimeZoneInfo> _tzCache = new();
    static MyService()
    {
        foreach (var id in new[] { "UTC", "China Standard Time", "Pacific Standard Time" })
        {
            _tzCache[id] = TimeZoneInfo.FindSystemTimeZoneById(id);
        }
    }
  • 注意:ID 是大小写敏感的,"utc" 会抛 TimeZoneNotFoundException

自定义时区(如 Etc/GMT+8)不能用 FindSystemTimeZoneById 直接获取

"Etc/GMT+8" 这类 IANA 时区名在 Windows 上默认不可用,FindSystemTimeZoneById 会直接抛异常;.NET 6+ 虽支持 IANA 数据(需启用 AppContext.SetSwitch("System.Globalization.UseNls", false)),但该开关是进程级的,且切换后会影响所有 DateTimeFormatInfo 行为,不建议 runtime 动态开启。

  • 若必须支持 IANA 时区,改用 TimeZoneInfo.CreateCustomTimeZone 构造固定偏移时区:
    var gmtPlus8 = TimeZoneInfo.CreateCustomTimeZone("GMT+8", TimeSpan.FromHours(8), "GMT+8", "GMT+8");
  • 不要在每次请求中重复创建 —— 同样应预缓存到 ConcurrentDictionarystatic readonly 字段
  • 注意:CreateCustomTimeZone 不支持夏令时,如需 DST,请改用第三方库(如 NodaTime

TimeZoneInfo.ConvertTime 的线程安全性与性能陷阱

TimeZoneInfo.ConvertTime 本身是线程安全的,但它的性能取决于两个因素:目标时区是否已“热”、转换逻辑是否涉及复杂规则(如历史 DST 变更)。对非本地时区做频繁转换(例如日志时间戳转用户本地时间),若未复用 TimeZoneInfo 实例,会反复触发内部时区规则解析。

Sora
Sora

Sora是OpenAI发布的一种文生视频AI大模型,可以根据文本指令创建现实和富有想象力的场景。

下载
  • 禁止这样写:
    var tz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
    var local = TimeZoneInfo.ConvertTime(utcTime, tz, TimeZoneInfo.Local); // 每次都 new tz?不,但 FindSystemTimeZoneById 被反复调用就糟了
  • 正确做法是:把 TimeZoneInfo 实例作为字段或参数传入,确保复用
  • 如果转换目标固定(如全站统一转成 "Asia/Shanghai"),直接缓存该实例,别每次都查
  • 极端吞吐场景下,考虑用 DateTimeOffset 替代 —— 若只需偏移量而无需时区名称或 DST 规则,DateTimeOffset 零分配、无查找开销

跨平台部署时 TimeZoneInfo.Local 的行为差异

TimeZoneInfo.Local 在 Linux/macOS 上依赖 TZ 环境变量/etc/localtime 符号链接,在容器中极易为空或指向错误时区(比如 Alpine 镜像默认没设 TZ)。此时 Local 可能回退为 UTC,且首次访问会触发同步锁,造成毛刺。

  • Dockerfile 中显式设置时区:
    ENV TZ=Asia/Shanghai
    RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
  • 代码中不要假设 TimeZoneInfo.Local 总是可用 —— 加一层 fallback:
    private static readonly TimeZoneInfo _appDefaultTz = 
        TimeZoneInfo.FindSystemTimeZoneById("China Standard Time");
    public static TimeZoneInfo GetEffectiveTimeZone(TimeZoneInfo? userTz = null) =>
        userTz ?? TimeZoneInfo.Local ?? _appDefaultTz;
  • 注意:TimeZoneInfo.Local 是只读属性,但其内部缓存可能被 ClearCachedData() 清空(极少用,慎调)
缓存策略本身不难,真正容易出问题的是“以为它已经缓存了”——比如漏掉预热、混用大小写 ID、或在容器里忘了配 TZ。这些点一旦在线上高频路径触发,表现就是 CPU 突增 + 请求延迟抖动,排查时容易误判为 GC 或锁竞争。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

765

2023.08.10

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

1496

2023.07.26

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1170

2023.07.27

windows照片无法显示
windows照片无法显示

当我们尝试打开一张图片时,可能会出现一个错误提示,提示说"Windows照片查看器无法显示此图片,因为计算机上的可用内存不足",本专题为大家提供windows照片无法显示相关的文章,帮助大家解决该问题。

835

2023.08.01

windows查看端口被占用的情况
windows查看端口被占用的情况

windows查看端口被占用的情况的方法:1、使用Windows自带的资源监视器;2、使用命令提示符查看端口信息;3、使用任务管理器查看占用端口的进程。本专题为大家提供windows查看端口被占用的情况的相关的文章、下载、课程内容,供大家免费下载体验。

463

2023.08.02

windows无法访问共享电脑
windows无法访问共享电脑

在现代社会中,共享电脑是办公室和家庭的重要组成部分。然而,有时我们可能会遇到Windows无法访问共享电脑的问题。这个问题可能会导致数据无法共享,影响工作和生活的正常进行。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2362

2023.08.08

windows自动更新
windows自动更新

Windows操作系统的自动更新功能可以确保系统及时获取最新的补丁和安全更新,以提高系统的稳定性和安全性。然而,有时候我们可能希望暂时或永久地关闭Windows的自动更新功能。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

874

2023.08.10

windows boot manager
windows boot manager

windows boot manager无法开机的解决方法:1、系统文件损坏,使用Windows安装光盘或USB启动盘进入恢复环境,选择修复计算机,然后选择自动修复;2、引导顺序错误,进入恢复环境,选择命令提示符,输入命令"bootrec /fixboot"和"bootrec /fixmbr",然后重新启动计算机;3、硬件问题,使用硬盘检测工具进行扫描和修复;4、重装操作系统。本专题还提供其他解决

1976

2023.08.28

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 10.5万人学习

Git 教程
Git 教程

共21课时 | 4.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号