LogoLogo
What's NewDeveloper CommunitySupportStatus
  • 🚀Get Started
    • What is JourneyApps Platform?
    • Tutorial: Build your First App
      • 1. Introduction
      • 2. Create a new App
      • 3. OXIDE IDE Overview
      • 4. Hello World app
      • 5. The Data Model
      • 6. View Components
      • 7. Queries and Data Sync
      • 8. Simple Navigation
      • 9. View Stack
      • 10. Input Validation
      • 11. View Parameters
      • 12. Data Manipulation
      • 13. Responsive Apps
      • 14. Styling
      • 15. Lists
      • 16. GPS Capturing
      • 17. Relationships
      • 18. Multiple User Roles
      • 19. Deployment and Users
      • 20. Version Control
      • 21. CSV and APIs
      • 22. Conclusion
    • JourneyApps Platform Fundamentals
      • Creating a New App
        • Git-enabled Apps
      • What are Views?
      • What is the Data Model?
      • JourneyApps Syntax Basics
      • Access the Database (DB)
        • Manipulate DB Objects
        • Query DB Objects
      • View Navigation
        • Deep Linking
      • CloudCode Overview
      • OXIDE (Online IDE)
  • 💻Build your App
    • JourneyApps Syntax
      • Syntax Basics
      • Access the DB
      • View Navigation
      • Async & Await
      • TypeScript Apps (Beta)
        • runtime-build package
        • TypeScript App Troubleshooting
      • What's New in V4
        • Updating to the V4 API
    • Configure your Data Model
      • What is the data model?
      • Reference: model
        • field
        • belongs-to
        • has-many
        • index
      • Data Rules
        • Data Buckets
        • Sync Rules - Limit data synced to devices
        • Data ACLs - Limit access to data
        • Real-world example for Data Rules
        • ❔FAQs
        • Migrate to Data Rules
      • App Indexes
      • Webhooks
    • UI Components
      • All UI Components
        • actionSheet
        • Attachments
        • button
        • button-group
        • capture-coordinates
          • marker
          • marker-query
        • capture-file
        • capture-photo
        • capture-signature
        • card
          • accent
          • action
        • columns
          • column
        • component
        • context-menu
          • divider
          • item
        • CSV
        • date-input
        • datetime-input
        • dialog
          • body
        • display-3d-model
          • 📖display-3d-model Guides
            • Guide 1: Initialize and layout a 3D model in a view
            • Guide 2: Control playback position
            • Guide 3: Troubleshooting controls
        • display-coordinates
        • display-file
        • display-image
        • display-photo
        • display-signature
        • heading
        • html
          • HTML Advanced Topics
          • ❔HTML FAQs
          • 📖Guide: HTML & JourneyApps iFrame Client
        • icons
        • info
        • info-table
          • row
        • journey.photos (capture multiple photos)
        • JourneyPrinter (print PDFs)
        • grid
          • cell
          • 📖grid Examples
        • list
          • list-item
            • accent
            • asset
            • pills
              • pill
            • action
        • multiple-choice-checklist
        • navigation (Navigation drawer)
          • general-section
            • item
          • section
            • item
              • item
          • ❔navigation FAQs
        • notification
        • object-dropdown
        • object-list
          • action
        • object-repeat
        • object-table
          • action
          • column
            • action
            • edit-boolean
            • edit-date
            • edit-datetime
            • edit-integer
            • edit-number
            • edit-select
            • edit-text
            • edit-time
            • edit-typeahead
              • action
            • header-action
          • column-group
          • empty-action
          • 📖object-table Guides
            • Actions
            • Cell callouts
            • Column groups
            • Columns
            • Controlled object-table
            • Controls
            • Copy & paste data
            • Edit cells
            • Filters
            • Frozen columns
            • Fullscreen object-table
            • Mode
            • State
            • Styles
        • optionList
        • PhotonSync (transfer data offline)
        • power-bi
          • 📖Guide: PowerBI Embedding
        • scan-barcode
        • shortcut
        • sidebar
        • single-choice-dropdown
        • single-choice-radio
        • template
        • text-input
        • time-input
        • toggle
        • view
      • JS/TS Events
      • Show / Hide UI Components
      • View Templates
      • XML Fields (Attributes)
        • align-content
        • align-controls
        • align-label
        • bind
        • clear-button-visibility
        • control-order
        • disabled
        • error-message
        • icon-position
        • id
        • hide-if
        • modifier-text
        • label
        • label-case
        • label-color
        • on-change
        • on-press
        • placeholder
        • required
        • show-if
    • JS / TS APIs
      • Attachment
      • Bluetooth (Beta)
      • Broadcast
      • component
      • CSV
      • DB
      • HardwareBarcode
      • journey
        • journey.config
        • journey.container
        • journey.device
        • journey.diagnostics
        • journey.dialog
        • journey.files
        • journey.hardware
        • journey.photos
        • journey.runtime
        • journey.sensors
        • journey.viewStack
      • JourneyPrinter
      • KeyboardBarcode
      • LocalDB
      • NFC
      • OnlineDB
      • PhotonSync
      • SerialPort
      • ShortcutManager
      • TCPSocket
      • user
    • Extend your App with Custom Code
      • App packages
        • App packages overview
        • PDF report package
        • TypeScript library & unit tests
        • Manage External Dependencies
      • Custom HTML
    • Style & Customize your App
      • Style & configure UI components
        • Overview
        • Understand extendable themes
        • Use themes on a view
        • Theme specific components on a view
        • Examples
        • Debugging
        • ❔FAQs
      • Change your App Font
      • Custom Branding
        • Custom Container Features
        • Special Requirements for iOS Containers
    • Integrate your App
      • Backend integrations with CloudCode
      • Barcode Scanning
        • Barcode Scanning using Keyboard Emulation
        • Hardware Barcode Scanning
        • scan-barcode
      • Bluetooth Low Energy (BLE)
      • Broadcast API
      • HTTP requests (Fetch API)
      • JourneyApps Print (Android)
      • Maps and navigation
      • NFC
      • Opening external links/apps
      • Serial Port
      • TCP Sockets
    • Design Intuitive Apps
      • UX Guidelines
      • Write Effective Copy
  • 📱App Features
    • RealWear® Voice Control
      • Automatic Voice Commands
        • Automatic Voice Commands - Advanced
      • Manual Voice Commands
    • App, Runtime and Container Updates
    • Batch Operations (App)
    • Call JS/TS Functions from XML
    • Capture GPS Locations
    • Push Notifications
    • Translations
    • XML Format Strings
    • Webhooks (External)
  • 🌐CloudCode
    • CloudCode Overview
    • Trigger a CloudCode Task
      • Trigger CC with a Schedule
      • Trigger CC via a Webhook
      • Trigger CC from an App
      • Trigger CC from Another Task
      • Trigger CC via HTTP
    • Attachments in CloudCode
    • Timezones
    • Advanced CloudCode Topics
      • Access Multiple DBs in CloudCode Tasks
      • Batch API (CloudCode)
      • CloudCode Dependencies
      • Configure HTTPS in CloudCode
      • Deployment environment variables
      • Local CloudCode Development
      • PDF Reports using CloudCode
      • Shared CloudCode Tasks
      • Translations in CloudCode
  • 📥Backend API
    • Introduction
    • API Reference
      • Retrieve All Objects
      • Query Objects
      • Sort Results
      • Limit and Skip
      • Count Objects
      • Create a New Object
      • Retrieve a Single Object
      • Update a Single Object
      • Delete a Single Object
      • Batch Operations (v4 API)
      • Oplog API
      • Retrieve the App Data Model
      • Manage App Users and Sessions
      • Field Representation
      • Error Responses
    • API Limits
    • Update to the V4 API
  • ⚙️Technical
    • Data Synchronization Priority
    • Device Diagnostics
    • JSON1 Query Engine
    • Improve App Performance
    • Security Measures
    • Supported Platforms
      • Web Container
      • Windows Installer
    • Domain Whitelist
  • 🖥️OXIDE
    • Get started with OXIDE
      • OXIDE Overview
      • Components of OXIDE
    • Configure Testing Deployments
    • Edit and Manage Files
      • How to Navigate to a Function
      • Manage External Dependencies
    • Create and Manage App Containers
    • Debugging & Troubleshooting
      • Common Troubleshooting Pointers
      • App Diagnostics Reports
      • Build Logs
    • OXIDE Workspaces
      • OXIDE Trees
  • ❕Deprecated Features
    • Deprecated Features and Components
