-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Avoid computing strlen() inside loops #16584
Conversation
Compiling with -O0 (no proper optimizations), strlen() call in loops for comparing the size, isn't being called/initialized before the actual loop gets started, which causes n-numbers of strlen() calls (as long as the string is). Keeping the length before entering in the loop is a good idea. On some places, even with -O2, both GCC and Clang can't recognize this pattern, which seem to happen in an array of char pointer. Signed-off-by: rilysh <nightquick@proton.me>
Since zvol_name was modified, we need to compute the length again. Signed-off-by: rilysh <nightquick@proton.me>
cmd/zdb/zdb.c
Outdated
@@ -8816,7 +8816,7 @@ zdb_read_block(char *thing, spa_t *spa) | |||
for (s = strtok_r(flagstr, ":", &tmp); | |||
s != NULL; | |||
s = strtok_r(NULL, ":", &tmp)) { | |||
for (i = 0; i < strlen(flagstr); i++) { | |||
for (i = 0, len = strlen(flagstr); i < len; i++) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this strlen()
before the if
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
e.g. like this?
len = strlen(flagstr);
for (i = 0; i < len; i++)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I do like compact code, but not by the cost of readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What really looks odd to me though, unrelated to this commit, is that flagstr
is used inside the strtok_r()
loop, while token's cut by it (s
) is not. Does this code actually work as intended, whatever it supposed to do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried with a small example, this portion looks a little bit hacky
#include <stdio.h>
#include <string.h>
int main(void)
{
char *flag, *tmp;
char *s, *tok;
s = "hello:world:s:this:world";
flag = strdup(s ? s : "");
tmp = NULL;
for (s = strtok_r(flag, ":", &tmp); s != NULL;
s = strtok_r(NULL, ":", &tmp)) {
fprintf(stdout, "len: %zu\n", strlen(flag));
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks "a little bit" broken. But I have no idea what it supposed to do, just suspect not this.
Signed-off-by: rilysh <nightquick@proton.me>
TIL: for loops work different than I thought for the past 20 years Sorry guys to spam as it likely doesn't belong here - but as I just found this: Java suffers from the same problem!
Until this here I always thought the computation of the strings length is done once - wrote this test code and got surprised: Nope! It's executed every single time! Both codes produce the same output:
I started learning Java roughly 20 years ago (plus/minus) - and in the book I used (no, it was not Head First Java) this style was all over the place. Wonder if the books author ever learned about that. Anyway - @rilysh nice catch! |
@n0xena |
@amotin Thanks for the explanation. 👍 |
Compiling with -O0 (no proper optimizations), strlen() call in loops for comparing the size, isn't being called/initialized before the actual loop gets started, which causes n-numbers of strlen() calls (as long as the string is). Keeping the length before entering in the loop is a good idea. On some places, even with -O2, both GCC and Clang can't recognize this pattern, which seem to happen in an array of char pointer. Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Alexander Motin <mav@FreeBSD.org> Signed-off-by: rilysh <nightquick@proton.me> Closes openzfs#16584
Description
Compiling with -O0 (no proper optimizations), strlen() call in loops for comparing the size, isn't being called/initialized before the actual loop gets started, which causes n-numbers of strlen() calls (as long as the string is). Keeping the length before entering in the loop is a good idea.
On some places, even with -O2, both GCC and Clang can't recognize this pattern, which seem to happen in an array of char pointer.
Out of this context, on some places, 32-bit int is used to store the length of a given string, which implicitly casts
strlen()
result to an int. I haven't made any changes to this.How Has This Been Tested?
Not yet tested.
Types of changes
Checklist:
Signed-off-by
.