Skip to content

Enhance moving PHP code pages into huge pages #12806

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

Merged
merged 1 commit into from
Nov 29, 2023

Conversation

PeterYang12
Copy link
Contributor

The former implementation of huge pages for PHP code segments may fail to map in certain scenarios. For instance, if the initial 'r-x-' segment is not PHP, it will result in a failure to map into huge pages. Consequently, the optimization for huge pages with PHP code will no longer be effective.

This patch improves the implementation by accurately matching all 'r-x-' segments until it locates the PHP code segment. Subsequently, it performs the necessary huge page mapping.

Signed-off-by: PeterYang12 yuhan.yang@intel.com
Reviewed-by: chen-hu-97 hu1.chen@intel.com

@PeterYang12
Copy link
Contributor Author

For example:
If use this command to start php-fpm /lib64/ld-linux-x86-64.so.2 /usr/local/sbin/php-fpm , the older implementation for huge pages will not take effect.
ld-linux-x86-64.so.2 will pack all the binaries into 4GB memories, like this:

7ffff336c000-7ffff33ec000 rwxp 00000000 00:00 0
...
7ffff3451000-7ffff3454000 r--p 00000000 00:d8 18389528                   /lib/x86_64-linux-gnu/libnss_files-2.28.so
7ffff3454000-7ffff345b000 r-xp 00003000 00:d8 18389528                   /lib/x86_64-linux-gnu/libnss_files-2.28.so
...
7ffff6746000-7ffff6836000 r--p 00000000 00:d8 32576869                   /usr/local/sbin/php-fpm
7ffff6836000-7ffff6946000 ---p 000f0000 00:d8 32576869                   /usr/local/sbin/php-fpm
7ffff6946000-7ffff6c88000 r-xp 00200000 00:d8 32576869                   /usr/local/sbin/php-fpm
7ffff6c88000-7ffff6d46000 ---p 00542000 00:d8 32576869                   /usr/local/sbin/php-fpm
...
7ffff7ffe000-7ffff81fc000 rw-p 00000000 00:00 0                          [heap]
7ffff81fc000-7ffff8256000 rw-p 00000000 00:00 0                          [heap]

@PeterYang12
Copy link
Contributor Author

This patch should fix #12807

Copy link
Member

@dstogov dstogov left a comment

Choose a reason for hiding this comment

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

The patch looks good. Only minor changes requested and few minor questions.

Comment on lines 3027 to 3028
if (ret >= 6) {
if (name[0] == '[') {
Copy link
Member

Choose a reason for hiding this comment

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

In sscanf() reads 6 arguments value of name may be undefined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same reason above. The name value in /proc/self/maps may be empty, I use >=6 to do the judgement.

Copy link
Member

Choose a reason for hiding this comment

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

The fact that name value in /ptoc/self/maps is empty doesn't mean that the value of variable name becomes empty. If scanf() processed only 6 variables, the value of name is undefined (most probably unchanged).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry for my wrong explanation. In the codes, scanf() will processe 7 variables:

ret=sscanf(buffer, "%lx-%lx %4s %lx %9s %lu %s\n", &start, &end, perm, &offset, dev, &inode, name);

If the name in maps is empty, it only return 6 but not 7.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, but the code below checks variable name even if ret == 6. I suppose lines without name should be skipped.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK. Changed the codes and still use ret==7 to do the judgement. Thank you~

ret = sscanf(buffer, "%lx-%lx %4s %lx %9s %lu %s\n", &start, &end, perm, &offset, dev, &inode, name);
if (ret >= 6) {
if (name[0] == '[') {
// meet heap segment, should break out.
Copy link
Member

Choose a reason for hiding this comment

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

Why do you stop on [heap] segment?
We stop on program code segment, but I'm not sure if [heap] may be placed before it.

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 saw most of the maps, [heap] segment is under program code segment in maps. So I suppose if met heap, the huge page mapping operation should break . Do you think it's unnecessary?

Copy link
Member

Choose a reason for hiding this comment

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

I think, it's better to remove this. It's not a problem to scan until the end of the file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you. I will remove this.

Comment on lines 3032 to 3035
if (perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/') {
long unsigned int seg_start = ZEND_MM_ALIGNED_SIZE_EX(start, huge_page_size);
long unsigned int seg_end = (end & ~(huge_page_size-1L));
long unsigned int real_end;

ret = fscanf(f, "%lx-", &start);
if (ret == 1 && start == seg_end + huge_page_size) {
real_end = end;
seg_end = start;
} else {
real_end = seg_end;
}
char *is_substring = strstr(name, __progname);
// try to find the php text segment and map it into huge pages
if (is_substring != NULL) {
Copy link
Member

Choose a reason for hiding this comment

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

Can you please minimize the diff avoiding unnecessary indentation changes.

-				if (perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/') {
+				if (perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/'
+				 && strstr(name, __progname) != NULL) {
      ... (the rest seems unchanged)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, thank you for your review. :)

@PeterYang12 PeterYang12 force-pushed the enhance-hugepage-for-php-text branch 2 times, most recently from 02d60f7 to 562fcaf Compare November 28, 2023 10:16
Comment on lines 3027 to 3030
if (ret == 7) {
if (perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/') {
// try to find the php text segment and map it into huge pages
char *is_substring = strstr(name, __progname);
if (perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/' && is_substring != NULL) {
Copy link
Member

Choose a reason for hiding this comment

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

I would rewrite this like

if (ret >= 6) {
    if (ret > 6
     && perm[0] == 'r' && perm[1] == '-' && perm[2] == 'x' && name[0] == '/'
     && strstr(name, __progname)) {
  • lines without "name" are going to be skipped and won't stop the search
  • strstr() call is going to be performed only after the cheaper checks

Copy link
Contributor Author

@PeterYang12 PeterYang12 Nov 29, 2023

Choose a reason for hiding this comment

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

Done. Thank you for your kindness help~

The former implementation of huge pages for PHP code segments may
fail to map in certain scenarios. For instance, if the initial
'r-x-' segment is not PHP, it will result in a failure to map into
huge pages. Consequently, the optimization for huge pages with PHP
code will no longer be effective.

This patch improves the implementation by accurately matching all
'r-x-' segments until it locates the PHP code segment. Subsequently,
it performs the necessary huge page mapping.

Signed-off-by: PeterYang12 <yuhan.yang@intel.com>
Reviewed-by: chen-hu-97 <hu1.chen@intel.com>
@PeterYang12 PeterYang12 force-pushed the enhance-hugepage-for-php-text branch from 562fcaf to ced9c52 Compare November 29, 2023 01:28
@dstogov dstogov merged commit 566100d into php:master Nov 29, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants