realm-java: Performance regression in query (nativeSize and nativeGetRow)

Goal

What do you want to achieve?

Upgrade Realm to latest and retain performance

Expected Results

No performance drop

Actual Results

My query which looks like this became slow when updating from 1.2.0 -> 4.0.0-BETA3-SNAPSHOT.

        Date startDate = DateUtils.setToMidnight(date);
        Date endDate = DateUtils.setToEndOfDay(startDate);
        RealmResults<Schedule> schedules = query(realm)
                .beginGroup()
                .beginGroup()
                .lessThan(ScheduleFields.START_TIME, endDate)
                .greaterThanOrEqualTo(ScheduleFields.START_TIME, startDate)
                .endGroup()
                .or()
                .beginGroup()
                .greaterThanOrEqualTo(ScheduleFields.END_TIME, startDate)
                .lessThan(ScheduleFields.START_TIME, endDate)
                .endGroup()
                .endGroup()
                .lessThanOrEqualTo(ScheduleFields.START_TIME, date)
                .equalTo(ScheduleFields.CHANNEL_ID, channel.getId())
                .findAllSorted(ScheduleFields.START_TIME);
        if(!schedules.isEmpty()) {
            return schedules.get(schedules.size() - 1);
        } else {
            return null;
        }

With a schema that looks like this

public class Schedule
        extends RealmObject {
    @PrimaryKey
    private long id;

    private String title;

    @Index
    private String titleLowerCase;

    private long categoryId;

    private String category;

    @Index
    private Date startTime;

    @Index
    private Date endTime;

    private int duration;

    private String ageLimit;

    private long programId;

    private String episodeId;

    @Index
    private long channelId;

    private Channel channel;

    private RealmList<TVGroup> tvGroups;

The query was then reduced to

        Schedule schedule = query(realm)
                .lessThanOrEqualTo(ScheduleFields.START_TIME, date)
                .equalTo(ScheduleFields.CHANNEL_ID, channel.getId())
                .findAllSorted(ScheduleFields.START_TIME, Sort.DESCENDING)
                .first(null); // <-- added this
        if(schedule == null) {
            return null;
        }
        long scheduleStartTime = schedule.getStartTime().getTime();
        long scheduleEndTime = schedule.getEndTime().getTime();

        if((scheduleStartTime < endDate.getTime() && scheduleStartTime >= startDate.getTime())
            || (scheduleEndTime >= startDate.getTime() && scheduleStartTime < endDate.getTime()) ){
            return schedule;
        }
        return null;

But it is still slower in first() than in Realm 2.3.0 (and then slow in Realm 3.0.0)

Version of Realm and tooling

Realm version(s): 1.2.0 -> 4.0.0-BETA3-SNAPSHOT

Realm sync feature enabled: no

Android Studio version: 2.3.3

Which Android version and device: LG Nexus 5X, 8.0.0

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 16 (16 by maintainers)

Commits related to this issue

Most upvoted comments

I’ll test this asap

Well like, previously it was not lagging super-badly while scrolling, and now it does.

But I’ve been doing some method tracing magic and some query optimization

    @Override
    public Schedule getScheduleForChannelWithLastStartTimeBeforeDate(Realm realm, Channel channel, Date date) {
        Date startDate = MiDateUtils.setToMidnight(date);
        Date endDate = MiDateUtils.setToEndOfDay(startDate);
        RealmResults<Schedule> schedules = query(realm)
                .lessThanOrEqualTo(ScheduleFields.START_TIME, date)
                .equalTo(ScheduleFields.CHANNEL_ID, channel.getId())
                .findAllSorted(ScheduleFields.START_TIME);
        if(!schedules.isEmpty()) {
            Schedule schedule = schedules.get(schedules.size() - 1);
            long scheduleStartTime = schedule.getStartTime().getTime();
            long scheduleEndTime = schedule.getEndTime().getTime();
//                .beginGroup()
//                .lessThan(Schedule.Fields.START_TIME.getField(), endDate)
//                .greaterThanOrEqualTo(Schedule.Fields.START_TIME.getField(), startDate)
//                .endGroup()
//                .or()
//                .beginGroup()
//                .greaterThanOrEqualTo(Schedule.Fields.END_TIME.getField(), startDate)
//                .lessThan(Schedule.Fields.START_TIME.getField(), endDate)
//                .endGroup()
            if((scheduleStartTime < endDate.getTime() && scheduleStartTime >= startDate.getTime())
                    || (scheduleEndTime >= startDate.getTime() && scheduleStartTime < endDate.getTime()) ){
                return schedule;
            }
        }
        return null;
    }

Which is now faster, but apparently the real culprit is

io.realm.internal.Collection.nativeSize()
io.realm.internal.Collection.nativeGetRow()

because I’m getting the last element in the RealmResults.

Apparently this is what’s slower now, but I’m not sure why yet. I’ll get the Realm file out.