Skip to content

Commit 00c81ba

Browse files
committed
Replace linear space scan with hash for update fields
closes tarantoolgh-24
1 parent d62eb1a commit 00c81ba

File tree

2 files changed

+82
-70
lines changed

2 files changed

+82
-70
lines changed

src/tarantool_schema.c

+74-64
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,53 @@
1414
#define MUR_SEED 13
1515
#include "third_party/msgpuck.h"
1616

17-
int mh_indexcmp_eq(
18-
const struct schema_index_value **lval,
19-
const struct schema_index_value **rval,
20-
void *arg
21-
) {
22-
(void )arg;
23-
if ((*lval)->key.id_len != (*rval)->key.id_len)
24-
return 0;
25-
return !memcmp((*lval)->key.id, (*rval)->key.id, (*rval)->key.id_len);
26-
}
17+
#define MH_DEFINE_CMPFUNC(NAME, TYPE) \
18+
int mh_##NAME##cmp_eq(const TYPE **lval, const TYPE **rval, \
19+
void *arg) { \
20+
(void *) arg; \
21+
if ((*lval)->key.id_len != (*rval)->key.id_len) \
22+
return 0; \
23+
return !memcmp((*lval)->key.id, (*rval)->key.id, \
24+
(*rval)->key.id_len); \
25+
} \
26+
\
27+
int mh_##NAME##cmp_key_eq(const struct schema_key *key, \
28+
const TYPE **val, void *arg) { \
29+
(void *) arg; \
30+
if (key->id_len != (*val)->key.id_len) \
31+
return 0; \
32+
return !memcmp(key->id, (*val)->key.id, key->id_len); \
33+
}
2734

28-
int mh_indexcmp_key_eq(
29-
const struct schema_key *key,
30-
const struct schema_index_value **val,
31-
void *arg
32-
) {
33-
(void )arg;
34-
if (key->id_len != (*val)->key.id_len)
35-
return 0;
36-
return !memcmp(key->id, (*val)->key.id, key->id_len);
37-
}
35+
MH_DEFINE_CMPFUNC(field, struct schema_field_value);
36+
MH_DEFINE_CMPFUNC(index, struct schema_index_value);
37+
MH_DEFINE_CMPFUNC(space, struct schema_space_value);
38+
#undef MH_DEFINE_CMPFUNC
39+
40+
#define mh_arg_t void *
41+
42+
#define mh_eq(a, b, arg) mh_fieldcmp_eq(a, b, arg)
43+
#define mh_eq_key(a, b, arg) mh_fieldcmp_key_eq(a, b, arg)
44+
#define mh_hash(x, arg) PMurHash32(MUR_SEED, (*x)->key.id, \
45+
(*x)->key.id_len)
46+
#define mh_hash_key(x, arg) PMurHash32(MUR_SEED, (x)->id, (x)->id_len);
47+
48+
#define mh_node_t struct schema_field_value *
49+
#define mh_key_t struct schema_key *
50+
51+
#define MH_CALLOC(x, y) pecalloc((x), (y), 1)
52+
#define MH_FREE(x) pefree((x), 1)
53+
54+
#define mh_name _schema_field
55+
#define MH_SOURCE 1
56+
#include "third_party/mhash.h"
3857

3958
#define mh_arg_t void *
4059

4160
#define mh_eq(a, b, arg) mh_indexcmp_eq(a, b, arg)
4261
#define mh_eq_key(a, b, arg) mh_indexcmp_key_eq(a, b, arg)
43-
#define mh_hash(x, arg) PMurHash32(MUR_SEED, (*x)->key.id, (*x)->key.id_len)
62+
#define mh_hash(x, arg) PMurHash32(MUR_SEED, (*x)->key.id, \
63+
(*x)->key.id_len)
4464
#define mh_hash_key(x, arg) PMurHash32(MUR_SEED, (x)->id, (x)->id_len);
4565

4666
#define mh_node_t struct schema_index_value *
@@ -79,7 +99,7 @@ schema_index_free(struct mh_schema_index_t *schema) {
7999
do {
80100
struct schema_key key_number = {
81101
(void *)&(ivalue->index_number),
82-
sizeof(uint32_t), 0
102+
sizeof(ivalue->index_number), 0
83103
};
84104
index_slot = mh_schema_index_find(schema, &key_number,
85105
NULL);
@@ -106,33 +126,12 @@ schema_index_free(struct mh_schema_index_t *schema) {
106126
}
107127
}
108128

109-
int
110-
mh_spacecmp_eq(
111-
const struct schema_space_value **lval,
112-
const struct schema_space_value **rval,
113-
void *arg) {
114-
(void )arg;
115-
if ((*lval)->key.id_len != (*rval)->key.id_len)
116-
return 0;
117-
return !memcmp((*lval)->key.id, (*rval)->key.id, (*rval)->key.id_len);
118-
}
119-
120-
int
121-
mh_spacecmp_key_eq(
122-
const struct schema_key *key,
123-
const struct schema_space_value **val,
124-
void *arg) {
125-
(void )arg;
126-
if (key->id_len != (*val)->key.id_len)
127-
return 0;
128-
return !memcmp(key->id, (*val)->key.id, key->id_len);
129-
}
130-
131129
#define mh_arg_t void *
132130

133131
#define mh_eq(a, b, arg) mh_spacecmp_eq(a, b, arg)
134132
#define mh_eq_key(a, b, arg) mh_spacecmp_key_eq(a, b, arg)
135-
#define mh_hash(x, arg) PMurHash32(MUR_SEED, (*x)->key.id, (*x)->key.id_len)
133+
#define mh_hash(x, arg) PMurHash32(MUR_SEED, (*x)->key.id, \
134+
(*x)->key.id_len)
136135
#define mh_hash_key(x, arg) PMurHash32(MUR_SEED, x->id, x->id_len);
137136

138137
#define mh_node_t struct schema_space_value *
@@ -158,6 +157,9 @@ schema_space_value_free(const struct schema_space_value *val) {
158157
schema_index_free(val->index_hash);
159158
mh_schema_index_delete(val->index_hash);
160159
}
160+
if (val->schema_hash) {
161+
mh_schema_field_delete(val->schema_hash);
162+
}
161163
}
162164
}
163165

