Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Faster manager_process_barrier_fd and drop message if BARRIER=1 found #15660

Merged
merged 3 commits into from May 14, 2020

Conversation

benjarobin
Copy link
Contributor

@benjarobin benjarobin commented May 1, 2020

  • This function is called for each message, and almost all of them will not
    contain BARRIER=1. So 5 comparaisons are realized in previous code. Now the buffer is
    parsed only once.

  • If BARRIER=1 is found, drop the message in all case. So always return true
    when BARRIER=1 is found at the beginning of a new line

Follow up of #15547

@poettering poettering added needs-discussion 🤔 reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks labels May 5, 2020
Indicates that the tags list cannot be modified by notify_message function.
Since the tags list is created only once for multiple call to
notify_message functions.
@benjarobin
Copy link
Contributor Author

@poettering This is a complete rewrite of the previous MR. I hope you will like the idea.

@@ -106,7 +106,7 @@ bool strv_overlap(char * const *a, char * const *b) _pure_;

#define STRV_FOREACH_BACKWARDS(s, l) \
for (s = ({ \
char **_l = l; \
typeof(l) _l = l; \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, this is a good idea

@@ -3894,19 +3894,19 @@ static void service_force_watchdog(Service *s) {
static void service_notify_message(
Unit *u,
const struct ucred *ucred,
char **tags,
char * const *tags,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we mostly gave up on using const on arrays of strings, since the semantics of that are so fucked in C. but i guess it doesn't hurt if it works here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have tried to had a few const at some place, I quickly forget about it. And yes I am agree this part in the C language is "not perfect".


buf = strv_join(tags, ", ");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs oom check. i mean, if we actually hit oom it might be fine to ignore it, given this is about debug logging only, but we shouldn't pass NULL to ellipsize() in that case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I choose to do the same things that with the output of ellipsize, ignore it.

if (fdset_size(fds) != 1)
log_warning("Got incorrect number of fds with BARRIER=1, closing them.");
if (strv_contains(tags, "BARRIER=1")) {
if (strv_length(tags) == 1) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you iterate through the array twice here. maybe:

if (strv_equal(tags, STRV_MAKE("BARRIER=1")) {
        …
} else if (strv_contains(tags, "BARRIER=1")) {
        …
}

that way you iterate through the array only once.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the reception of "BARRIER=1" is less frequent (currently nobody uses it, but statically, it will always be less frequent), we can write it in the reverse way:

        if (strv_contains(tags, "BARRIER=1")) {
                if (strv_equal(tags, STRV_MAKE("BARRIER=1")) {

But technically strv_length is very cheap, and faster than strv_equal() (Just iterating on a array costs less than a string compare).
So even if there is a slight improvement, I do not think that it is easier to read.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If somebody really care about performance, (strv_length(tags) == 1) can be replaced (in this specific case) by (tags[1] == NULL)
But I don't think this is necessary

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

strv_equal() is O(1) time in this case where the second argument is literal, it's hard to beat that.

@poettering
Copy link
Member

i very much like the idea of converting this earlier into an an array of strings, btw!

 - Parse the tags list using strv_split_newlines() which remove any
   unnecessary empty string at the end of the strv.
 - Use this parsed list for manager_process_barrier_fd() and every call
   to manager_invoke_notify_message().
 - This also allow to simplify the manager_process_barrier_fd() function.
@benjarobin
Copy link
Contributor Author

@poettering Force pushed, add a check on strv_join() return value

@poettering poettering merged commit 3250501 into systemd:master May 14, 2020
@benjarobin benjarobin deleted the perf_barrier_fd branch May 23, 2020 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pid1 reviewed/needs-rework 🔨 PR has been reviewed and needs another round of reworks
Development

Successfully merging this pull request may close these issues.

None yet

3 participants