Powered by GitBook
On this page
  • Typical sources of poor app performance
  • Use the developer console to pinpoint specific issues
  • Common app performance improvements
  • Views with an editable object-table
  • Global UI components
  • iOS devices and memory use
  1. Technical

Improve App Performance

PreviousJSON1 Query EngineNextSecurity Measures

Last updated 2 years ago

As your app grows in size and complexity, it may run into performance bottlenecks. This document aims to address common app performance issues and gives you tools to identify performance bottlenecks and to improve the performance of your app.

Advanced Topic

Debugging performance issues requires a systematic approach, and a deeper understanding of how an app is run on specific hardware. This doc assumes that you understand the high-level constraints on app performance i.e. CPU, memory use and graphical rendering.

Typical sources of poor app performance

To start, it is useful to know what the common causes are of poor app performance:

  • The device running the app is slow. If only some users are affected, and they are running older hardware, check to see whether their devices meet the .

  • The app is making against big data sets without .

  • The app is making many in sequence (or in parallel).

  • On each digest cycle, the app is performing many operations to refresh the view.

  • The app is rendering a lot of data at once.

This is a non-exhaustive list, but covers the most typical causes.

Each of the above root causes for poor app performance can be pinpointed using the tools described below.

Use the developer console to pinpoint specific issues

