-
Notifications
You must be signed in to change notification settings - Fork 7.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 a lot of string copies in ext-phar #17240
Conversation
2eb848a
to
561401c
Compare
Feel free to merge the first commit already. |
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 left some initial comments :)
if (phar_metadata_tracker_has_data(&entry->phar->metadata_tracker, entry->phar->is_persistent)) { | ||
efree(metadata); | ||
return FAILURE; | ||
} | ||
entry->phar->metadata_tracker = entry->metadata_tracker; | ||
entry->metadata_tracker.str = NULL; | ||
ZVAL_UNDEF(&entry->metadata_tracker.val); | ||
} else if (entry->filename_len >= sizeof(".phar/.metadata/") + sizeof("/.metadata.bin") - 1 && NULL != (mentry = zend_hash_str_find_ptr(&(entry->phar->manifest), entry->filename + sizeof(".phar/.metadata/") - 1, entry->filename_len - (sizeof("/.metadata.bin") - 1 + sizeof(".phar/.metadata/") - 1)))) { | ||
} else if (ZSTR_LEN(entry->filename) >= sizeof(".phar/.metadata/") + sizeof("/.metadata.bin") - 1 && NULL != (mentry = zend_hash_str_find_ptr(&entry->phar->manifest, ZSTR_VAL(entry->filename) + sizeof(".phar/.metadata/") - 1, ZSTR_LEN(entry->filename) - (sizeof("/.metadata.bin") - 1 + sizeof(".phar/.metadata/") - 1)))) { |
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.
Can you use zend_string_starts_with_literal
here?
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.
No, this is a hash lookup
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.
same comment as the previous one regarding the leading/trailing /
ext/phar/tar.c
Outdated
if (entry->filename_len >= sizeof(".phar/.metadata") && !memcmp(entry->filename, ".phar/.metadata", sizeof(".phar/.metadata")-1)) { | ||
if (entry->filename_len == sizeof(".phar/.metadata.bin")-1 && !memcmp(entry->filename, ".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1)) { | ||
if (ZSTR_LEN(entry->filename) >= sizeof(".phar/.metadata") && !memcmp(ZSTR_VAL(entry->filename), ".phar/.metadata", sizeof(".phar/.metadata")-1)) { | ||
if (ZSTR_LEN(entry->filename) == sizeof(".phar/.metadata.bin")-1 && !memcmp(ZSTR_VAL(entry->filename), ".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1)) { | ||
return phar_tar_setmetadata(&entry->phar->metadata_tracker, entry, error); | ||
} | ||
/* search for the file this metadata entry references */ | ||
if (entry->filename_len >= sizeof(".phar/.metadata/") + sizeof("/.metadata.bin") - 1 && !zend_hash_str_exists(&(entry->phar->manifest), entry->filename + sizeof(".phar/.metadata/") - 1, entry->filename_len - (sizeof("/.metadata.bin") - 1 + sizeof(".phar/.metadata/") - 1))) { | ||
if (ZSTR_LEN(entry->filename) >= sizeof(".phar/.metadata/") + sizeof("/.metadata.bin") - 1 && !zend_hash_str_exists(&entry->phar->manifest, ZSTR_VAL(entry->filename) + sizeof(".phar/.metadata/") - 1, ZSTR_LEN(entry->filename) - (sizeof("/.metadata.bin") - 1 + sizeof(".phar/.metadata/") - 1))) { |
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.
Ditto zend string equals/start with APIs?
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.
No, this is a hash lookup
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.
Okay, this is confusing, also isn't there a bug with:
ZSTR_LEN(entry->filename) >= sizeof(".phar/.metadata/") + sizeof("/.metadata.bin") - 1
as it has the /
both as a trailing and leading character?
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.
No, I believe this is for: .phar/.metadata/FILENAME_HERE/.metadata.bin
in which case it makes sense. And the fact that we only do -1
instead of -2
for the 2 sizeof
s is because it enforces that FILENAME_HERE
is >= 1 character in size.
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.
Okay, this is really unintuitive >.> but nothing new with Phar
@@ -1133,13 +1124,13 @@ void phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_def | |||
} else { | |||
phar_entry_info newentry = {0}; | |||
|
|||
newentry.filename = estrndup(".phar/.metadata.bin", sizeof(".phar/.metadata.bin")-1); | |||
newentry.filename_len = sizeof(".phar/.metadata.bin")-1; | |||
newentry.filename = ZSTR_INIT_LITERAL(".phar/.metadata.bin", false); |
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.
Is it possible to intern those at startup of the extension? (Obviously for a future PR)
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.
We could
The contents of the string are copied many times, especially in hash tables. Avoid all this work by using zend_string in the first place.
e172bc2
to
f079964
Compare
do you expect this will have a positive impact on .phar based CLI applications, e.g. PHPStan in some form? |
no |
@Girgias as promised I made a final pass over the PR to look for lifetime mistakes and I think it's okay. |
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.
Okay did a complete pass, only one main comment
entry.is_dir = 1; | ||
if(entry.filename_len > 1) { | ||
entry.filename_len--; | ||
if(filename_len > 1) { |
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.
Tiny nit which could be done at the same time as editing this line
if(filename_len > 1) { | |
if (filename_len > 1) { |
This is only the first batch, but it's large enough already to warrant its own PR.