为什么 tzset() 在 Mac OS X 上 fork 后速度变慢了?

2024-03-08

Calling tzset()fork之后显得很慢。如果我第一次打电话,我只会看到缓慢的情况tzset()在 fork 之前在父进程中。我的TZ环境变量未设置。我dtruss我的测试程序显示子进程读取/etc/localtime对于每一个tzset()调用,而父进程只读取一次。此文件访问似乎是缓慢的根源,但我无法确定为什么它每次在子进程中都访问它。

这是我的测试程序 foo.c:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>

void check(char *msg);

int main(int argc, char **argv) {
  check("before");

  pid_t c = fork();
  if (c == 0) {
    check("fork");
    exit(0);
  }

  wait(NULL);

  check("after");
}

void check(char *msg) {
  struct timeval tv;

  gettimeofday(&tv, NULL);
  time_t start = tv.tv_sec;
  suseconds_t mstart = tv.tv_usec;

  for (int i = 0; i < 10000; i++) {
    tzset();
  }

  gettimeofday(&tv, NULL);
  double delta = (double)(tv.tv_sec - start);
  delta += (double)(tv.tv_usec - mstart)/1000000.0;

  printf("%s took: %fs\n", msg, delta);
}

我像这样编译并执行 foo.c:

[muir@muir-work-mb scratch]$ clang -o foo foo.c
[muir@muir-work-mb scratch]$ env -i ./foo
before took: 0.002135s
fork took: 1.122254s
after took: 0.001120s

我正在运行 Mac OS X 10.10.1(也在 10.9.5 上重现)。

