Re: Some performance notes
- From: Johannes Stezenbach <js convergence de>
- To: Tim Janik <timj gtk org>
- Cc: Owen Taylor <otaylor redhat com>, Gtk+ Developers <gtk-devel-list gnome org>
- Subject: Re: Some performance notes
- Date: Wed, 08 Aug 2001 12:59:26 +0200
Tim Janik wrote:
>
> On Mon, 6 Aug 2001, Johannes Stezenbach wrote:
>
> > int i;
> > GObject *obj[10000];
> > for (i = 0; i < 10000; i++)
> > obj[i] = g_object_new (G_TYPE_OBJECT, NULL);
> >
> > takes about 20 msecs. Not too bad ;-)
> >
> > The same using
> >
> > obj[i] = g_cim_list_new ();
> >
> > takes 700 msecs
> don't let the code's complexity fool you, it's written to handle unlimted
> numbers of construct and non-construct parameters, however the
> normal case is none or 1 construct property per object, so that
> code like:
> if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
> {
...
>
> usually boils down to a NOP.
I created a stand-alone test program which shows that either using two
G_PARAM_CONSTRUCT_ONLY or passing two property arguments to g_object_new()
slows down object creating by a factor of 16.
(Creating 100.000 objects takes 1 sec. vs. 16 sec. on my PIII 733.)
I profiled it using gprof and attach relevant excerpts from the
profile results.
Regards,
Johannes
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ns/call ns/call name
8.70 0.04 0.04 800705 49.96 49.96 lookup_type_node_L
8.70 0.08 0.04 200004 200.00 433.26 g_type_class_ref
8.70 0.12 0.04 100044 399.82 399.82 type_get_qdata_L
6.52 0.15 0.03 200032 149.98 149.98 type_data_ref_Wm
6.52 0.18 0.03 100003 299.99 1799.45 g_type_create_instance
4.35 0.20 0.02 400113 49.99 49.99 g_malloc
4.35 0.22 0.02 400016 50.00 50.00 g_free
4.35 0.24 0.02 200002 100.00 100.00 g_datalist_id_get_data
4.35 0.26 0.02 200002 100.00 299.99 g_object_notify_queue_freeze
4.35 0.28 0.02 100058 199.88 249.87 g_strdup
4.35 0.30 0.02 100006 199.99 199.99 g_slist_free
4.35 0.32 0.02 100005 199.99 349.83 g_type_check_instance_cast
4.35 0.34 0.02 100001 200.00 599.99 g_object_init
4.35 0.36 0.02 100001 200.00 200.00 test_object_init
2.17 0.37 0.01 400568 24.96 24.96 g_static_rw_lock_reader_lock
2.17 0.38 0.01 400568 24.96 24.96 g_static_rw_lock_reader_unlock
2.17 0.39 0.01 300060 33.33 33.33 g_static_rw_lock_writer_unlock
2.17 0.40 0.01 200006 50.00 149.99 g_data_set_internal
2.17 0.41 0.01 200004 50.00 199.99 g_datalist_id_set_data_full
2.17 0.42 0.01 200002 50.00 174.99 g_object_notify_queue_thaw
2.17 0.43 0.01 100001 100.00 100.00 g_datalist_init
2.17 0.44 0.01 100001 100.00 3999.34 g_object_new
2.17 0.45 0.01 100001 100.00 3899.34 g_object_newv
2.17 0.46 0.01 100001 100.00 183.28 g_type_class_unref
(% time for remaining functions was shown as 0.0)
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ns/call ns/call name
11.70 0.77 0.77 18800885 40.96 40.96 lookup_type_node_L
9.88 1.42 0.65 7400315 87.83 167.83 g_type_value_table_peek
5.17 1.76 0.34 14600710 23.29 23.29 g_static_rw_lock_reader_lock
4.86 2.08 0.32 3700052 86.49 86.49 type_node_is_a_L
3.95 2.34 0.26 2700070 96.29 96.29 type_get_qdata_L
3.65 2.58 0.24 200002 1199.99 14405.40 g_signal_emit_valist
3.50 2.81 0.23 14600710 15.75 15.75 g_static_rw_lock_reader_unlock
2.89 3.00 0.19 800230 237.43 387.37 g_hash_table_lookup_node
2.43 3.16 0.16 2600026 61.54 237.83 type_check_is_value_type_U
2.43 3.32 0.16 200002 799.99 3822.15 signal_emit_unlocked_R
2.28 3.47 0.15 1100015 136.36 343.80 g_type_check_instance_cast
2.28 3.62 0.15 1000010 150.00 1091.25 g_value_type_compatible
1.98 3.75 0.13 100001 1299.99 65253.65 g_object_new_valist
1.67 3.86 0.11 2200022 50.00 287.83 g_type_check_value
1.52 3.96 0.10 1600016 62.50 269.93 g_type_is_a
1.52 4.06 0.10 1000018 100.00 307.43 g_type_instance_is_a
1.37 4.15 0.09 800132 112.48 499.86 g_hash_table_lookup
1.37 4.24 0.09 800008 112.50 610.65 g_value_init
1.22 4.32 0.08 200002 400.00 1655.64 g_closure_invoke
1.22 4.40 0.08 200002 400.00 2640.61 g_param_value_validate
0.91 4.46 0.06 800008 75.00 706.26 g_value_unset
0.91 4.52 0.06 400004 150.00 170.00 value_free_string
0.91 4.58 0.06 300005 200.00 354.27 g_type_class_ref
0.91 4.64 0.06 200006 299.99 607.42 g_param_spec_ref
0.91 4.70 0.06 200002 300.00 2323.28 g_value_copy
0.76 4.75 0.05 400014 125.00 125.00 param_spec_pool_hash
0.76 4.80 0.05 200046 249.94 749.95 g_quark_from_string
0.76 4.85 0.05 200006 249.99 433.31 g_data_set_internal
0.76 4.90 0.05 200002 250.00 557.43 g_object_unref
0.76 4.95 0.05 200002 250.00 1440.12 test_object_set_property
0.76 5.00 0.05 200002 250.00 1948.67 value_param_collect_value
0.76 5.05 0.05 100001 500.00 843.79 param_int_validate
0.61 5.09 0.04 700119 57.13 57.13 g_malloc
0.61 5.13 0.04 400008 100.00 649.86 g_param_spec_pool_lookup
0.61 5.17 0.04 400004 100.00 100.00 closure_invoke_notifiers
0.61 5.21 0.04 400004 100.00 607.76 g_type_check_value_holds
0.61 5.25 0.04 400004 100.00 378.71 g_value_object_free_value
0.61 5.29 0.04 200078 199.92 199.92 g_direct_hash
0.61 5.33 0.04 200002 200.00 200.00 g_closure_unref
0.61 5.37 0.04 200002 200.00 300.00 g_generic_node_alloc
0.61 5.41 0.04 200002 200.00 16107.00 g_object_notify_queue_thaw
0.61 5.45 0.04 200002 200.00 507.43 g_object_ref
0.61 5.49 0.04 200002 200.00 805.65 g_value_peek_pointer
0.61 5.53 0.04 200002 200.00 4004.29 g_value_set_instance
0.61 5.57 0.04 200002 200.00 699.85 handler_list_lookup
0.61 5.61 0.04 200002 200.00 10461.60 object_set_property
0.61 5.65 0.04 200002 200.00 200.00 value_init_long0
0.61 5.69 0.04 100001 400.00 57541.42 g_object_newv
0.46 5.72 0.03 1200012 25.00 25.00 value_meminit
0.46 5.75 0.03 400004 75.00 154.99 g_type_check_instance
0.46 5.78 0.03 300062 99.98 157.11 g_strdup
0.46 5.81 0.03 300003 100.00 100.00 g_trash_stack_pop
0.46 5.84 0.03 200204 149.85 149.85 g_str_hash
0.46 5.87 0.03 200007 149.99 150.00 _g_slist_alloc
0.46 5.90 0.03 200004 150.00 583.31 g_datalist_id_set_data_full
0.46 5.93 0.03 200002 150.00 216.66 emission_pop
0.46 5.96 0.03 200002 150.00 491.66 g_object_notify_queue_freeze
0.46 5.99 0.03 200002 150.00 14555.40 g_signal_emit
0.46 6.02 0.03 200002 150.00 229.99 g_type_class_peek
0.46 6.05 0.03 200002 150.00 150.00 g_value_object_peek_pointer
0.46 6.08 0.03 200002 150.00 150.00 value_init_string
0.46 6.11 0.03 100001 300.00 30910.70 g_object_dispatch_properties_changed
0.46 6.14 0.03 100001 300.00 31210.70 g_object_notify_dispatcher
0.30 6.16 0.02 1000022 20.00 20.00 g_free
0.30 6.18 0.02 500062 40.00 40.00 g_static_rw_lock_writer_lock
0.30 6.20 0.02 500062 40.00 40.00 g_static_rw_lock_writer_unlock
0.30 6.22 0.02 400008 50.00 549.86 param_spec_ht_lookup
0.30 6.24 0.02 400004 50.00 50.01 test_object_get_type
0.30 6.26 0.02 300033 66.66 66.66 g_trash_stack_push
0.30 6.28 0.02 200007 100.00 249.99 g_slist_prepend
0.30 6.30 0.02 200002 100.00 400.00 emission_push
0.30 6.32 0.02 200002 100.00 1698.68 g_value_object_collect_value
0.30 6.34 0.02 200002 100.00 100.00 g_value_object_init
0.30 6.36 0.02 200002 100.00 100.00 type_data_unref_Wm
0.30 6.38 0.02 200002 100.00 100.00 value_param_init
0.30 6.40 0.02 100135 199.73 199.73 g_malloc0
0.30 6.42 0.02 100006 199.99 199.99 g_slist_free
0.30 6.44 0.02 100005 199.99 376.28 g_type_check_flags
0.30 6.46 0.02 100001 200.00 543.80 param_string_validate
0.15 6.47 0.01 300033 33.33 33.33 type_data_ref_Wm
0.15 6.48 0.01 200003 50.00 50.00 LOOKUP_SIGNAL_NODE
0.15 6.49 0.01 200002 50.00 50.00 emission_find
0.15 6.50 0.01 200002 50.00 299.99 g_object_notify_queue_add
0.15 6.51 0.01 200002 50.00 855.65 g_type_class_meta_marshal
0.15 6.52 0.01 100003 100.00 1427.66 g_type_create_instance
0.15 6.53 0.01 100001 100.00 930.25 g_object_constructor
0.15 6.54 0.01 100001 100.00 366.65 g_object_notify_queue_free
0.15 6.55 0.01 100001 100.00 864.87 g_value_dup_string
0.15 6.56 0.01 100001 100.00 707.76 g_value_get_int
0.15 6.57 0.01 100001 100.00 100.00 test_object_init
0.15 6.58 0.01 main
(% time for remaining functions was shown as 0.0)
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total
time seconds seconds calls ns/call ns/call name
12.05 0.83 0.83 20800905 39.90 39.90 lookup_type_node_L
7.40 1.34 0.51 16000724 31.87 31.87 g_static_rw_lock_reader_lock
7.11 1.83 0.49 16000724 30.62 30.62 g_static_rw_lock_reader_unlock
6.82 2.30 0.47 7400315 63.51 165.91 g_type_value_table_peek
5.95 2.71 0.41 4500060 91.11 91.11 type_node_is_a_L
4.64 3.03 0.32 3200032 100.00 287.24 type_check_is_value_type_U
4.06 3.31 0.28 3300076 84.85 84.85 type_get_qdata_L
3.63 3.56 0.25 200002 1249.99 13705.45 g_signal_emit_valist
2.61 3.74 0.18 1500019 120.00 353.41 g_type_check_instance_cast
2.32 3.90 0.16 1200020 133.33 366.74 g_type_instance_is_a
2.18 4.05 0.15 200002 749.99 3074.02 signal_emit_unlocked_R
1.74 4.17 0.12 2600026 46.15 333.40 g_type_check_value
1.74 4.29 0.12 800008 150.00 584.20 g_value_init
1.60 4.40 0.11 300003 366.66 10229.44 g_object_notify_queue_thaw
1.45 4.50 0.10 100001 999.99 67831.76 g_object_newv
1.31 4.59 0.09 1800018 50.00 283.41 g_type_is_a
1.31 4.68 0.09 1000010 90.00 1037.05 g_value_type_compatible
1.31 4.77 0.09 400226 224.87 374.77 g_hash_table_lookup_node
1.16 4.85 0.08 100003 799.98 1853.14 g_type_create_instance
1.02 4.92 0.07 200006 349.99 516.64 g_data_set_internal
1.02 4.99 0.07 200002 350.00 1249.30 g_closure_invoke
0.87 5.05 0.06 400004 150.00 252.40 g_type_check_instance
0.87 5.11 0.06 200002 300.00 4121.11 g_value_transform
0.87 5.17 0.06 200002 300.00 10630.85 object_set_property
0.87 5.23 0.06 100001 599.99 33868.79 g_object_constructor
0.73 5.28 0.05 1400014 35.71 35.71 value_meminit
0.73 5.33 0.05 800008 62.50 706.27 g_value_unset
0.73 5.38 0.05 400004 125.00 125.00 closure_invoke_notifiers
0.73 5.43 0.05 200009 249.99 249.99 _g_slist_alloc
0.73 5.48 0.05 200002 250.00 3007.77 g_param_value_set_default
0.73 5.53 0.05 200002 250.00 2427.61 g_param_value_validate
0.73 5.58 0.05 200002 250.00 1703.79 value_param_collect_value
0.58 5.62 0.04 400128 99.97 474.74 g_hash_table_lookup
0.58 5.66 0.04 400064 99.98 112.49 g_strdup
0.58 5.70 0.04 400004 100.00 100.00 test_object_get_type
0.58 5.74 0.04 300060 133.31 133.31 g_static_rw_lock_writer_unlock
0.58 5.78 0.04 300033 133.32 133.32 g_trash_stack_push
0.58 5.82 0.04 200004 200.00 716.64 g_datalist_id_set_data_full
0.58 5.86 0.04 200003 200.00 200.00 LOOKUP_SIGNAL_NODE
0.58 5.90 0.04 200002 200.00 200.00 emission_find
0.58 5.94 0.04 200002 200.00 302.40 g_type_class_peek
0.58 5.98 0.04 200002 200.00 1603.79 g_value_object_collect_value
0.58 6.02 0.04 200002 200.00 3886.63 g_value_set_instance
0.44 6.05 0.03 600006 50.00 620.66 g_type_check_value_holds
0.44 6.08 0.03 400004 75.00 308.37 value_param_free_value
0.44 6.11 0.03 300003 100.00 361.11 g_object_notify_queue_freeze
0.44 6.14 0.03 200204 149.85 149.85 g_str_hash
0.44 6.17 0.03 200032 149.98 149.98 type_data_ref_Wm
0.44 6.20 0.03 200002 150.00 150.00 _g_list_alloc
0.44 6.23 0.03 100001 300.00 920.65 g_value_get_int
0.44 6.26 0.03 100001 300.00 653.41 param_string_validate
0.29 6.28 0.02 400119 49.99 49.99 g_malloc
0.29 6.30 0.02 300060 66.65 66.65 g_static_rw_lock_writer_lock
0.29 6.32 0.02 300003 66.67 66.67 g_trash_stack_pop
0.29 6.34 0.02 200078 99.96 99.96 g_direct_hash
0.29 6.36 0.02 200046 99.98 574.85 g_quark_from_string
0.29 6.38 0.02 200004 100.00 489.84 g_type_class_ref
0.29 6.40 0.02 200002 100.00 100.00 _g_list_free_1
0.29 6.42 0.02 200002 100.00 200.00 g_list_free_1
0.29 6.44 0.02 200002 100.00 466.74 g_object_unref
0.29 6.46 0.02 200002 100.00 466.74 g_param_spec_unref
0.29 6.48 0.02 200002 100.00 599.31 g_type_class_meta_marshal
0.29 6.50 0.02 200002 100.00 2117.27 g_value_copy
0.29 6.52 0.02 200002 100.00 100.00 g_value_object_init
0.29 6.54 0.02 200002 100.00 673.91 g_value_reset
0.29 6.56 0.02 200002 100.00 1485.86 test_object_set_property
0.29 6.58 0.02 200002 100.00 100.00 value_param_init
0.29 6.60 0.02 100006 199.99 199.99 g_slist_free
0.29 6.62 0.02 100001 200.00 28760.59 g_object_dispatch_properties_changed
0.29 6.64 0.02 100001 200.00 933.14 g_value_dup_string
0.29 6.66 0.02 100001 200.00 200.00 test_object_init
0.29 6.68 0.02 100001 200.00 68797.66 test_object_new
0.15 6.69 0.01 900021 11.11 11.11 g_free
0.15 6.70 0.01 400210 24.99 24.99 g_str_equal
0.15 6.71 0.01 400004 25.00 258.37 g_value_object_free_value
0.15 6.72 0.01 300003 33.33 33.33 value_init_long0
0.15 6.73 0.01 300003 33.33 33.33 value_init_string
0.15 6.74 0.01 200009 50.00 299.99 g_slist_prepend
0.15 6.75 0.01 200006 50.00 416.74 g_param_spec_ref
0.15 6.76 0.01 200002 50.00 50.00 accumulate
0.15 6.77 0.01 200002 50.00 183.32 emission_pop
0.15 6.78 0.01 200002 50.00 166.68 emission_push
0.15 6.79 0.01 200002 50.00 50.00 g_closure_unref
0.15 6.80 0.01 200002 50.00 116.68 g_generic_node_alloc
0.15 6.81 0.01 200002 50.00 200.00 g_list_prepend
0.15 6.82 0.01 200002 50.00 349.99 g_object_notify_queue_add
0.15 6.83 0.01 100001 100.00 461.11 g_object_init
0.15 6.84 0.01 100001 100.00 67931.76 g_object_new_valist
0.15 6.85 0.01 100001 100.00 28860.59 g_object_notify_dispatcher
0.15 6.86 0.01 100001 100.00 439.86 g_type_class_unref
0.15 6.87 0.01 100001 100.00 100.00 type_data_unref_Wm
0.15 6.88 0.01 100001 100.00 100.00 value_copy_long0
0.15 6.89 0.01 __bb_exit_func
(% time for remaining functions was shown as 0.0)
/********************************************************************
Demonstrate slowness of GObject properties passed to g_object_new():
First I built a profiling version of Glib using:
CFLAGS="-pg -g -a" ./autogen.sh --disable-gtk-doc --enable-debug=minimum \
--prefix=/home/js/profile --disable-shared
Then try:
gcc -Wall -pg -g -a gobject-test.c -o gobject-test \
`pkg-config --cflags gobject-2.0` `pkg-config --libs gobject-2.0`
vs.
gcc -DMAKE_IT_SLOW_1 -Wall -pg -g -a gobject-test.c -o gobject-test \
`pkg-config --cflags gobject-2.0` `pkg-config --libs gobject-2.0`
or
gcc -DMAKE_IT_SLOW_2 -Wall -pg -g -a gobject-test.c -o gobject-test \
`pkg-config --cflags gobject-2.0` `pkg-config --libs gobject-2.0`
./gobject-test
gprof ./gobject-test
**********************************************************************/
#define REPEATS 100000
#include <glib.h>
#include <glib-object.h>
/*************************/
#define TYPE_TEST_OBJECT (test_object_get_type ())
#define TEST_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
TYPE_TEST_OBJECT, TestObject))
#define IS_TEST_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
TYPE_TEST_OBJECT))
typedef struct _TestObject TestObject;
typedef struct _TestObjectClass TestObjectClass;
struct _TestObject
{
GObject parent_instance;
gint foo;
gchar *bar;
};
struct _TestObjectClass
{
GObjectClass parent_class;
};
GType test_object_get_type (void) G_GNUC_CONST;
TestObject *test_object_new (void);
enum
{
PROP_0,
PROP_FOO,
PROP_BAR
};
static void test_object_class_init (TestObjectClass *klass);
static void test_object_init (TestObject *object);
static void test_object_finalize (GObject *object);
static void test_object_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void test_object_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static GObjectClass *parent_class = NULL;
GType
test_object_get_type (void)
{
static GType test_object_type = 0;
if (!test_object_type)
{
static const GTypeInfo test_object_info =
{
sizeof (TestObjectClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) test_object_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (TestObject),
0, /* n_preallocs */
(GInstanceInitFunc) test_object_init,
};
test_object_type =
g_type_register_static (G_TYPE_OBJECT, "TestObject",
&test_object_info, 0);
}
return test_object_type;
}
static void
test_object_class_init (TestObjectClass *klass)
{
GObjectClass *object_class;
GParamSpec *param_spec;
object_class = G_OBJECT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
object_class->set_property = test_object_set_property;
object_class->get_property = test_object_get_property;
param_spec = g_param_spec_string ("bar", NULL, NULL,
NULL,
G_PARAM_READABLE | G_PARAM_WRITABLE
#ifdef MAKE_IT_SLOW_2
| G_PARAM_CONSTRUCT_ONLY
#endif
);
g_object_class_install_property (object_class, PROP_BAR, param_spec);
param_spec = g_param_spec_int ("foo", NULL, NULL,
G_MININT, G_MAXINT, 0,
G_PARAM_READABLE | G_PARAM_WRITABLE
#ifdef MAKE_IT_SLOW_2
| G_PARAM_CONSTRUCT_ONLY
#endif
);
g_object_class_install_property (object_class, PROP_FOO, param_spec);
object_class->finalize = test_object_finalize;
}
static void
test_object_init (TestObject *object)
{
object->bar = NULL;
object->foo = 0;
}
static void
test_object_finalize (GObject *object)
{
TestObject *obj;
obj = (TestObject *) (object);
g_free (obj->bar);
if (G_OBJECT_CLASS (parent_class)->finalize)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
test_object_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
TestObject *test_object;
test_object = TEST_OBJECT (object);
switch (property_id)
{
case PROP_FOO:
test_object->foo = g_value_get_int (value);
break;
case PROP_BAR:
g_free (test_object->bar);
test_object->bar = g_value_dup_string (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
test_object_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
TestObject *test_object;
test_object = TEST_OBJECT (object);
switch (property_id)
{
case PROP_BAR:
g_value_set_string (value, test_object->bar);
break;
case PROP_FOO:
g_value_set_int (value, test_object->foo);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
TestObject *
test_object_new (void)
{
#ifdef MAKE_IT_SLOW_1
return TEST_OBJECT (g_object_new (test_object_get_type (),
"foo", 5,
"bar", "blah",
NULL));
#else
TestObject *obj =
TEST_OBJECT (g_object_new (test_object_get_type (),
NULL));
obj->foo = 5;
obj->bar = g_strdup ("blah");
return obj;
#endif
}
/*************************/
int main (int argc, char *argv[])
{
GTimeVal start, end;
int i;
TestObject *obj[REPEATS];
g_type_init_with_debug_flags (G_TYPE_DEBUG_NONE);
test_object_new ();
g_get_current_time (&start);
for (i = 0; i < REPEATS; i++)
obj[i] = test_object_new ();
g_get_current_time (&end);
if (end.tv_usec - start.tv_usec < 0)
end.tv_sec--, end.tv_usec += 1000000;
g_print ("loop %d, %ld.%06ld sec\n", REPEATS,
(end.tv_sec - start.tv_sec),
(end.tv_usec - start.tv_usec));
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]