Skip to main content
Topic: site slow (Read 9573 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Re: site slow

Reply #15

I have disabled hostname lookup. Let's see if it fixes the delay..
Thorsten "TE" Eurich
------------------------

Re: site slow

Reply #16

Not to jinx us, but since you turned that off I have not had a slowdown ... interesting !

Re: site slow

Reply #17

I haven't had any issues after that was turned off.

Re: site slow

Reply #18

Quote from: Spuds – Not to jinx us, but since you turned that off I have not had a slowdown ... interesting !
hostname lookup is cached for 600 seconds, that's why the first request ( most likely not cached) is soo slow. After a quick check the related function host_from_ip() in Subs.php checks:
Code: [Select]
@shell_exec('host...
then
Code: [Select]
@shell_exec('nslookup...
then
Code: [Select]
@gethostbyaddr(...
I'd bet that both shell_exec calls fail.. Maybe should we switch the order of hostname lookups and start with the gethostbyaddr() ?
Thorsten "TE" Eurich
------------------------

Re: site slow

Reply #19

Quote from: TE – I'd bet that both shell_exec calls fail.. Maybe should we switch the order of hostname lookups and start with the gethostbyaddr() ?

I will try this as well.

 

Re: site slow

Reply #20

There is something wrong with the home page (http://www.elkarte.net/), it takes several seconds to be loaded and sometimes is not displayed correctly, the right blocks are not displayed. It's somehow random, now seems working fine, but today I saw it 2-3 times loading very slow. Try it also in incognito mode.
The forum is loading fine
Am I the only one with this problem?
sorry for my bad english

Re: site slow

Reply #21

Had not noticed anything, but I don't tend to land on that page.   It's possible that fetching the "latest" data (commits etc) for display was/is causing a page block, maybe GitHub is slow today

Re: site slow

Reply #22

Yep, that's what I was thinking as well.
Bugs creator.
Features destroyer.
Template killer.

Re: site slow

Reply #23

It's a few days that randomly I get page loads way out of the average like this one few moments ago:
Page created in 13.742 seconds with 18 queries.
It almost feels like it's recaching too frequently the CSS/JS hives...
Bugs creator.
Features destroyer.
Template killer.

Re: site slow

Reply #24

This is back as a new head to the same issue. PHP 8.1 on cPanel seems to come without shell_exec.

I've match a patch to check if it's disabled first before even attempting it.

Issue: https://github.com/elkarte/Elkarte/issues/3656
Patch: https://github.com/elkarte/Elkarte/pull/3660

However maybe we're better going to gethostbyaddr() in all cases and accepting sometimes it doesn't work?

Re: site slow

Reply #25

Thanks for the bug report and patch!

Indeed this is a new behavior in 8.1, but they have been warning for some time that @ is a bad idea.

In a couple of areas that I've "Fixed" I did so with  if (function_exists('some_function')) which seemed to work in conjunction with functions placed on the disabled list.  Do you happen to have the list of functions that CP has added to that list?  I just want to do a code search to check if there are other unprotected areas.
Quote from: Trekkie101 – However maybe we're better going to gethostbyaddr()
Looking at that code, you may be right! 
  • Currently it will randomly, 50% chance, call host  if running on *nix (maybe with a timeout, but maybe not)
  • Failing, or missing the random, it will, again at a 50% chance, call nslookup only if on windows (all of my *nix installs have this, not sure why it was limited to windows, but its also likely 2 decades old code)
  • failing the above two it will call gethostbyaddr

    I'd imagine there is some old commentary somewhere that would explain these programmed in behaviors, but they are probably no longer relevant:man_shrugging:  Even the cache the result only if it took more that 1/2 second seems odd.

Re: site slow

Reply #26

So down the rabbit hole I went:

gethostbyaddr() in PHP may be incredibly slow. In fact it may be the cause of all the slow reports entirely. So maybe not as the new behaviour haha

The shell_exec / nslookup method is apparently faster, likely why it made it in. It's also why the 'disable hostname lookups' is included as an option.

Function exists may come with bugs vs being explicitly disabled but if function_exists is working, it's defo neater.

Quote from: https://www.php.net/manual/en/function.function-exists.phpNote:
A function name may exist even if the function itself is unusable due to configuration or compiling options (with the image functions being an example).

By default on Cloudlinux cPanel PHP 8.1 the following are disabled.
Code: [Select]
"system, exec, shell_exec, passthru, show_source"


Re: site slow

Reply #27

I'm guessing that PHP does not set any timeout in gethostbyaddr  and so the breakout which sets a 1 second timeout on host and nslookup 

I feel that function can be cleaned up some ... nslookup appears to be part of bind-utils so if you have the host command you should have nslookup.  There is also that hidden modSettings value that could get set (if your host command does not use W) but its not unset if you update your system or move to a new host or ...

Then there is the mt_rand as well, which provides a good chance it going to use gethostbyaddr anyway.  It all seems a bit suspect.

Re: site slow

Reply #28

From 8.1

gethostbyaddr() is gonna be the only method anyway (excluding $SERVER['REMOTE_HOST']

Maybe simplify to that and then turn it off by default?

Trying to save you effort. I've got it off anyway.

Re: site slow

Reply #29

Code: [Select]
function gethostbyaddr_timeout($ip, $dns, $timeout = 1000)
{
    // random transaction number (for routers etc to get the reply back)
    $data = rand(0, 99);
    // trim it to 2 bytes
    $data = substr($data, 0, 2);
    // request header
    $data .= "\1\0\0\1\0\0\0\0\0\0";
    // split IP up
    $bits = explode(".", $ip);
    // error checking
    if (count($bits) != 4) return "ERROR";
    // there is probably a better way to do this bit...
    // loop through each segment
    for ($x=3; $x>=0; $x--)
    {
        // needs a byte to indicate the length of each segment of the request
        switch (strlen($bits[$x]))
        {
            case 1: // 1 byte long segment
                $data .= "\1"; break;
            case 2: // 2 byte long segment
                $data .= "\2"; break;
            case 3: // 3 byte long segment
                $data .= "\3"; break;
            default: // segment is too big, invalid IP
                return "INVALID";
        }
        // and the segment itself
        $data .= $bits[$x];
    }
    // and the final bit of the request
    $data .= "\7in-addr\4arpa\0\0\x0C\0\1";
    // create UDP socket
    $handle = @fsockopen("udp://$dns", 53);
    // send our request (and store request size so we can cheat later)
    $requestsize = @fwrite($handle, $data);
 
    @socket_set_timeout($handle, $timeout - $timeout%1000, $timeout%1000);
    // hope we get a reply
    $response = @fread($handle, 1000);
    @fclose($handle);
    if ($response == "")
        return $ip;
    // find the response type
    $type = @unpack("s", substr($response, $requestsize+2));
    if ($type[1] == 0x0C00)  // answer
    {
        // set up our variables
        $host = "";
        $len = 0;
        // set our pointer at the beginning of the hostname
        // uses the request size from earlier rather than work it out
        $position = $requestsize+12;
        // reconstruct hostname
        do
        {
            // get segment size
            $len = unpack("c", substr($response, $position));
            // null terminated string, so length 0 = finished
            if ($len[1] == 0)
                // return the hostname, without the trailing .
                return substr($host, 0, strlen($host) -1);
            // add segment to our host
            $host .= substr($response, $position+1, $len[1]) . ".";
            // move pointer on to the next segment
            $position += $len[1] + 1;
        }
        while ($len != 0);
        // error - return the hostname we constructed (without the . on the end)
        return $ip;
    }
    return $ip;
}

Is probably a quicker way to do it at socket level if you have fsockopen or sockets enabled.