【问题标题】:GObject g_type_init and g_object_new take hundres of millisecondsGObject g_type_init 和 g_object_new 需要数百毫秒
【发布时间】:2016-01-13 10:30:39
【问题描述】:

我们在 Apache httpd 模块中使用 Apache Thrift 将来自另一个服务的数据注入到请求中。除了似乎源于 gobject 的一些奇怪的性能问题之外,这很好用。

类型系统和/或第一个对象的初始化通常需要 100ms)。

在child_init-Handler中,调用g_type_init()来初始化类型系统。读取请求时,使用 g_object_new(大约 6)创建对象。

使用gettimeofday 测量对象初始化的时间,以获取用户经过的时间。它看起来像这样:

VhostResult *result = NULL;
struct timeval  tv1, tv2;
gettimeofday(&tv1, NULL);
result = g_object_new (TYPE_VHOST_RESULT, NULL);
gettimeofday(&tv2, NULL);

这个问题只分批出现。所有对象初始化都低于 1 毫秒几分钟,然后在同一秒内有大约 10 个请求需要 500 毫秒来创建第一个对象,同时完成。

请注意进程总是在请求之后被销毁,所以它总是是一个新的分叉进程,这意味着没有内存泄漏。

编辑:按照建议,我在墙上时间之外添加了 clock() 的测量值,它报告测量代码块的 0。

编辑 2:我查看了 grafana 数据,了解这些批次的缓慢初始化弹出且 iowait 始终很高的时间。是否会因为 iowait 或 iowait 也在测量内存访问而阻塞进程?

编辑3:用于计时(cpu时间)的代码是

  clock_t t = clock();

  result = g_object_newv(TYPE_VHOST_RESULT, 0, NULL);

  t = clock() - t; // stop

  ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "%i %s result init clock %f ms", thepid, r->hostname, ((float)t)/CLOCKS_PER_SEC*1000);

这可能是什么原因?

【问题讨论】:

  • 恕我直言,您可能需要改进您的配置文件。 gettimeofday 是挂壁时间。因此,如果您的进程在调用gettimeofday 之间切换,那么计算的时间将不准确。一个建议是改用clock - 只是为了消除它作为一个因素。
  • @kaylum 但有了时钟我会得到 CPU 时间,而不是调用者/用户经过的时间,对吧?我想为用户测量和改进时间,而不是 CPU 时间。
  • 是的,最终目标当然是为用户缩短时间。但是要到达那里,您需要拥有正确的数据。您已经得出结论,g_object_new 有时需要 500 毫秒。但这个结论可能不正确,因此你会在完全错误的地方寻找。这就是为什么您需要 CPU 时间,以便您可以自信地说,是的,这个调用 单独 花费了所有时间。
  • 我也使用了clock() (clock() - t_start / CLOCKS_PER_SECOND),它给了我零。
  • 请显示您为clock 尝试的准确和完整代码。首先,您显示的 sn-p 看起来不正确,因为它似乎缺少减法周围的括号。

标签: c performance glib gobject


【解决方案1】:

+1 使用clock() 甚至更好的clock_getttime()。

此外,如果您实例化不带参数的对象,您可以使用以下方法避免可变参数开销:

g_object_newv(TYPE_VHOST_RESULT, 0, NULL);

如果您不时看到峰值,一种解释可能是内存子系统。 (隐藏的)free() 调用会导致 glibc 不时合并空闲区域。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    相关资源
    最近更新 更多