9

How can I measure the FPS of my ListView?

See the slides 13-17 from http://code.google.com/events/io/2010/sessions/world-of-listview-android.html.

Mostafa
  • 26,886
  • 10
  • 57
  • 52
Erdal
  • 1,472
  • 3
  • 16
  • 33

2 Answers2

2

I don't know about calculating FPS (I guess that should be done system-wide and is not calculated per view), but you can use Hierarchy Viewer to profile performance of each View. It gives you time needed to measure, calculate layout of, and draw each View in milliseconds, and helps you to find slow View objects by showing yellow and red circles indicating bad performance.

Mostafa
  • 26,886
  • 10
  • 57
  • 52
0

You might be interested in this ListAdapter, which will wrap another ListAdapter and print out log statements about how many views were displayed per second.

import android.database.DataSetObserver;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListAdapter;

public class VpsAdapter implements ListAdapter {
    protected int vpsViewCount = 0;
    protected long vpsStartTimeNanos = System.nanoTime();
    protected ListAdapter delegate;

    public VpsAdapter(ListAdapter delegate) {
        super();
        this.delegate = delegate;
    }

    public void resetViewsPerSecond() {
        vpsViewCount = 0;
        vpsStartTimeNanos = System.nanoTime();
    }

    public double getViewsPerSecond() {
        final long now = System.nanoTime();
        return (vpsViewCount / (double)(now - vpsStartTimeNanos)) * 1e9;
    }

    public int getViewsPerSecondViewCount() {
        return vpsViewCount;
    }

    @Override
    public boolean areAllItemsEnabled() {
        return delegate.areAllItemsEnabled();
    }

    @Override
    public int getCount() {
        return delegate.getCount();
    }

    @Override
    public Object getItem(int i) {
        return delegate.getItem(i);
    }

    @Override
    public long getItemId(int i) {
        return delegate.getItemId(i);
    }

    @Override
    public int getItemViewType(int i) {
        return delegate.getItemViewType(i);
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ++vpsViewCount;
        Log.d("VpsAdapter", String.format("VpsAdapter: %.2f views per second (%s views)", getViewsPerSecond(), getViewsPerSecondViewCount()));
        return delegate.getView(i, view, viewGroup);
    }

    @Override
    public int getViewTypeCount() {
        return delegate.getViewTypeCount();
    }

    @Override
    public boolean hasStableIds() {
        return delegate.hasStableIds();
    }

    @Override
    public boolean isEmpty() {
        return delegate.isEmpty();
    }

    @Override
    public boolean isEnabled(int i) {
        return delegate.isEnabled(i);
    }

    @Override
    public void registerDataSetObserver(DataSetObserver dataSetObserver) {
        delegate.registerDataSetObserver(dataSetObserver);
    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver dataSetObserver) {
        delegate.unregisterDataSetObserver(dataSetObserver);
    }
}

To use, simply wrap your existing ListAdapter in a VpsAdapter, eg.

setListAdapter( new VpsAdapter( myAdapter ) );

Then call resetViewsPerSecond() when you're ready to start timing, and getViewsPerSecond() when you're ready to retrieve the result. The adapter will also log to the console the current vps for every call to getView().

I use this adapter in conjunction with ListView.smoothScrollTo( adapter.getCount()-1 ) in order to programmatically scroll the listview to the bottom and get the average vps.

emmby
  • 99,783
  • 65
  • 191
  • 249