我最初注意到 ruby​​ 的缓慢(子进程中的 Time#localtime 缓慢)。


肯·托马斯的回答可能是正确的,但我很好奇更具体的答案,因为我仍然发现单线程程序执行如此简单/常见操作后的缓慢意外行为forking。检查后http://opensource.apple.com/source/Libc/Libc-997.1.1/stdtime/FreeBSD/localtime.c http://opensource.apple.com/source/Libc/Libc-997.1.1/stdtime/FreeBSD/localtime.c(不能100%确定这是正确的来源),我想我有一个答案。

该代码使用被动通知来确定时区是否已更改(与stating /etc/localtime每次)。看起来注册的通知令牌在子进程中变得无效forking。此外,代码将使用无效令牌产生的错误视为时区已更改的积极通知,并继续读取/etc/localtime每次。我想这是你可以得到的那种未定义的行为fork英?不过,如果图书馆注意到该错误并重新注册通知,那就太好了。

以下是 localtime.c 中的代码片段,它将错误值与状态值混合在一起:

nstat = notify_check(p->token, &ncheck);
if (nstat || ncheck) {

我演示了使用此程序分叉后注册令牌变得无效:

#include <notify.h>
#include <stdio.h>
#include <stdlib.h>

void bail(char *msg) {
  printf("Error: %s\n", msg);
  exit(1);
}

int main(int argc, char **argv) {
  int token, something_changed, ret;

  notify_register_check("com.apple.system.timezone", &token);

  ret = notify_check(token, &something_changed);
  if (ret)
    bail("notify_check #1 failed");
  if (!something_changed)
    bail("expected change on first call");

  ret = notify_check(token, &something_changed);
  if (ret)
    bail("notify_check #2 failed");
  if (something_changed)
    bail("expected no change");

  pid_t c = fork();
  if (c == 0) {
    ret = notify_check(token, &something_changed);
    if (ret) {
      if (ret == NOTIFY_STATUS_INVALID_TOKEN)
        printf("ret is invalid token\n");

      if (!notify_is_valid_token(token))
        printf("token is not valid\n");

      bail("notify_check in fork failed");
    }

    if (something_changed)
      bail("expected not changed");

    exit(0);
  }

  wait(NULL);
}

并像这样运行:

muir-mb:projects muir$ clang -o notify_test notify_test.c 
muir-mb:projects muir$ ./notify_test 
ret is invalid token
token is not valid
Error: notify_check in fork failed
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 tzset() 在 Mac OS X 上 fork 后速度变慢了? 的相关文章

随机推荐

  • .forEach 完成后执行回调函数

    我试图在 forEach 循环完成所有迭代后执行一个函数 This answer https stackoverflow com a 18983245 3976696提供了一个有趣的解决方案 但我无法让它发挥作用 这是我改编的代码 创建了一
  • 将 Android 库导出为 AAR 文件

    我在我的项目中创建了一个库模块 现在 我想与其他人分享 发布这个库 目前共享 aar 文件就可以了 我浏览了这篇文章 https developer android com studio projects android library h
  • Maven:生命周期阶段与目标之间的关系

    我很难在某些 Maven 概念中看到 树木中的森林 我知道 Maven 预先配置了一系列所谓的 构建生命周期阶段 开头为validate and test并结束于deploy 我从 Ant 转向 Maven 在 Ant 中 您将主要构建阶段
  • mysql_insert_id 或类似的东西返回最后一个 mysql UUID()

    如何返回最后生成的 UUID 主键 有类似 mysql insert id 的东西吗 Table uuidtable primary key uuid uuid id u index integer 多个 id u 与主键 uuid 匹配
  • 如何使 rake 测试不使用默认的 minitest?

    我正在跟随制作你自己的宝石 http guides rubygems org make your own gem来自 RubyGems 的指南 执行rake test指令失败如下 gt rake test rbenv versions 2
  • 使用 Backbone 将文件上传到 tastypie?

    检查了一些其他问题 我认为我的 tastypie 资源应该如下所示 class MultipartResource object def deserialize self request data format None if not fo
  • 聚类——稀疏向量和稠密向量

    对于聚类 Mahout 输入需要采用向量形式 有两种类型的向量实现 一种是稀疏向量 另一种是密集向量 两者有什么区别 稀疏和密集的使用场景 从概念上讲 稀疏向量中的大多数值都为零 而在稠密向量中则不是 对于稠密矩阵和稀疏矩阵也是如此 条款s
  • emacs 窗口中的文本居中

    在一个孤独的 emacs 框架内 我频繁地在编辑 70 列文本文件 LaTeX 和 120 列程序 h cpp 文件 之间切换 我想继续仅使用一个 emacs 框架 而不调整其大小或创建其他框架 问题就在这里 我的窗口宽度大约适合编辑 12
  • 使用未选中的复选框,如何过滤掉始终隐藏的 NSFW 标记的 div,但选中打开时,以遵循可见性规则?

    这个问题基于这个问题 答案 同时使用复选框和下拉菜单进行准确过滤 https stackoverflow com q 68317206 4383420 Hi 注意 简化的问题和代码位于代码笔或下面的代码片段中 这里我只是解释上下文 Imag
  • 将 FutureBuilder 与 setState 一起使用

    如何使用FutureBuilder with setState适当地 例如 当我创建一个有状态小部件时 它开始加载数据 FutureBuilder 然后我应该用新数据更新列表 所以我使用 setState 但它开始无限循环 因为我再次重建小
  • 如何使用 bnd/maven-bundle-plugin 将资源文件从 jar 依赖项包含到 osgi 包中?

    我在用着maven bundle plugin bnd有效地 从源中包含资源文件很简单 例如 资源文件 src main resources some xml 移至下面target目录 target classes some xml 在构建
  • 在 Backbone.js 中实现 Backbone.Subset.js 以从父集合中过滤模型

    In 这个 stackoverflow 帖子 https stackoverflow com questions 6865174 backbone js correct way of filter collection data and d
  • 如何获取 ntile() 的间隔

    我试图弄清楚是否有一种方法可以获取用于何时的间隔ntile 用来 我有一个样本 我想将其用作获取较大样本的百分位值的基础 并且我希望找到一种方法来获取使用时的间隔值ntile 对此的任何启发将不胜感激 我真的很想把这个作为评论 但我仍然无法
  • 手动删除 anaconda python 中 pkgs 文件夹中的所有文件是否安全?

    我运行这个命令来释放 anaconda 上的磁盘空间 conda clean all 但是 仍然有一些大文件残留在pkgsanaconda python 中的文件夹 手动删除其中的所有文件是否安全pkgs文件夹 有破坏我的 anaconda
  • Invoke-Restmethod:如何获取返回码?

    有没有办法在调用时将返回码存储在某处Invoke RestMethod在 PowerShell 中 我的代码如下所示 url http www dictionaryapi com api v1 references collegiate x
  • 如何从字符串中获取size_t?

    我需要从用户输入中获取数组大小 对我来说 将输入存储为很自然size t 但是正在寻找合适的strto 功能我找不到 我刚用过strtoull since unsigned long long保证至少是 64 位 而且我无论如何都使用 C9
  • 可变值和不可变值重定义有什么区别?

    我读到 F 中的值是不可变的 然而 我也遇到了重新定义价值定义的概念 它掩盖了以前的定义 这与可变值有何不同 我问这不仅是一个理论构造 而且还询问是否有关于何时使用可变值以及何时重新定义表达式的建议 或者如果有人可以指出后者不是惯用的 f
  • 如何让 GNU Unifont 或 Free Mono 在 gvim windows 上运行?

    我正在尝试在 Windows 7 上的 gvim 中获得对符文字符的支持 我的 Fonts 目录中安装了 Free Mono 和 GNU Unifont 字体 都支持此范围 但它们没有出现在字体菜单中 gvim 给出了我收到以下行的无效字体
  • ASP.NET MVC 4 引用单父实体的多个外键

    我正在尝试开发一个 ASP NET MVC 4 应用程序 可以根据玩家的进攻 防守和助攻技能对他们进行评级 进攻 防守和助攻是球员表上的外键 引用相同的查找表 评分 我有以下父实体 public class Rating public in
  • 为什么 tzset() 在 Mac OS X 上 fork 后速度变慢了?

    Calling tzset fork之后显得很慢 如果我第一次打电话 我只会看到缓慢的情况tzset 在 fork 之前在父进程中 我的TZ环境变量未设置 我dtruss我的测试程序显示子进程读取 etc localtime对于每一个tzs