Search code examples
phpemailopencartregistration

Opencart registration takes extremely long


I just installed an OpenCart system for one of my customers on my server(Server is Debian Wheezy, with Nginx, PHP and MariaDB). Everything is working fine, except for one thing. When a customer tries to register, the registration takes huge amount of time, somewhere around 3 minutes. I have traced the problem and it most likely hangs when sending emails to customer and to admin.

I handle emails on the server with SSMTP, which in turn uses my own email server. Other webapps like Joomla work fine and email is sent instantly, without any delay (same for mail command in system). Opencart is set to "mail" (I even tried entering SMTP directly to opencart, but it was not working).

Since I don't know basically anything about OpenCarts inner workings, can someone more experienced help me with this problem?

Thanks in advance!

EDIT:

I have been able to successfuly identify the root cause of the problem. It was not at all matter of PHP or OpenCart, but actually a system thing. The settings for sendmail path in php.ini were commented out, which means PHP tries to find it by itself. For some reason, it went for sSMTP in case of OpenCart. Since sSMTP is synchronous, it took a long time to wait for it to finish. Joomla on the other hand, went for Heirloom mailx forgotten on my server from some old dependency (why I have no idea) and the mail command exited right away, hence no delay.

My solution after hours of debugging and trial-error was to scrap ssmtp and mailx altogether and use postfix to relay mail to external server. Now everything works as expected.


Solution

  • I'll generalize it a bit - how to root cause the performance issues in complex PHP systems.

    Follow these steps:

    1. Install Xdebug PHP extension
    2. Configure the Xdebug's profiler (profiler_enable or profiler_enable_trigger, profiler_output_path etc.)
    3. Navigate to the page which is slow in a browser and load it (if profiler_enable is set the profile will be created for every request, if it isn't set and profiler_enable_trigger is set just add XDEBUG_PROFILE parameter to the URL)
    4. Navigate into directory you have configured profiler_output_path to and open the profiler output file in some GUI tool (see this answer)
    5. Check which function call took the most time (a function call can take just 5 ms, but if it's called 1000 times during single execution it's 5 seconds in total - you should see all these information in the GUI tool)

    Notes:

    • you shouldn't have Xdebug enabled on a production server (it slows down the execution)
    • if your application can be accessed by someone else, don't enable profiler_enable, but rather profiler_enable_trigger, so you can control what requests trigger the profiling (profiler output file can be pretty big)