Cannot reproduce the issue?

The first step to debugging any performance-related issue is to try and reproduce the issue. If you cannot reproduce the issue it makes it nearly impossible to debug the problem. First spend time and gather information to reproduce the issue before proceeding.

The most effective tool for you to help identify what is causing an app to be slow is the . The developer console logs performance-related information.

For a desktop container, confirm that you have a container where the developer tools are enabled. The JourneyApps branded container has developer tools enabled by default. Right-click anywhere in the app and select "Toggle DevTools".

To open the developer console, open the "Console" tab. Be sure to view the Verbose log levels, and for best results, update the developer console settings to include time stamps.

  • View function names are now listed instead of “widgets-navigate”

  • Each digest cycle is being logged

  • More sync system operations are being logged, including expensive DB operations

  • Queries now show indexes where applicable

Common app performance improvements

This section covers the most common ways to improve an app's performance.

Query optimizations

App indexes

In the developer console, look for single queries that are taking longer than 100ms, especially if the result set is less than 30 objects.

To see whether a query is correctly using an index, or might need one, you can add .explain() to the query and place it in a console.log() during development.

  • Example query log without indexes: DB.job.where("customer_id = ?", view.customer_id) (type: full scan, results: 1, scanned: 17987)

  • Example query log with indexes: DB.job.where("customer_id = ?", view.customer_id) (type: index, results: 1, scanned: 25 ...)

Queries and loops

As a rule of thumb, avoid making queries in a loop. Queries being run in a loop (for or forEach() etc.) are prone to poor performance, especially on devices with less computing power.

It's often easy to identify queries in a loop by inspecting the code where the app is slow. If you're looking at the developer console, queries in a loop are very easy to spot. It presents as a series of similar queries in very quick succession.

Changing many DB objects in quick succession

OnlineDB queries

