我们在 Apache httpd 模块中使用 Apache Thrift 将来自另一个服务的数据注入(inject)到请求中。除了一些似乎源于 gobject 的奇怪性能问题外,这工作正常。
类型系统和/或第一个对象的初始化通常需要 <1 毫秒,但有时批处理操作系统请求需要更长的时间(例如 >100 毫秒)。
在 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 毫秒来创建第一个对象,所有请求同时完成。
请注意,进程总是在请求后被销毁,所以它总是是一个新的 fork 进程,这意味着没有内存泄漏。
编辑:按照建议,除了挂钟时间外,我还使用 clock()
添加了测量值,它报告测量的代码块为 0。
编辑 2:我查看了 grafana 数据,了解这些批处理缓慢的 inits 弹出并且 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);
这可能是什么原因?
最佳答案
+1 使用 clock() 或更好的 clock_getttime()。
此外,如果您实例化对象时没有参数,您可以使用以下方法避免可变参数开销:
g_object_newv(TYPE_VHOST_RESULT, 0, NULL);
如果您不时看到尖峰,一种解释可能是内存子系统。 (隐藏的)free() 调用将导致 glibc 不时合并空闲区域。
关于c - GObject g_type_init 和 g_object_new 耗时数百毫秒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34643296/