@@ -166,7 +168,8 @@ schema_space_free(struct mh_schema_space_t *schema) {
166168
int pos = 0;
167169
mh_int_t space_slot = 0;
168170
mh_foreach(schema, pos) {
169-
const struct schema_space_value *svalue, *sv1 = NULL, *sv2 = NULL;
171+
const struct schema_space_value *svalue;
172+
const struct schema_space_value *sv1 = NULL, *sv2 = NULL;
170173
svalue = *mh_schema_space_node(schema, pos);
171174
do {
172175
struct schema_key key_number = {
@@ -254,7 +257,8 @@ parse_schema_space_value(struct schema_space_value *space_string,
254257
goto error;
255258
int i = 0;
256259
for (i = 0; i < fmt_len; ++i) {
257-
struct schema_field_value *val = &(space_string->schema_list[i]);
260+
struct schema_field_value *val =
261+
&(space_string->schema_list[i]);
258262
if (mp_typeof(**tuple) != MP_MAP)
259263
goto error;
260264
uint32_t arrsz = mp_decode_map(tuple);
@@ -263,6 +267,11 @@ parse_schema_space_value(struct schema_space_value *space_string,
263267
goto error;
264268
}
265269
val->field_number = i;
270+
val->key.id = val->field_name;
271+
val->key.id_len = val->field_name_len;
272+
mh_schema_field_put(space_string->schema_hash,
273+
(const struct schema_field_value **)&val,
274+
NULL, NULL);
266275
}
267276
return 0;
268277
error:
@@ -289,7 +298,8 @@ parse_schema_index_value(struct schema_index_value *index_string,
289298
goto error;
290299
if (mp_decode_array(tuple) != 2)
291300
goto error;
292-
struct schema_field_value *val = &(index_string->index_parts[i]);
301+
struct schema_field_value *val =
302+
&(index_string->index_parts[i]);
293303
if (mp_typeof(**tuple) != MP_UINT)
294304
goto error;
295305
val->field_number = mp_decode_uint(tuple);
@@ -367,6 +377,7 @@ schema_add_space(
367377
* }
368378
*/
369379
case 6:
380+
space_string->schema_hash = mh_schema_field_new();
370381
if (parse_schema_space_value(space_string, &tuple) < 0)
371382
goto error;
372383
break;
@@ -590,27 +601,26 @@ tarantool_schema_get_fid_by_string(
590601
struct tarantool_schema *schema_obj, uint32_t sid,
591602
const char *field_name, uint32_t field_name_len
592603
) {
593-
struct mh_schema_space_t *schema = schema_obj->space_hash;
594-
struct schema_key space_key = {
595-
(void *)&sid,
596-
sizeof(uint32_t), 0
597-
};
598-
mh_int_t space_slot = mh_schema_space_find(schema, &space_key, NULL);
599-
if (space_slot == mh_end(schema))
604+
struct mh_schema_space_t *sschema = schema_obj->space_hash;
605+
struct schema_key space_key = { (void *)&sid, sizeof(uint32_t), 0 };
606+
mh_int_t space_slot = mh_schema_space_find(sschema, &space_key, NULL);
607+
if (space_slot == mh_end(sschema))
600608
return -1;
601-
const struct schema_space_value *space = *mh_schema_space_node(schema,
609+
const struct schema_space_value *space = *mh_schema_space_node(sschema,
602610
space_slot);
603-
int i = 0;
604-
for (i = 0; i < space->schema_list_len; ++i) {
605-
struct schema_field_value *val = &space->schema_list[i];
606-
if (strncmp(val->field_name, field_name, field_name_len) == 0)
607-
return val->field_number;
608-
}
609-
return -1;
611+
struct schema_key field_key = { field_name, field_name_len, 0 };
612+
struct mh_schema_field_t *fschema = space->schema_hash;
613+
mh_int_t field_slot = mh_schema_field_find(fschema, &field_key, NULL);
614+
if (field_slot == mh_end(fschema))
615+
return -1;
616+
const struct schema_field_value *field = *mh_schema_field_node(fschema,
617+
field_slot);
618+
return field->field_number;
610619
}
611620

612621
struct tarantool_schema *tarantool_schema_new(int is_persistent) {
613-
struct tarantool_schema *obj = pemalloc(sizeof(struct tarantool_schema *), 1);
622+
struct tarantool_schema *obj = NULL;
623+
obj = pemalloc(sizeof(struct tarantool_schema *), 1);
614624
obj->space_hash = mh_schema_space_new();
615625
return obj;
616626
}

src/tarantool_schema.h

+8-6
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,18 @@ enum field_type {
1414
};
1515

1616
struct schema_field_value {
17-
uint32_t field_number;
18-
char *field_name;
19-
uint32_t field_name_len;
20-
enum field_type field_type;
17+
struct schema_key key;
18+
uint32_t field_number;
19+
char *field_name;
20+
uint32_t field_name_len;
21+
enum field_type field_type;
2122
};
2223

2324
struct schema_index_value {
2425
struct schema_key key;
26+
uint32_t index_number;
2527
char *index_name;
2628
uint32_t index_name_len;
27-
uint32_t index_number;
2829
struct schema_field_value *index_parts;
2930
uint32_t index_parts_len;
3031
};
@@ -33,10 +34,11 @@ struct mh_schema_index_t;
3334

3435
struct schema_space_value {
3536
struct schema_key key;
37+
uint32_t space_number;
3638
char *space_name;
3739
uint32_t space_name_len;
38-
uint32_t space_number;
3940
struct mh_schema_index_t *index_hash;
41+
struct mh_schema_field_t *schema_hash;
4042
struct schema_field_value *schema_list;
4143
uint32_t schema_list_len;
4244
};

0 commit comments

Comments
 (0)