From: Alan Maguire <alan.maguire@oracle.com>
To: Jiri Olsa <olsajiri@gmail.com>
Cc: acme@kernel.org, dwarves@vger.kernel.org, eddyz87@gmail.com,
shung-hsi.yu@suse.com, jirislaby@kernel.org
Subject: Re: [PATCH v2 dwarves 1/3] btf_encoder: record BTF-centric function state instead of DWARF-centric
Date: Tue, 24 Sep 2024 15:40:03 +0100 [thread overview]
Message-ID: <09440a31-5f04-4c66-bcfe-0a11c128dad3@oracle.com> (raw)
In-Reply-To: <ZvF5AdxV-8chJXgp@krava>
On 23/09/2024 15:19, Jiri Olsa wrote:
> On Mon, Sep 16, 2024 at 02:49:44PM +0100, Alan Maguire wrote:
>
> SNIP
>
>> Baseline
>>
>> $ time pahole -J vmlinux -j1 --btf_features=default
>>
>> real 0m17.268s
>> user 0m15.808s
>> sys 0m1.415s
>>
>> $ time pahole -J vmlinux -j8 --btf_features=default
>>
>> real 0m10.768s
>> user 0m30.793s
>> sys 0m4.199s
>>
>> With these changes:
>>
>> $ time pahole -J vmlinux -j1 --btf_features=default
>>
>> real 0m16.564s
>> user 0m16.029s
>> sys 0m0.492s
>>
>> $ time pahole -J vmlinux -j8 --btf_features=default
>>
>> real 0m8.332s
>> user 0m30.627s
>> sys 0m0.714s
>>
>> In terms of functions encoded, 360 fewer functions make it into
>> BTF due to the different approach in consistency checking, but after
>> examining these cases, they do appear to be legitimately inconsistent
>> functions where the optimized versions have parameter mismatches
>> with the non-optimized expectations.
>>
>> Mileage may vary of course, and any testing folks could do would
>> be greatly appreciated!
>
> looks good, some comments below.. I was hoping to find some way
> to split the change, but can't think of any ;-)
>
thanks for trying it out and looking at the code Jiri! Replies below..
> thanks,
> jirka
>
>
> SNIP
>
>> -static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct ftype *ftype)
>> +static int32_t btf_encoder__add_func_proto(struct btf_encoder *encoder, struct ftype *ftype, struct elf_function *func)
>> {
>> struct btf *btf = encoder->btf;
>> const struct btf_type *t;
>> struct parameter *param;
>> uint16_t nr_params, param_idx;
>> int32_t id, type_id;
>> + char tmp_name[KSYM_NAME_LEN];
>> + const char *name;
>> + struct btf_encoder_func_state *state = &func->state;
>
> func could be NULL right?
>
good catch; I've moved the assignment to the code that deals with ELF
function prototype addition.
> SNIP
>
>> static int32_t btf_encoder__save_func(struct btf_encoder *encoder, struct function *fn, struct elf_function *func)
>> {
>> - fn->priv = encoder->cu;
>> - if (func->function) {
>> - struct function *existing = func->function;
>> -
>> - /* If saving and we find an existing entry, we want to merge
>> - * observations across both functions, checking that the
>> - * "seen optimized parameters", "inconsistent prototype"
>> - * and "unexpected register" status is reflected in the
>> - * the func entry.
>> - * If the entry is new, record encoder state required
>> - * to add the local function later (encoder + type_id_off)
>> - * such that we can add the function later.
>> - */
>> - existing->proto.optimized_parms |= fn->proto.optimized_parms;
>> - existing->proto.unexpected_reg |= fn->proto.unexpected_reg;
>> - if (!existing->proto.unexpected_reg && !existing->proto.inconsistent_proto &&
>> - !funcs__match(encoder, func, fn))
>> - existing->proto.inconsistent_proto = 1;
>> - } else {
>> - func->state.type_id_off = encoder->type_id_off;
>> - func->function = fn;
>> - encoder->cu->functions_saved++;
>
> we could remove functions_saved from cu now?
>
good idea; removed that and the "processed" flag from ftypes.
> SNIP
>
>> -static int32_t btf_encoder__add_func(struct btf_encoder *encoder, struct function *fn)
>> +static int32_t btf_encoder__add_func(struct btf_encoder *encoder, struct function *fn, struct elf_function *func)
>> {
>> - int btf_fnproto_id, btf_fn_id, tag_type_id;
>> - struct llvm_annotation *annot;
>> + int btf_fnproto_id, btf_fn_id, tag_type_id = 0;
>> + int16_t component_idx = -1;
>> const char *name;
>> + const char *value;
>> + char tmp_value[KSYM_NAME_LEN];
>>
>> - btf_fnproto_id = btf_encoder__add_func_proto(encoder, &fn->proto);
>> - name = function__name(fn);
>> - btf_fn_id = btf_encoder__add_ref_type(encoder, BTF_KIND_FUNC, btf_fnproto_id, name, false);
>> + btf_fnproto_id = btf_encoder__add_func_proto(encoder, fn ? &fn->proto : NULL, func);
>> + name = func->alias ?: func->name;
>> + if (btf_fnproto_id >= 0)
>> + btf_fn_id = btf_encoder__add_ref_type(encoder, BTF_KIND_FUNC, btf_fnproto_id, name, false);
>> if (btf_fnproto_id < 0 || btf_fn_id < 0) {
>> - printf("error: failed to encode function '%s'\n", function__name(fn));
>> + printf("error: failed to encode function '%s': invalid %s\n", name, btf_fnproto_id < 0 ? "proto" : "func");
>> return -1;
>> }
>> - list_for_each_entry(annot, &fn->annots, node) {
>> - tag_type_id = btf_encoder__add_decl_tag(encoder, annot->value, btf_fn_id,
>> - annot->component_idx);
>> - if (tag_type_id < 0) {
>> - fprintf(stderr, "error: failed to encode tag '%s' to func %s with component_idx %d\n",
>> - annot->value, name, annot->component_idx);
>> - return -1;
>> + if (!fn) {
>> + struct btf_encoder_func_state *state = &func->state;
>> + uint16_t idx;
>> +
>> + if (!state || state->nr_annots == 0)
>
> it probably can't happen, but state will be allways != NULL in here.. should it be:
>
> if (!func || state->nr_annots == 0)
>
I've added assert()s to the btf_encoder__add_func[proto]() functions to
ensure that either the fn or func are non-NULL, since winding up with a
NULL fn/func is more of a programming error than a state we can wind up
in.
>
>> + return 0;
>> +
>> + for (idx = 0; idx < state->nr_annots; idx++) {
>> + struct btf_encoder_func_annot *a = &state->annots[idx];
>> +
>> + value = btf__str_by_offset(encoder->btf, a->value);
>> + /* adding BTF data may result in a mode of the
>> + * value string memory, so make a temporary copy.
>> + */
>> + strncpy(tmp_value, value, sizeof(tmp_value));
>> + component_idx = a->component_idx;
>> +
>> + tag_type_id = btf_encoder__add_decl_tag(encoder, tmp_value, btf_fn_id, component_idx);
>> + if (tag_type_id < 0)
>> + break;
>> + }
>> + } else {
>> + struct llvm_annotation *annot;
>> +
>> + list_for_each_entry(annot, &fn->annots, node) {
>> + value = annot->value;
>> + component_idx = annot->component_idx;
>> +
>> + tag_type_id = btf_encoder__add_decl_tag(encoder, value, btf_fn_id,
>> + component_idx);
>> + if (tag_type_id < 0)
>> + break;
>> }
>> }
>> + if (tag_type_id < 0) {
>> + fprintf(stderr, "error: failed to encode tag '%s' to func %s with component_idx %d\n",
>> + value, name, component_idx);
>> + return -1;
>> + }
>> +
>> return 0;
>> }
>>
>> -static void btf_encoder__add_saved_funcs(struct btf_encoder *encoder)
>> +static int btf_encoder__add_saved_funcs(struct btf_encoder *encoder)
>> {
>> int i;
>>
>> for (i = 0; i < encoder->functions.cnt; i++) {
>> struct elf_function *func = &encoder->functions.entries[i];
>> - struct function *fn = func->function;
>> - struct btf_encoder *other_encoder;
>> + struct btf_encoder_func_state *state = &func->state;
>> + struct btf_encoder *other_encoder = NULL;
>>
>> - if (!fn || fn->proto.processed)
>> + if (!state || !state->initialized || state->processed)
>> continue;
>
> state is now placed directly in elf_function so will allways be state != NULL
>
>> -
>> /* merge optimized-out status across encoders; since each
>> * encoder has the same elf symbol table we can use the
>> * same index to access the same elf symbol.
>> */
>> btf_encoders__for_each_encoder(other_encoder) {
>> - struct function *other_fn;
>> + struct elf_function *other_func;
>> + struct btf_encoder_func_state *other_state;
>> + uint8_t optimized, unexpected, inconsistent;
>>
>> if (other_encoder == encoder)
>> continue;
>>
>> - other_fn = other_encoder->functions.entries[i].function;
>> - if (!other_fn)
>> + other_func = &other_encoder->functions.entries[i];
>> + other_state = &other_func->state;
>> + if (!other_state)
>> continue;
>
> same as above it will allways be other_state != NULL
>
both fixed now. thanks!
>> - fn->proto.optimized_parms |= other_fn->proto.optimized_parms;
>> - fn->proto.unexpected_reg |= other_fn->proto.unexpected_reg;
>> - if (other_fn->proto.inconsistent_proto)
>> - fn->proto.inconsistent_proto = 1;
>> - if (!fn->proto.unexpected_reg && !fn->proto.inconsistent_proto &&
>> - !funcs__match(encoder, func, other_fn))
>> - fn->proto.inconsistent_proto = 1;
>> - other_fn->proto.processed = 1;
>> + optimized = state->optimized_parms | other_state->optimized_parms;
>> + unexpected = state->unexpected_reg | other_state->unexpected_reg;
>> + inconsistent = state->inconsistent_proto | other_state->inconsistent_proto;
>> + if (!unexpected && !inconsistent &&
>> + !funcs__match(encoder, func,
>> + encoder->btf, state,
>> + other_encoder->btf, other_state))
>> + inconsistent = 1;
>> + state->optimized_parms = other_state->optimized_parms = optimized;
>> + state->unexpected_reg = other_state->unexpected_reg = unexpected;
>> + state->inconsistent_proto = other_state->inconsistent_proto = inconsistent;
>> +
>> + other_state->processed = 1;
>
> SNIP
next prev parent reply other threads:[~2024-09-24 14:40 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-16 13:49 [PATCH v2 dwarves 0/3] reduce memory overhead of BTF encoding Alan Maguire
2024-09-16 13:49 ` [PATCH v2 dwarves 1/3] btf_encoder: record BTF-centric function state instead of DWARF-centric Alan Maguire
2024-09-20 19:18 ` Eduard Zingerman
2024-09-24 14:31 ` Alan Maguire
2024-09-24 19:02 ` Ihor Solodrai
2024-09-24 19:10 ` Eduard Zingerman
2024-09-23 14:19 ` Jiri Olsa
2024-09-24 14:40 ` Alan Maguire [this message]
2024-09-16 13:49 ` [PATCH v2 dwarves 2/3] pfunct: show all functions that match filter criteria Alan Maguire
2024-09-16 13:49 ` [PATCH v2 dwarves 3/3] tests: add test validating BTF encoding, reasons we skip functions Alan Maguire
2024-09-18 8:41 ` Arnaldo Carvalho de Melo
2024-09-25 9:27 ` Alan Maguire
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=09440a31-5f04-4c66-bcfe-0a11c128dad3@oracle.com \
--to=alan.maguire@oracle.com \
--cc=acme@kernel.org \
--cc=dwarves@vger.kernel.org \
--cc=eddyz87@gmail.com \
--cc=jirislaby@kernel.org \
--cc=olsajiri@gmail.com \
--cc=shung-hsi.yu@suse.com \
/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
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox