Skip to content

Commit a2a60ff

Browse files
committed
reduce TypeMap memory wastage
the TypeMap structure is usually very sparsely populated switching to an OrderedDict implementation allows faster iteration (the filled cells don't have gaps) and the index array can use a small memory footprint
1 parent 4913c25 commit a2a60ff

File tree

5 files changed

+233
-155
lines changed

5 files changed

+233
-155
lines changed

src/dump.c

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -938,38 +938,17 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v)
938938
// perform some compression on the typemap levels
939939
// (which will need to be rehashed during deserialization anyhow)
940940
jl_typemap_level_t *node = (jl_typemap_level_t*)v;
941-
size_t i, l;
942941
assert( // make sure this type has the expected ordering
943942
offsetof(jl_typemap_level_t, arg1) == 0 * sizeof(jl_value_t*) &&
944-
offsetof(jl_typemap_level_t, targ) == 1 * sizeof(jl_value_t*) &&
945-
offsetof(jl_typemap_level_t, linear) == 2 * sizeof(jl_value_t*) &&
946-
offsetof(jl_typemap_level_t, any) == 3 * sizeof(jl_value_t*) &&
947-
offsetof(jl_typemap_level_t, key) == 4 * sizeof(jl_value_t*) &&
948-
sizeof(jl_typemap_level_t) == 5 * sizeof(jl_value_t*));
949-
if (node->arg1 != (void*)jl_nothing) {
950-
jl_array_t *a = jl_alloc_vec_any(0);
951-
for (i = 0, l = jl_array_len(node->arg1); i < l; i++) {
952-
jl_value_t *d = jl_array_ptr_ref(node->arg1, i);
953-
if (d != NULL && d != jl_nothing)
954-
jl_array_ptr_1d_push(a, d);
955-
}
956-
jl_serialize_value(s, a);
957-
}
958-
else {
959-
jl_serialize_value(s, jl_nothing);
960-
}
961-
if (node->targ != (void*)jl_nothing) {
962-
jl_array_t *a = jl_alloc_vec_any(0);
963-
for (i = 0, l = jl_array_len(node->targ); i < l; i++) {
964-
jl_value_t *d = jl_array_ptr_ref(node->targ, i);
965-
if (d != NULL && d != jl_nothing)
966-
jl_array_ptr_1d_push(a, d);
967-
}
968-
jl_serialize_value(s, a);
969-
}
970-
else {
971-
jl_serialize_value(s, jl_nothing);
972-
}
943+
offsetof(jl_typemap_level_t, targ) == 2 * sizeof(jl_value_t*) &&
944+
offsetof(jl_typemap_level_t, linear) == 4 * sizeof(jl_value_t*) &&
945+
offsetof(jl_typemap_level_t, any) == 5 * sizeof(jl_value_t*) &&
946+
offsetof(jl_typemap_level_t, key) == 6 * sizeof(jl_value_t*) &&
947+
sizeof(jl_typemap_level_t) == 7 * sizeof(jl_value_t*));
948+
jl_serialize_value(s, jl_nothing);
949+
jl_serialize_value(s, node->arg1.values);
950+
jl_serialize_value(s, jl_nothing);
951+
jl_serialize_value(s, node->targ.values);
973952
jl_serialize_value(s, node->linear);
974953
jl_serialize_value(s, node->any.unknown);
975954
jl_serialize_value(s, node->key);

src/gf.c

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -981,19 +981,23 @@ static void invalidate_conflicting(union jl_typemap_t *pml, jl_value_t *type, jl
981981
jl_typemap_entry_t **pl;
982982
if (jl_typeof(pml->unknown) == (jl_value_t*)jl_typemap_level_type) {
983983
jl_typemap_level_t *cache = pml->node;
984-
if (cache->arg1 != (void*)jl_nothing) {
985-
for(int i=0; i < jl_array_len(cache->arg1); i++) {
986-
union jl_typemap_t *pl = &((union jl_typemap_t*)jl_array_data(cache->arg1))[i];
987-
if (pl->unknown && pl->unknown != jl_nothing) {
988-
invalidate_conflicting(pl, type, (jl_value_t*)cache->arg1, shadowed);
984+
if (cache->arg1.values != (void*)jl_nothing) {
985+
size_t i, l = jl_array_len(cache->arg1.values);
986+
union jl_typemap_t *d = (union jl_typemap_t*)jl_array_data(cache->arg1.values);
987+
for (i = 0; i < l; i++) {
988+
union jl_typemap_t *pl = &d[i];
989+
if (pl->unknown != jl_nothing) {
990+
invalidate_conflicting(pl, type, (jl_value_t*)cache->arg1.values, shadowed);
989991
}
990992
}
991993
}
992-
if (cache->targ != (void*)jl_nothing) {
993-
for(int i=0; i < jl_array_len(cache->targ); i++) {
994-
union jl_typemap_t *pl = &((union jl_typemap_t*)jl_array_data(cache->targ))[i];
995-
if (pl->unknown && pl->unknown != jl_nothing) {
996-
invalidate_conflicting(pl, type, (jl_value_t*)cache->targ, shadowed);
994+
if (cache->targ.values != (void*)jl_nothing) {
995+
size_t i, l = jl_array_len(cache->targ.values);
996+
union jl_typemap_t *d = (union jl_typemap_t*)jl_array_data(cache->targ.values);
997+
for (i = 0; i < l; i++) {
998+
union jl_typemap_t *pl = &d[i];
999+
if (pl->unknown != jl_nothing) {
1000+
invalidate_conflicting(pl, type, (jl_value_t*)cache->targ.values, shadowed);
9971001
}
9981002
}
9991003
}

src/jltypes.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3678,9 +3678,23 @@ void jl_init_types(void)
36783678

36793679
jl_typemap_level_type =
36803680
jl_new_datatype(jl_symbol("TypeMapLevel"), jl_any_type, jl_emptysvec,
3681-
jl_svec(5, jl_symbol("arg1"), jl_symbol("targ"), jl_symbol("list"), jl_symbol("any"), jl_symbol("key")),
3682-
jl_svec(5, jl_any_type, jl_any_type, jl_any_type, jl_any_type, jl_any_type),
3683-
0, 1, 4);
3681+
jl_svec(7,
3682+
jl_symbol("index_arg1"),
3683+
jl_symbol("arg1"),
3684+
jl_symbol("index_targ"),
3685+
jl_symbol("targ"),
3686+
jl_symbol("list"),
3687+
jl_symbol("any"),
3688+
jl_symbol("key")),
3689+
jl_svec(7,
3690+
jl_any_type,
3691+
jl_any_type,
3692+
jl_any_type,
3693+
jl_any_type,
3694+
jl_any_type,
3695+
jl_any_type,
3696+
jl_any_type),
3697+
0, 1, 6);
36843698

36853699
jl_typemap_entry_type =
36863700
jl_new_datatype(jl_symbol("TypeMapEntry"), jl_any_type, jl_emptysvec,

src/julia.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,10 +418,14 @@ typedef struct _jl_typemap_entry_t {
418418

419419
// one level in a TypeMap tree
420420
// indexed by key if it is a sublevel in an array
421+
struct jl_ordereddict_t {
422+
jl_array_t *indexes; // Array{Int{8,16,32}}
423+
jl_array_t *values; // Array{union jl_typemap_t}
424+
};
421425
typedef struct _jl_typemap_level_t {
422426
JL_DATA_TYPE
423-
jl_array_t *arg1; // Array{union jl_typemap_t}
424-
jl_array_t *targ; // Array{union jl_typemap_t}
427+
struct jl_ordereddict_t arg1;
428+
struct jl_ordereddict_t targ;
425429
jl_typemap_entry_t *linear; // union jl_typemap_t (but no more levels)
426430
union jl_typemap_t any; // type at offs is Any
427431
jl_value_t *key; // [nullable]

0 commit comments

Comments
 (0)