Tarantool development patches archive
 help / color / mirror / Atom feed
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: Tue, 1 Dec 2020 11:48:44 +0300	[thread overview]
Message-ID: <301e2d4d-3534-d03e-4dec-84c72d4c351d@tarantool.org> (raw)
In-Reply-To: <9eba270a-c0fb-3238-bc2e-2e39fe73eb91@tarantool.org>


25.11.2020 01:33, Vladislav Shpilevoy пишет:
>
>> ```
>> diff --git a/src/box/tuple_format.c b/src/box/tuple_format.c
>> index d8656aa26..6c9b2a255 100644
>> --- a/src/box/tuple_format.c
>> +++ b/src/box/tuple_format.c
>> @@ -888,17 +888,10 @@ tuple_field_map_create_plain(struct tuple_format *format, const char *tuple,
>>                         required_fields_sz);
>>          }
>>
>> -       struct json_token token = {
>> -               .type = JSON_TOKEN_NUM,
>> -               .num = 0,
>> -       };
>>          struct tuple_field *field;
>> -
>> -       for (uint32_t i = 0; i < defined_field_count; i++, mp_next(&pos)) {
>> -               token.num = i;
>> -               field = json_tree_lookup_entry(&format->fields,
>> - &format->fields.root, &token,
>> -                                              struct tuple_field, token);
>> +       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,
>> ```
>>
>>
>> I actually profiled my original patch and the version with this diff applied:
>>
>>
>> This diff reduces time taken by tuple_field_map_create from 2.12 seconds
>> to 1.69 seconds. 1.10 still has the best time: 1.31 seconds.
>> Just for comparison, current 2.x takes 6.1 seconds for the same amount of
>> tuple_field_map_create calls.
> Hm. That looks too much. json_tree_lookup_entry() is sure slower than a
> direct access, but why so much slower? It calls json_tree_lookup, which
> checks token type, which is num, and then it does the same as you in the
> diff above. So it is just +2 ifs, not counting the 'unlikely' multikey
> check. Does a couple of ifs slow down the code so heavily?

I suppose we should count all ifs. likely/unlikely shouldn't make any 
difference
after some iterations, the branch predictor should already learn and guess
correctly every time.  and we have ~30 mil iteratiions in this test.
So there's +3 ifs in a cycle (just +3 instructions, without any branch 
misprediction).


> Maybe the inlining was too aggressive, and we washed out the instruction
> cache? Don't know how to check it properly. Just out of curiosity, what
> if we move json_tree_lookup to json.c, and field_map_builder_set_slot
> to field_map.c? And maybe field_mp_type_is_compatible to field_def.c.
tuple_field_map_create time with everything moved to *.c: 2.44 s
field_mp_type_is_compatible inlined, everything elese in *.c: 2.8 s
only json_tree_lookup moved to json.c: 2.21 s
everything inlined: 2.12 s

> If it won't change anything, then probably just 2 ifs really matter that
> much.
>
>> I'm starting to like this variant more. Anyway, I'm not applying this diff
>> until your ack.
> Looks fine. Just don't understand why so big difference for such a simple
> change.


These 3 ifs are a noticeable portion of all the instructions inside the 
loop. Why not?

The diff applied.

> 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.

Is this possible that compiler already evaluates `validate`?

The diff, just in case.

=============================================

diff --git a/src/box/tuple_format.c b/src/box/tuple_format.c
index d8656aa26..14e3984b2 100644
--- a/src/box/tuple_format.c
+++ b/src/box/tuple_format.c
@@ -857,7 +857,7 @@ tuple_format_required_fields_validate(struct 
tuple_format *format,
                                       void *required_fields,
                                       uint32_t required_fields_sz);

-static int
+static inline int
  tuple_field_map_create_plain(struct tuple_format *format, const char 
*tuple,
                              bool validate, struct field_map_builder 
*builder)
  {
@@ -925,10 +925,9 @@ end:
                0;
  }

-/** @sa declaration for details. */
-int
-tuple_field_map_create(struct tuple_format *format, const char *tuple,
-                      bool validate, struct field_map_builder *builder)
+static inline int
+tuple_field_map_create_impl(struct tuple_format *format, const char *tuple,
+                           bool validate, struct field_map_builder 
*builder)
  {
         struct region *region = &fiber()->gc;
         if (field_map_builder_create(builder, format->field_map_size,
@@ -966,6 +965,20 @@ tuple_field_map_create(struct tuple_format *format, 
const char *tuple,
         return entry.data == NULL ? 0 : -1;
  }

+int
+tuple_field_map_create(struct tuple_format *format, const char *tuple,
+                      struct field_map_builder *builder)
+{
+       return tuple_field_map_create_impl(format, tuple, true, builder);
+}
+
+int
+tuple_field_map_create_unchecked(struct tuple_format *format, const 
char *tuple,
+                                struct field_map_builder *builder)
+{
+       return tuple_field_map_create_impl(format, tuple, false, builder);
+}
+
  uint32_t
  tuple_format_min_field_count(struct key_def * const *keys, uint16_t 
key_count,
                              const struct field_def *space_fields,


> We could also template tuple_field_raw_by_path, because tuple_field_raw
> always passes NULL path and NULL offset_slot_hint.


Yes, this should also help.


-- 
Serge Petrenko

  reply	other threads:[~2020-12-01  8:48 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 [this message]
2020-12-01 22:04           ` Vladislav Shpilevoy
2020-12-02  9:53             ` Serge Petrenko
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=301e2d4d-3534-d03e-4dec-84c72d4c351d@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