From: Serge Petrenko <sergepetrenko@tarantool.org> To: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>, korablev@tarantool.org Cc: tarantool-patches@dev.tarantool.org Subject: Re: [Tarantool-patches] [PATCH 1/2] box: speed up tuple_field_map_create Date: Wed, 2 Dec 2020 12:53:21 +0300 [thread overview] Message-ID: <f506f4fd-c7a9-865c-2a66-dc860fa2c606@tarantool.org> (raw) In-Reply-To: <76a500bf-baa4-fc72-825d-ce324a190abf@tarantool.org> 02.12.2020 01:04, Vladislav Shpilevoy пишет: > Thanks for the investigation! > >>> Then we probably also could gain some perf by splitting these functions >>> into 2 versions with validate true and validate false. Because we always >>> know it at compile time. Would be cool to use templates for this, but not >>> sure if we can simply change tuple.c to tuple.cc only for that. >> >> You mean like that? >> >> tuple_field_map_create(...) { >> >> tuple_field_map_create_impl(..., true, ...); >> >> } >> >> tuple_field_map_create_unchecked(...) { >> >> tuple_field_mp_create_impl(..., false, ...); >> >> } >> >> I tried this approach, it didn't give anything. tuple_field_map_create time 2.15 s. > No, I mean create 2 versions of tuple_field_map_create. It leads > to some code duplication, and we probably don't want to do that > this way. But if it will give notable perf increase, we may decide > to consider templates. I see. I thought the compiler would do the same if it saw an inline function with explicit boolean argument. > >> Is this possible that compiler already evaluates `validate`? > I guess it can, but we can not be sure it will always do so. > > Consider this diff. Super ugly, but should reveal if validate > matters. After all, we have at least 4 validate checks here. The > diff replaces it with 1. Thanks for all the suggestions! Tested this diff. My numbers must be off somewhere in the previous letter, because tuple_field_map_create() took ~2.15 seconds back then. This must be because I took a 19 second profile, instead of a 15 second one, I guess. Anyway, all the comparisons from the previous letter were valid. During this test tuple_field_map_create() took ~ 1.6 seconds. With and without the diff applied. I double-checked it this time. It is a 15 second profile. So looks like splitting by validate doesn't help much. > > ==================== > diff --git a/src/box/tuple_format.c b/src/box/tuple_format.c > index 6c9b2a255..5ee0c4484 100644 > --- a/src/box/tuple_format.c > +++ b/src/box/tuple_format.c > @@ -859,12 +859,38 @@ tuple_format_required_fields_validate(struct tuple_format *format, > > static int > tuple_field_map_create_plain(struct tuple_format *format, const char *tuple, > - bool validate, struct field_map_builder *builder) > + struct field_map_builder *builder) > +{ > + const char *pos = tuple; > + uint32_t defined_field_count = mp_decode_array(&pos); > + defined_field_count = MIN(defined_field_count, > + tuple_format_field_count(format)); > + if (unlikely(defined_field_count == 0)) > + return 0; > + > + struct tuple_field *field; > + struct json_token **token = format->fields.root.children; > + for (uint32_t i = 0; i < defined_field_count; i++, token++, mp_next(&pos)) { > + field = json_tree_entry(*token, struct tuple_field, token); > + if (field->offset_slot != TUPLE_OFFSET_SLOT_NIL && > + field_map_builder_set_slot(builder, field->offset_slot, > + pos - tuple, MULTIKEY_NONE, > + 0, NULL) != 0) { > + return -1; > + } > + } > + return 0; > +} > + > +static int > +tuple_field_map_create_and_validate_plain(struct tuple_format *format, > + const char *tuple, > + struct field_map_builder *builder) > { > struct region *region = &fiber()->gc; > const char *pos = tuple; > uint32_t defined_field_count = mp_decode_array(&pos); > - if (validate && format->exact_field_count > 0 && > + if (format->exact_field_count > 0 && > format->exact_field_count != defined_field_count) { > diag_set(ClientError, ER_EXACT_FIELD_COUNT, > (unsigned) defined_field_count, > @@ -881,28 +907,22 @@ tuple_field_map_create_plain(struct tuple_format *format, const char *tuple, > required_fields = format->required_fields; > goto end; > } > - > - if (validate) { > - required_fields = region_alloc(region, required_fields_sz); > - memcpy(required_fields, format->required_fields, > - required_fields_sz); > - } > + required_fields = region_alloc(region, required_fields_sz); > + memcpy(required_fields, format->required_fields, > + required_fields_sz); > > struct tuple_field *field; > struct json_token **token = format->fields.root.children; > for (uint32_t i = 0; i < defined_field_count; i++, token++, mp_next(&pos)) { > field = json_tree_entry(*token, struct tuple_field, token); > - if (validate) { > - bool nullable = tuple_field_is_nullable(field); > - if(!field_mp_type_is_compatible(field->type, pos, > - nullable)) { > - diag_set(ClientError, ER_FIELD_TYPE, > - tuple_field_path(field), > - field_type_strs[field->type]); > - return -1; > - } > - bit_clear(required_fields, field->id); > + bool nullable = tuple_field_is_nullable(field); > + if(!field_mp_type_is_compatible(field->type, pos, nullable)) { > + diag_set(ClientError, ER_FIELD_TYPE, > + tuple_field_path(field), > + field_type_strs[field->type]); > + return -1; > } > + bit_clear(required_fields, field->id); > if (field->offset_slot != TUPLE_OFFSET_SLOT_NIL && > field_map_builder_set_slot(builder, field->offset_slot, > pos - tuple, MULTIKEY_NONE, > @@ -910,12 +930,9 @@ tuple_field_map_create_plain(struct tuple_format *format, const char *tuple, > return -1; > } > } > - > end: > - return validate ? > - tuple_format_required_fields_validate(format, required_fields, > - required_fields_sz) : > - 0; > + return tuple_format_required_fields_validate(format, required_fields, > + required_fields_sz); > } > > /** @sa declaration for details. */ > @@ -935,8 +952,11 @@ tuple_field_map_create(struct tuple_format *format, const char *tuple, > * tuple field traversal may be simplified. > */ > if (format->fields_depth == 1) { > - return tuple_field_map_create_plain(format, tuple, validate, > - builder); > + if (validate) { > + return tuple_field_map_create_and_validate_plain( > + format, tuple, builder); > + } > + return tuple_field_map_create_plain(format, tuple, builder); > } > > uint32_t field_count; -- Serge Petrenko
next prev parent reply other threads:[~2020-12-02 9:53 UTC|newest] Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-11-14 17:28 [Tarantool-patches] [PATCH 0/2] reduce performance degradation introduced by JSON path indices Serge Petrenko 2020-11-14 17:28 ` [Tarantool-patches] [PATCH 1/2] box: speed up tuple_field_map_create Serge Petrenko 2020-11-14 18:00 ` Cyrill Gorcunov 2020-11-16 7:34 ` Serge Petrenko 2020-11-20 23:26 ` Vladislav Shpilevoy 2020-11-23 13:50 ` Serge Petrenko 2020-11-24 22:33 ` Vladislav Shpilevoy 2020-12-01 8:48 ` Serge Petrenko 2020-12-01 22:04 ` Vladislav Shpilevoy 2020-12-02 9:53 ` Serge Petrenko [this message] 2020-11-14 17:28 ` [Tarantool-patches] [PATCH 2/2] box: use tuple_field_raw_by_part where possible Serge Petrenko 2020-11-20 23:26 ` Vladislav Shpilevoy 2020-11-23 13:51 ` Serge Petrenko 2020-11-24 22:33 ` Vladislav Shpilevoy 2020-12-01 8:48 ` Serge Petrenko 2020-12-01 22:04 ` Vladislav Shpilevoy 2020-11-16 7:50 ` [Tarantool-patches] [PATCH 0/2] reduce performance degradation introduced by JSON path indices Serge Petrenko
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=f506f4fd-c7a9-865c-2a66-dc860fa2c606@tarantool.org \ --to=sergepetrenko@tarantool.org \ --cc=korablev@tarantool.org \ --cc=tarantool-patches@dev.tarantool.org \ --cc=v.shpilevoy@tarantool.org \ --subject='Re: [Tarantool-patches] [PATCH 1/2] box: speed up tuple_field_map_create' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox