Performance degradation with sessions. Laravel 8. Docker
apoldev opened this issue · 8 comments
Hello.
I have a docker container with RoadrRunner and Laravel 8.16.1 by default. (clean install laravel new www
)
I try it many times:
ab -n 1000 -c 100 "http://serverhost:8080/"
I notice a degradation of app performance:
3113.96 [#/sec]
....
1024.88 [#/sec]
539.06 [#/sec]
439.41 [#/sec]
If i remove in Http/Kernel.php in $middlewareGroups
these lines:
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
then performance not degrade:
Requests per second: 2844.97 [#/sec] (mean)
Time per request: 35.150 [ms] (mean)
Time per request: 0.351 [ms] (mean, across all concurrent requests)
I suppose I need to reset the sessions? Only with the default config, roadrunner-laravel does not work.
How can I do it?
Dockerfile
FROM php:7.4-cli
#COPY opcache.ini /usr/local/etc/php/conf.d/opcache.ini
RUN apt-get update && apt-get install -y \
curl \
vim \
libfreetype6-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpng-dev \
zlib1g-dev \
libxml2-dev \
libzip-dev \
libonig-dev \
graphviz \
libcurl4-openssl-dev \
pkg-config \
libpq-dev \
iputils-ping \
wget \
git
# Install PHP Extensions
RUN docker-php-ext-install -j$(nproc) iconv mbstring mysqli pdo_mysql zip \
&& docker-php-ext-install opcache \
&& docker-php-ext-enable opcache
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Download RoadRunner
ENV RR_VERSION 1.8.4
RUN mkdir /tmp/rr \
&& cd /tmp/rr \
&& echo "{\"require\":{\"spiral/roadrunner\":\"${RR_VERSION}\"}}" >> composer.json \
&& composer install --ignore-platform-reqs \
&& vendor/bin/rr get-binary -l /usr/local/bin \
&& rm -rf /tmp/rr
## Copy RoadRunner config
COPY config /etc/roadrunner
WORKDIR /var/www
CMD ["/usr/local/bin/rr", "serve", "-c", "/etc/roadrunner/.rr.yaml", "-w", "/var/www"]
docker-compose.yml
version: "3.7"
services:
roadrunner:
build: ./images/roadrunner
container_name: "roadrunner"
ports:
- 8080:8080
volumes:
- ./www:/var/www:cached
- ./configs/roadrunner:/etc/roadrunner:cached
network_mode: "host"
.rr.yaml
env:
#APP_REFRESH: true
http:
address: 0.0.0.0:8080
workers:
command: 'php /var/www/vendor/bin/rr-worker' # for windows: `php vendor/spiral/roadrunner-laravel/bin/rr-worker`
static:
dir: 'public'
reload:
interval: 1s
patterns: [".php"]
services:
http:
dirs: [""]
recursive: true
Hi @apoldev! What about memory usage during your ab
tests?
Hello!
If i remove these three lines from $middlewareGroups:
Start. MEMORY USAGE
197MiB
After `ab` tests:
ab -c 100 -t 120 "http://remote_server:8080"
Time taken for tests: 17.783 seconds
Requests per second: 2811.70 [#/sec] (mean)
MEMORY USAGE 287.7MiB
WITH SESSION IN $middlewareGroups.
Start. MEMORY USAGE
197MiB
After ab tests:
ab -c 100 -t 120 "http://remote_server:8080"
Complete requests: 13926
Time taken for tests: 120.201 seconds
Requests per second: 115.86 [#/sec] (mean)
MEMORY USAGE: 398.9MiB
Performance degradation confirmed.
My dockerfile:
FROM php:7.4.13-alpine
# Install PHP Extensions
RUN set -x \
&& docker-php-ext-install opcache \
&& docker-php-ext-enable opcache
# Download RoadRunner
COPY --from=spiralscout/roadrunner:1.9.0 /usr/bin/rr /usr/bin/rr
# Download Composer
COPY --from=composer:2.0.7 /usr/bin/composer /usr/bin/composer
# Install "clean" laravel
RUN composer create-project --prefer-dist --no-progress "laravel/laravel" /src "^8.4"
# Change working diretory to the laravel installation
WORKDIR /src
# Install RR bridge
RUN composer require --no-progress spiral/roadrunner-laravel "^3.4"
# Create simple RR config file
RUN echo -e \
"rpc:\n"\
" enable: false\n"\
"http:\n"\
" address: 0.0.0.0:8080\n"\
" workers:\n"\
" command: 'php ./vendor/bin/rr-worker'\n"\
" pool:\n"\
" numWorkers: 4\n"\
" maxJobs: 0\n"\
" allocateTimeout: 60\n"\
" destroyTimeout: 60\n"\
"static:\n"\
" dir: 'public'" > ./.rr.yaml
CMD rr -c /src/.rr.yaml serve -d
Build & run:
$ docker build --tag laravel-rr:local . && docker run --rm -p "8080:8080/tcp" laravel-rr:local
In separate terminal:
$ for i in {0..20}; do ab -n 1000 -c 100 "http://127.0.0.1:8080/" 2>&1 | grep 'per second:'; done
Requests per second: 1102.43 [#/sec] (mean)
Requests per second: 918.61 [#/sec] (mean)
Requests per second: 746.16 [#/sec] (mean)
Requests per second: 637.29 [#/sec] (mean)
Requests per second: 614.52 [#/sec] (mean)
Requests per second: 512.78 [#/sec] (mean)
Requests per second: 540.68 [#/sec] (mean)
Requests per second: 445.41 [#/sec] (mean)
Requests per second: 479.77 [#/sec] (mean)
Requests per second: 388.88 [#/sec] (mean)
Requests per second: 445.12 [#/sec] (mean)
Requests per second: 381.85 [#/sec] (mean)
Requests per second: 328.83 [#/sec] (mean)
Requests per second: 324.74 [#/sec] (mean)
Requests per second: 409.21 [#/sec] (mean)
Requests per second: 351.63 [#/sec] (mean)
Requests per second: 304.58 [#/sec] (mean)
Requests per second: 347.62 [#/sec] (mean)
Requests per second: 262.54 [#/sec] (mean)
Requests per second: 281.68 [#/sec] (mean)
Requests per second: 221.30 [#/sec] (mean)
I need in some time for additional local tests. Thank for your report!
With next config RR works better:
http:
workers:
pool:
numWorkers: 16
maxJobs: 64
allocateTimeout: 60
destroyTimeout: 60
$ for i in {0..10}; do ab -n 1000 -c 100 "http://127.0.0.1:8080/" 2>&1 | grep 'per second:'; done
Requests per second: 1053.86 [#/sec] (mean)
Requests per second: 578.81 [#/sec] (mean)
Requests per second: 613.15 [#/sec] (mean)
Requests per second: 517.34 [#/sec] (mean)
Requests per second: 552.03 [#/sec] (mean)
Requests per second: 492.22 [#/sec] (mean)
Requests per second: 491.06 [#/sec] (mean)
Requests per second: 475.94 [#/sec] (mean)
Requests per second: 455.25 [#/sec] (mean)
Requests per second: 359.54 [#/sec] (mean)
Requests per second: 401.63 [#/sec] (mean)
Hello, I will take part in this discussion.
Are you using the RoadRunner
config (If you publish a vendor config, it is placed in ./config/roadrunner.php
)?
Please, show it.
Hello.
Default laravel session driver is file
(.env.example, config).
Each time session starts, laravel calls garbage-collector (StartSession middleware). This operation is I/O bound for FileSessionHandler and degrade on large session list.
For tests i use "Apache jMeter" and "Apache ab", dockerfile from @tarampampam reply with configs:
http:
workers:
pool:
numWorkers: 4 # I have only 4 threads on testing machine
maxJobs: 64
allocateTimeout: 60
destroyTimeout: 60
jMeter tests was run in 50 parallel threads. Each thread does 5000 calls.
All graphics contains 90th percentile.
Default run:
$ docker run --rm -p "8080:8080/tcp" laravel-rr:local
$ for i in {0..20}; do ab -n 1000 -c 100 "http://127.0.0.1:8080/" 2>&1 | grep 'per second:'; done
Requests per second: 714.26 [#/sec] (mean)
Requests per second: 676.30 [#/sec] (mean)
Requests per second: 650.93 [#/sec] (mean)
Requests per second: 619.68 [#/sec] (mean)
Requests per second: 581.30 [#/sec] (mean)
Requests per second: 587.99 [#/sec] (mean)
Requests per second: 493.58 [#/sec] (mean)
Requests per second: 577.38 [#/sec] (mean)
Requests per second: 480.70 [#/sec] (mean)
Requests per second: 486.99 [#/sec] (mean)
Requests per second: 506.49 [#/sec] (mean)
Requests per second: 422.18 [#/sec] (mean)
Requests per second: 419.97 [#/sec] (mean)
Requests per second: 410.45 [#/sec] (mean)
Requests per second: 400.14 [#/sec] (mean)
Requests per second: 458.22 [#/sec] (mean)
Requests per second: 412.70 [#/sec] (mean)
Requests per second: 419.72 [#/sec] (mean)
Requests per second: 518.80 [#/sec] (mean)
Requests per second: 388.01 [#/sec] (mean)
Requests per second: 347.34 [#/sec] (mean)
With array
session driver:
$ docker run --rm -p "8080:8080/tcp" -e "SESSION_DRIVER=array" laravel-rr:local
$ for i in {0..20}; do ab -n 1000 -c 100 "http://127.0.0.1:8080/" 2>&1 | grep 'per second:'; done
Requests per second: 780.17 [#/sec] (mean)
Requests per second: 725.75 [#/sec] (mean)
Requests per second: 742.22 [#/sec] (mean)
Requests per second: 699.86 [#/sec] (mean)
Requests per second: 730.22 [#/sec] (mean)
Requests per second: 734.53 [#/sec] (mean)
Requests per second: 711.45 [#/sec] (mean)
Requests per second: 705.01 [#/sec] (mean)
Requests per second: 715.21 [#/sec] (mean)
Requests per second: 718.66 [#/sec] (mean)
Requests per second: 703.98 [#/sec] (mean)
Requests per second: 747.79 [#/sec] (mean)
Requests per second: 684.66 [#/sec] (mean)
Requests per second: 718.03 [#/sec] (mean)
Requests per second: 724.57 [#/sec] (mean)
Requests per second: 723.42 [#/sec] (mean)
Requests per second: 720.13 [#/sec] (mean)
Requests per second: 695.69 [#/sec] (mean)
Requests per second: 711.15 [#/sec] (mean)
Requests per second: 724.82 [#/sec] (mean)
Requests per second: 687.52 [#/sec] (mean)
Remove gc call from startSession
middleware, using session.lottery
config:
$ for i in {0..20}; do ab -n 1000 -c 100 "http://127.0.0.1:8080/" 2>&1 | grep 'per second:'; done
Requests per second: 699.82 [#/sec] (mean)
Requests per second: 661.41 [#/sec] (mean)
Requests per second: 603.76 [#/sec] (mean)
Requests per second: 597.45 [#/sec] (mean)
Requests per second: 702.27 [#/sec] (mean)
Requests per second: 658.57 [#/sec] (mean)
Requests per second: 659.56 [#/sec] (mean)
Requests per second: 726.27 [#/sec] (mean)
Requests per second: 738.47 [#/sec] (mean)
Requests per second: 724.43 [#/sec] (mean)
Requests per second: 669.35 [#/sec] (mean)
Requests per second: 705.24 [#/sec] (mean)
Requests per second: 704.70 [#/sec] (mean)
Requests per second: 695.04 [#/sec] (mean)
Requests per second: 710.15 [#/sec] (mean)
Requests per second: 683.25 [#/sec] (mean)
Requests per second: 695.19 [#/sec] (mean)
Requests per second: 704.88 [#/sec] (mean)
Requests per second: 679.48 [#/sec] (mean)
Requests per second: 680.28 [#/sec] (mean)
Requests per second: 734.98 [#/sec] (mean)
@tarampampam
Yes. Thanks for your research!
There is no more problem. Thanks