Edjet LMS Server 6.4

Performance and scaling

This guide will help you to make important decisions about the resources to use to operate the Edjet LMS Server in your environment.

Article outline:

Resource decisions

Before setting up your environment (server) and deploying the Edjet LMS Server to it, we recommend you to check basic system requirements and also make a few resource (hardware) configuration decisions based on your expected workload.

First, you should ask some basic questions about the operation characteristics:

  • How many concurrent users you want/need to handle?
  • What will be the character of the load? Peaks?
  • What are your requirements on the application speed/latency?
  • What are your requirements on the application availability?
  • How many total data you expect to store? Videos? Hi-res photos?
  • Are there any other specific issues? Public e-learning portal with public courses for example.

Based on this and some simple calculations, you should be able to decide:

  • What processor (CPU
  • How much memory (RAM)
  • What storage
  • What network
  • Other options

Processor (CPU)

Faster processor is better for application latency.

More CPUs (cores) is better for handling more concurrent users.

As the LAPP stack running on Unix machines is very well scaling using multi-threaded architecture, the biggest impact on performance has more cores (threads or vCPUs in cloud). This is most important namely for environment with high concurrency.

To understand the impact of number of cores and to see what is possible to handle with various configurations, please see the Performance report below.

Memory (RAM)

It is critical to get enough memory for your workload to avoid swapping to slower any storage.

Amount of the RAM has usually the biggest impact on the performance, if there is not enough of it. So, get as much as you can. Of course, on the other hand, it is not economical to over-estimate the required memory. It can be very expensive mistake.

For calculating the RAM we need to estimate the number required concurrent users, the average size of processes (Apache and PostgreSQL process) combined in one HTTP request and the amount of RAM used by OS and other services.

Concurrent users

The load on the server at a particular time depends on the number of concurrent users.

Not on the total number of user accounts and not on the number of users logged-in. The term "concurrent users" is used to mean those users for whom the server is actively doing something – sending HTTP requests by clicking is the most often.

As the concurrent users activity is quite random, it is hard to measure and calculate with. So when calculating the exact concurrency is the only ways to strictly mean a number of active web server processes – concurrent processes.

Concurrent processes

Every user's click generates a HTTP request to the server and require an Apache sub-process, and, if the database is involved in the particular part of the application, also the PostgreSQL sub-process.

Each of which consume some memory and also it require an webserver connection and database connection.

Size of the processes

Edjet LMS is a quite complex application. One HTTP request, like a rendering a page with a course content, require approx. 40-75 MB of RAM. Statistically there is more processes of the more complex ones, so we calculate with the average size of the 68 MB*. This includes both Apache and PostgreSQL process.

* This is only informative. Environment used: Edjet LMS Server 3.6.1, Debian 6 with 24GB of memory. On different versions and different configs the size may wary. Windows Server processes size may be quite different! Please make your own investigation on this for your particular situation.

OS memory consumption

It depend on many things. Best way is to install configuration of your choice and see what are the demands.

For more info see:
Requirements and Environment setup for Linux
Requirements and Environment setup for Windows

For standard Linux distribution suitable for webserver, if you don't want to spent a time with this, use about the 1 GB per each 8 GB of installed memory.

Calculation

For 150 concurrent processes it is:
150 x 68 = 10.2 GB of RAM.

So your option will be probably 16 GB of RAM, so add more 2 GB for OS:
10.2 + 2 = 12.2 GB

And you have also some spare RAM for additional tasks like running backups f.e.

See following table for calculated estimates*:

Required amount of concurrent processes Estimated amount of RAM needed
100 8 GB
200 16 GB
450 32 GB
850 64 GB
1700 128 GB
3000 224 GB

* for simplicity let's assume one physical server dedicated only to LMS

Storage

Faster storage is better, namely for SQL database (see below).

Fast SSD are the best option. In the cloud, you can use volume with higher provisioned IOPS.

You can also setup specific disk array using RAID or other configuration/technology designed for speed.

If you are using network drive (NAS), make sure to connect it with fast-enough low-latency line to the server.

Network

Make sure, your server is connected with a stable and fast line to the internet.

You should be looking for at least moderate performance, but connection with 1 Gbps network bandwidth is recommend for larger deployments.

Other options

Also, you should consider multi-server environment or specific cloud solution and options like managed databases, load balancers or other.

Performance testing

Testing of the app/server performance cannot be done properly without a right tools. There is many load or stress test tools so let's pick at least this two:

ab - ApacheBench

Apachebench is available out of the box with Apache.

ab is a tool for benchmarking your Apache Hypertext Transfer Protocol (HTTP) server. It is designed to give you an impression of how your current Apache installation performs. This especially shows you how many requests per second your Apache installation is capable of serving.

It is operated from command line. Opensource.
http://httpd.apache.org/docs/2.2/programs/ab.html

JMeter

The Apache JMeter™ desktop application is open source software, a 100% pure Java application designed to load test functional behavior and measure performance. It was originally designed for testing Web Applications but has since expanded to other test functions.

JMeter simulates the concurrent users nicely, can export logs to CSV,...

Opensource, written in JAVA. Has UI which allows to set up load tests for non-programmers.
https://jmeter.apache.org

Performance report (download)

Download the paper Edjet LMS Server Performance report in PDF format with all the data and charts.

Download

Environment optimizations

There are possible server-side optimizations to speed up the LMS.

This is supposed to be tuned based on analysis of the real situation to determine the bottlenecks and measured using synthetic tests before putting to production.

SQL database

Database performance issues are the most common.

SQL database vs storage speed

Database is just as fast, as your storage. Fast storage can boost the Edjet LMS Server significantly.

If the price is a concern, you can setup 2 storages:

  • Fast - small but very fast storage dedicated to SQL database
  • Slow - large but slower storage for "files"

Also, consider to move your SQL to a specialized cloud services like AWS RDS, offering advanced performance options.

PostgreSQL configuration

Database configuration can help the database to better adapt to your workload. Edjet LMS Server works just fine with default settings, unless some specific situations occur.

These optimizations are relatively easy to do, but do not expect much of a performance gain, if the database was not misconfigured in the first place.

All changes are recommended to do using PostgreSQL .conf file. After changes restart the PostgreSQL.

All following settings are done on PostgreSQL 8.4 on Debian 6 with 24GB RAM.

Option Recommended value
shared_buffers* Set allocation of 25% available free memory to PostgreSQL - 5,5 GB.
effective_cache_size* Set allocation of 50% available free memory to PostgreSQL - 11 GB.
max_connections Set to at least to Apache MaxClients option.

* need to change kernel SHMMAX to value of combined needed amount of memory, in this case 50% of available free memory with some spare space - 12 GB.

Example: How to change SHMMAX option on Debian 6

  • add to /etc/sysctl.conf this line:
    kernel.shmmax = <value in bytes>
  • apply new setting by running:
    sysctl -p /etc/sysctl.conf

Tune kernel parameters according to webserver and postgres needs (SHMMAX etc.).

Optimizing SQL queries and using indexes

SQL performance problems can be often solved by optimization of database queries, views and functions. Also, an indexes can be build to speed and lower the load on large tables and frequently accessed data.

Both techniques require the app to be modified and tested, but are usually very effective if done right.

Specialized SQL profiling tools should be used to detect and fix SQL performance issues.

Connection pooling

If the bottleneck is a number of connections, you can setup a "pgpool" or other connection pooling software.

Advanced SQL configurations

You can scale up the performance using various advanced setups like read replicas, moving databases into the cloud, where autoscaling feature is available (services like AWS RDS) etc.

Webserver

Webserver is rarely a preformance bottleneck, but if you experience issues, you can try to take some steps even in this way.

  • Apache tuning – minimizing the memory footprint (unused modules, custom compilation)
  • Change MPM module from prefork to worker (less memory usage, better for more CPUs)
  • Choosing a different webserver faster and less memory consuming than Apache (nginx, lightppd,...)
Apache configuration

All changes are recommended to do using Apache .conf file.
After changes restart the webserver (stop+start can be not enough).

All following setting are done on Apache 2.2.16 on Debian 6

Option Recommended value
MaxClients Set to number of calculated concurrent processes.
when going above 256 you need to change ServerLimit option too (default is 256), need to add (is not listed by default).
KeepAliveTimeout Set this number to lower values (5s f.e.) then default (15s) if this is the problem. We recommend to set this based on real-life tests and real-life audience.

Enable gzip compression support

Turning on zlib.output_compression on your server might help to lower the size of transmitted data.

On the other hand, the processing power is needed to handle the compression on the fly, which can cause a high load on the CPU which can lead to actually a lower overall performance.

The compression can be set for various mimetypes:

  • HTML
  • CSS
  • JS
  • other cacheable mimetypes

Edjet LMS caching

Also whole caching subsystem is implemented for two reasons – speed and server load (both processing and bandwidth load). There are several types of caching involved in server-client interactions:

Type Level or technique
Application cache
  • Images cache (class ImageGenerator, fce getSrc & loadScr)
  • Localization strings cache
  • CSS images - sprites technique
Browser cache Expiration of cache in browser (set via HTTP headers).

Images cache

This type of cache is implemented everywhere the image is processed via imageGenerator class.

ImageGenerator class
This class is placed in <approot>\class\class_imagegenerator.php

Class is using this methods:

  • loadSrc – used for loading the url of cached image (string)
  • getSrc - used for loading the url of cached image (output echo)

getSrc

This class is used for caching images. When image from Media-library is used in page (anywhere in system, both admin and site – depending on used template) then following procedure is applied:

  • first hash of original image is acquired
  • then required image dimensions are acquired (input for method, defined in template typically)
  • then other parameters are acquired (if any) like „square“, „crop“, „watermark“ etc.
  • in other step this data are compared to existing files in image cache directory
  • if file is matched, then this cached image path is returned into method
  • if file is not matched, then appropriate cached image is built via GD library and cached image path is returned into method

Image cache directory / path
Both values are defined in config.php.
Default value is: tmp\cache\images

Cached file name format options
This format is defined in cfg.ini.php in section System in variable image_cache_format.

Format can consists from following parts:

  • info: required parameters (dimensions + other options...)
  • hash: filehash (sha1) of image (used for image ID and security issues – protecting files)
  • ext: extension of image (jpg, gif, png)
  • filename: name of image (returned value is with extension)

Default format is info_hash.ext
Example of file name of cached image
150_150__4f3b0172bb9866239cbf9ba1a3d5c23543a01518.jpg

Example of syntax of using imagegenerator in templates:
ImageGenerator::loadSrc(security::image_getFullPath($value['image_path'] . $value['image_filename']), 180, 220, true, true, true);

For more examples see code_examples.tpl.php.

Localization strings cache

This type of cache is implemented everywhere the localization string is processed via Lang class.
Cache folder is located in system files repository: /tmp/cache/localization_strings/

Installation and upgrade