For that reason, using OnlineDB may exacerbate other sources of poor performance, e.g. querying in a loop, or doing queries in $: functions.

.count() vs .length

.count() is considered a query, and can contribute to poor app performance. If a function may do multiple .count() queries, consider using Arrays instead and use .length, which will execute much faster.

Queries in the view

Queries defined in the View XML are refreshed on every digest cycle. By contrast, arrays are not refreshed on every digest cycle. If a view needs to show data from many queries, but the data sets are not expected to change, try to use arrays instead of queries for view variables.

$: functions and the digest cycle

The app can take a performance hit when using $: functions, especially when queries are run as part of the functions.

The reason why an app slows down where queries are run in $: functions is linked to the concept of the digest cycle. The digest cycle is the process where the app refreshes what is displayed. A digest is triggered on every saved change on a view, every on-change, every on-press.

For that reason, when $: functions include many queries, or a few slow queries, it means that those queries need to be run every single time the app has to refresh the values displayed. That will mean that users will perceive the app to be slow to interact with.

Views with an editable object-table

Here are some specific performance considerations for object-table:

  • A table often displays large amounts of data, which implies that there is a big (and often slow) query made. Sometimes there are ways to index the query to improve performance.

  • Tables might display related belongs-to data in the table as one or more of the columns. This creates a situation where a belongs-to look-up is being made for each row in the table (effectively a query within a loop). To rectify this, add .include() on the query that is bound to the table for the related object you'd like to display.

  • Editable tables have on-change functions that trigger on each change made in each cell. And in the function lookups might be made or queries may inadvertently be run. App users often want to edit cells in quick succession, which potentially sets off a number of on-change functions, compounding the problem.

  • Tables often use $: functions to update formatting in tables. These functions might contain operations or queries that aren't performant, adding to the digest cycle.

Global UI components

iOS devices and memory use

Different devices handle high memory and CPU use differently. On iOS an app that is using high amounts of memory may cause a "white screen" where the app is no longer accessible and will need to be restarted. Use the guide above to identify performance bottlenecks and address them.

It's also possible to use the developer tools in , though note that DB performance could be very different on Web vs other platforms.

We recommend using the developer debug console with runtime version 4.85.0 or greater and enabling , which includes the following performance profiling improvements:

Also see:

Most performance issues are created by issues related to slow or high volumes of . For the purpose of this doc, queries refer to both DB and OnlineDB queries, and even belongs-to relationship look-ups.

When specific interactions in an app have become reproducibly slow as the data volumes have grown, it might point to a query that requires an . App indexes might be required on belongs-to relationships, or where the query result is a small subset of the queried data.

For apps with runtime version 4.85.0 or greater, indexes can be seen together with queries logged in the developer console with enabled.

Sometimes it is necessary to perform a large number of DB operations in quick succession. If you do this as multiple .save() operations, the DB performance may suffer. A better pattern is to batch them together using .

DB queries are typically very fast, since the application is querying data on a local database. By contrast, (similar to fetch requests) have significant delay to complete because the request - response loop depends on a connection between the app device and remote server.

are very commonly used to make an app more dynamic and respond to user feedback. What's important to understand about $: functions is that they are run on every digest cycle (more about this below). These functions can be used in the View XML, and in global UI components such as the Navigation component.

Views with large or complicated UI components are specifically prone to poor performance given that it is easy to make many of the above performance mistakes.

Global UI components (e.g. the ) are displayed on most, if not all app views. For some use cases it might be necessary to show the number of objects (e.g. unread messages, or "todo" tasks). Be mindful, however, that any $: functions that do .count() or even other queries, will be run on every digest cycle, and may contribute to an app feeling unresponsive overall.

⚙️
Web
journey.profiling
DB queries
app index
journey.profiling
Batch Operations
OnlineDB
$: functions
object-table
navigation drawer
recommended hardware specifications
queries
app indexes
queries
developer debug console
Debug console