Showing posts with label performance. Show all posts
Showing posts with label performance. Show all posts

Friday, 4 August 2017

Firebase Performance Monitoring for Android Tip #1: Automatic Traces for All Activities

Doug Stevenson
Doug Stevenson
Developer Advocate

If you haven't tried Firebase Performance Monitoring yet, many Firebase developers have found it to be a helpful way to get a sense of some of the performance characteristics of their iOS or Android app, without writing many extra lines of code. To get more detailed information beyond what's collected automatically, you'll eventually have to write some custom traces and counters. Traces are a report of performance data within a distinct period of time in your app, and counters let you measure performance-related events during a trace. In today's perf tip, I'll propose a way to add potentially many more traces to your Android app without writing very much code at all.

Android apps are typically made up of a collection of activities that present some task or data to the user. For the purpose of hunting down potential performance problems, it can be handy to define a trace for every Activity in your app, so you can study the results later in the Firebase console. If your app has lots of activities, it might be kind of a pain to write the code for all of them. Instead, you can write a little bit of code that instruments all of them with their own trace.

Android gives you a way to listen in on the lifecycle of every single Activity in your app. The listeners are implementations of the interface ActivityLifecycleCallbacks, and you can register one with the Application.registerLifecycleCallbacks()method. For measuring performance, I suggest creating a trace that corresponds to the onStart() and onStop() lifecycle methods. When an activity is "started", that means it's visible on screen, and when it's "stopped", it's no longer visible, so I think this is a good place to define a trace that tracks an activity while it's actually doing things. Here's the start of an implementation of ActivityLifecycleCallbacks that keeps track of traces for each of your activities. First we'll make it a singleton so it can be easily accessed everywhere (or you might want to use some form of dependency injection):

public class PerfLifecycleCallbacks
implements Application.ActivityLifecycleCallbacks {

private static final PerfLifecycleCallbacks instance =
new PerfLifecycleCallbacks();

private PerfLifecycleCallbacks() {}
public static PerfLifecycleCallbacks getInstance() {
return instance;
}
}

Then, inside that class, I'll add some members that manage custom traces for each Activity:

    private final HashMap<Activity, Trace> traces = new HashMap<>();

@Override
public void onActivityStarted(Activity activity) {
String name = activity.getClass().getSimpleName();
Trace trace = FirebasePerformance.startTrace(name);
traces.put(activity, trace);
}

@Override
public void onActivityStopped(Activity activity) {
Trace trace = traces.remove(activity);
trace.stop();
}


// ...empty implementations of other lifecycle methods...

This will start a trace when any activity is started, and stop the same trace when the activity is stopped. For the name of the trace, I'm using the simple class name of the activity object, which is just the class name without the full java package. (Note: if you do this, make sure that your Activity class names are unique, if they're spread across Java packages!)

I'll add one more method to it that will return the trace of a given Activity object. That can be used in any activity to get a hold of the current trace so that counters can be added to it:

    @Nullable
public Trace getTrace(Activity activity) {
return traces.get(activity);
}

This class should be registered before any Activity starts. A ContentProvider is a good place to do that. If you're not familiar with how that works, you can read about how Firebase uses a ContentProvider to initialize.

public class PerfInitContentProvider extends ContentProvider {
@Override
public boolean onCreate() {
context = getContext();
if (context != null) {
Application app = (Application) context.getApplicationContext();
app.registerActivityLifecycleCallbacks(
PerfLifecycleCallbacks.getInstance());
}
}
}

Don't forget to add the ContentProvider to your app's manifest! This will ensure that it gets created before any Activity in your app.

Once this ContentProvider is in place, your app will automatically create traces for all your activities. If you want to add counters to one of them, simply use the getTrace() method from the PerfLifecycleCallbacks singleton using the current Activity object. For example:

private Trace trace;

@Override
protected void onCreate(Bundle savedInstanceState) {
trace = PerfLifecycleCallbacks.getInstance().getTrace(this);
// use the trace to tally counters...
}

Be sure to think carefully about the counters you want to log! You'll want to measure things that will give you information that helps inform a decision about how the user experience could be improved in your app. For example, you could record the ratio of cache hits to misses to help tune the amount of memory for the cache. And be sure to follow Firebase on Twitter to get more Firebase Performance Monitoring tips.

Share:

Wednesday, 5 July 2017

Test Your Game with Firebase Test Lab for Android

Doug Stevenson
Doug Stevenson
Developer Advocate

Testing your application is a great way to help maximize its quality, and many of you know that Firebase Test Lab for Android has some useful tools for testing Android apps. If you're the type of engineer who likes to maximize test coverage by writing instrumented tests (and regular unit tests), you can send those to Test Lab for execution. Even if you don't like writing tests, you have some options. You can record instrumented tests by interacting with your app using Espresso Test Recorder in Android Studio. And there's almost no effort required at all to run a Robo test that automatically crawls your app.

These tests are helpful for data-driven apps because there are robust test frameworks that understand how to navigate the Android platform widgets used to receive input and display data on screen. However, most games don't work with platform widgets. Games typically take over the screen using their own UI elements, and provide their own touch controls. As a result, it's extremely difficult to write instrumented tests for testing games, and Robo test won't know how to navigate the game at all.

To help deal with these challenges with testing games, the Test Lab team has come up with a way for game developers to test their games effectively across many of the devices that Test Lab offers. It's a new type of test called a Game Loop Test, and it's available today in beta.

How does a Game Loop test work?

If you've seen arcade video games operate, you know that they're always showing something on screen, typically some automated demo of the game, called "attract mode". With Firebase Test Lab, game developers can now use this concept of attract mode to construct test scenarios, and Test Lab will arrange for those scenarios to be invoked in sequence. This gives developers the opportunity to test a wide variety of game levels and situations in a single test run on all the devices provided by Test Lab. If there are any problems with a scenario, you'll find out which ones are problematic, so you can focus your efforts on improving that specific case.

Even better, Test Lab now provides performance data with every report. Of particular interest to game developers is a graph of the rendered frame rate over time throughout the test, tied to a video of the device display. This helps you quickly identify the parts of your game that aren't rendering at an acceptable FPS.

In addition to FPS, there are other performance metrics available for all apps. You'll be able to see your app's CPU utilization, memory usage, and network ingress and egress. Notice how you can jump directly to the point in the video where you're observing performance problems.

If you're a game developer, now is a great time to check out Firebase Test Lab for Android to see what it can do to help the quality of your game.

Share: