GObject Private 데이터 접근 오버헤드 줄이기
GTK+ 개발자 메일링 리스트에서 GTK+ 속도 관련 질의 응답 이 오가는 걸 지켜보는 도중 g_type_class_add_private() + g_type_instance_get_private() 조합을 사용하면 편하지만, 오버헤드가 크고 느리기 때문에 이를 줄일 수 있는 다른 방법을 소개한 내용 이 있어 결론만 정리해 보았습니다.
그 방법은, 그놈 프로그래밍 가이드라인 에서도 명시했듯이, 객체 데이터 선언시 ‘priv’ 등과 같은 필드를 선언하고, g_type_instance_get_private() 함수로 내부 데이터 주소를 얻어 ‘priv’ 필드에 저장해 둡니다. 그리고 다음부터는 그 필드를 이용하여 내부 데이터(Private Data)에 직접 접근하는 방식입니다.
예를 들어 기존의 코드가 다음과 같다면,
/* foo-object.h */
typedef struct _FooObject FooObject;
struct _FooObject
{
GObject parent;
};
gint foo_object_do_something (FooObject *foo);
/* foo-object.c */
typedef struct _FooObjectPrivate FooObjectPrivate;
struct _FooObjectPrivate
{
gboolean eating;
gint size;
};
#define FOO_OBJECT_GET_PRIVATE(obj)
(G_TYPE_INSTANCE_GET_PRIVATE ((obj),
FOO_TYPE_OBJECT,
FooObjectPrivate))
static void
foo_object_class_init (FooObjectClass *klass)
{
/* ... */
g_type_class_add_private (G_OBJECT_CLASS (klass),
sizeof (FooBarPrivate));
}
gint
foo_object_do_something (FooObject *foo)
{
FooObjectPrivate *priv;
priv = FOO_OBJECT_GET_PRIVATE (foo);
priv->eating = TRUE;
/* ... */
}
다음과 같이 변경하면, 매번 g_type_instance_get_private() 함수를 호출하는 오버헤드를 줄일 수 있습니다.
/* foo-object.h */
typedef struct _FooObjectPrivate FooObjectPrivate;
typedef struct _FooObject FooObject;
struct _FooObject
{
GObject parent;
FooObjectPrivate *priv;
};
gint foo_object_do_something (FooObject *foo);
/* foo-object.c */
struct _FooObjectPrivate
{
gboolean eating;
gint size;
};
#define FOO_OBJECT_GET_PRIVATE(obj)
(((FooObject *) (obj))->priv)
static void
foo_object_class_init (FooObjectClass *klass)
{
/* ... */
g_type_class_add_private (G_OBJECT_CLASS (klass),
sizeof (FooBarPrivate));
}
static void
foo_object_init (FooObject *obj)
{
/* ... */
obj->priv =
G_TYPE_INSTANCE_GET_PRIVATE (obj,
FOO_TYPE_OBJECT,
FooObjectPrivate);
}
gint
foo_object_do_something (FooObject *foo)
{
FooObjectPrivate *priv;
priv = FOO_OBJECT_GET_PRIVATE (foo);
priv->eating = TRUE;
/* ... */
}
물론 위에서 설명한 방식 대신 객체 초기화시 내부 데이터(private)를 아예 따로 할당해서 관리하는 방식도 비슷하지만, g_type_class_add_private() 함수를 통해 추가한 메모리는 GLib 라이브러리가 알아서 관리해주기 때문에 더 편합니다.