Performance Improvement Techniques (Magic xpa 3.x)
The first step in improving the application performance is removing redundant menu declarations and unused components. This is especially important for mobile devices since, by default, a new application is created with a default pulldown menu and a reference to the User Functionality components. Both these objects are not used in mobile applications, so they should be removed.
In most applications you will have a startup program that starts an initialization process that synchronizes data and downloads resources for offline use.
It is recommended to condition the execution of this process, or at least the parts in the process that access the server with the following condition: ServerLastAccessStatus()=0.
This condition will ensure that the access to the server will be made only if the client successfully accessed the server on the last attempt.
Therefore, if the client failed to connect to the server on the last attempt made, then by having this condition, the client will not waste time trying to connect again to the server to perform the operation.
When you have a non-interactive process that updates a lot of records, it is advised to use a Task level transaction when possible.
Using a Record level transaction will open a transaction for each record, which can reduce the performance. In addition, when the task updates a server data source, a Record level transaction will access the server after each record in order to commit the transaction and, therefore, will reduce the performance even more.
As explained in the Caching Resources Locally section, to make sure that all images used in Offline programs are available when disconnected, you should copy, on initial startup, all server images that are used in Offline programs to the client using the ServerFileToClient() function.
To improve the performance of copying the files to the client, you should download a full folder and not several separate files.
The ServerFileToClient() function supports folders and wildcard characters (Since version: 2.4b).
Executing the function once for a folder with several files means that there will be one request to fetch the modification timestamp of all the files and then consecutive requests for each file that was changed. This means that if the files were not changed, the second time the application is started, only one request will be made.
Executing the function once per file means that for each file there will be one request to fetch the modification timestamp and then a consecutive request to fetch the file if it was changed. This means that for the first time the application is started, there are more timestamp check requests as compared to using a folder and for the second time the application is started, if the files were not changed, there will be a request to fetch the timestamp per each file as compared to a single request when using a folder.
If you need to copy several records from the server to the client or from the client to the server, it is best to do it using the DataviewToDataSource() function.
This function copies a set of records (according to range criteria) as a whole and not one by one, which results in improved performance.
Refer to DataviewToDataSource.
If your app includes a large database that needs to be available offline, such as a database with all of the countries and cities, it would be time consuming to copy each data source to the client as mentioned above.
To improve performance, you can create an SQLite database on the server with the data that should be available offline, and on the first execution, copy this database as a whole to the client using the ServerFileToClient function.
To do this, carry out the following steps on a desktop machine:
-
Delete the content of the applications’ runtime RIA cache folder under %TEMP%\MgxpaRIACache folder\<server address>.
-
Run the data copy programs to copy the data from the server data sources to the local data sources. It is recommended to use the DataviewToDataSource() function in these programs as mentioned above.
-
Navigate to the applications’ runtime RIA cache folder. This folder now contains the database file (the file name is defined in the local database properties, such as local.sqlite).
-
Place the file on the server in a folder with the same name as the local database folder. For example:
-
If the local database is named local.sqlite, place the file in the projects’ working directory on the server (next to the EDP/ECF files).
-
If the local database is named db\local.sqlite, place the file in a DB subfolder under the projects’ working directory on the server.
-
If the local database is named c:\temp\local.sqlite, place the file in c:\temp\local.sqlite on the server.
-
In your startup program, copy the database file from the server to the client.
You only need to copy the file if the local database does not exist.
Make sure that you use the same path as defined in the local database name. For example:
-
If the local database is named local.sqlite, use: Evaluate ServerFileToClient(‘local.sqlite’).
-
If the local database is named db\local.sqlite, use: Evaluate ServerFileToClient(‘db\local.sqlite’).
-
If the local database is named c:\temp\local.sqlite, use: Evaluate ServerFileToClient(‘c:\temp\local.sqlite’).
Notes:
-
If you previously used the local database in the current session (for example, to check if it has records), you will need to use the ClientDBDiscnct() function to close the connecting to the local database.
-
If you need to save data in the local database before fetching it from the server (for example, to save the user name), you should use two local databases with different names).This method only sets the initial data. To add more records to it later on, refer to Synchronizing Data Between Client and Server.
-
For Android, iOS and Windows 10 Mobile devices you can also package the database file into the mobile packages (APK, IPA and APPX) and deploy them to the application cache folder on the client immediately after an installation or an upgrade. Refer to Packaging Resource Files.
You can package resource files during the creation of the mobile packages (APK, IPA and APPX) and deploy them to the application cache folder on the client immediately after an installation or an upgrade. This means that these files are available to the Magic xpa programs without the need to retrieve them at runtime. This saves server access and the download time.
The main usage of this feature is to deploy the images and the local database when installing the package, instead of retrieving them from the server on the first execution.
Refer to Packaging Resource Files.
Note that even if the images are packaged in the APK, IPA or APPX, it is recommended to use ServerFileToClient() on the images folder since:
-
If there was a change in an image, this image will be updated in the client without having to repackage everything and download an update of the application.
-
It will improve the performance of the first programs.
The action of ServerFileToClient() validates that the local files are current and stores this information in the memory. When executing a program that uses an image, since the image is known to be current, the client will not try to fetch it from the server again. Without using the function, the client would have to access the server to check the image modification time.
Note that this improvement is seen only for the first programs because once an image is used in one program, the client will not access the server to fetch the image again in the entire session. Therefore, the function only improves the performance in the program that first uses the image.
The Rich Client Samples project (program RDS01)