realm-js: React Native realm bulk insert to local database is slower than expected

Expected Results

Branching off of #2009

To create and insert 1000 documents, and in the long run, 35000+ documents in to a local realm db (currently an android device) in a quick timeframe using Realm’s JavaScript, React Native api layer.

This all call and mapping will only happen on initial app login & load in order to support an offline first methodology.

Actual Results

Took ~47 seconds to create and insert 1000 objects into realm local db when performing a benchmark.

I’ve found the following https://stackoverflow.com/questions/29214236/how-to-add-1-milion-items-in-realm-correctly question on StackOverflow - upon looking in to the proposed solutions and through some of the other Realm language’s API docs, such as Java, it looks like there are methods exposed that the JavaScript layer doesn’t have access to - could this be my problem?

I was hoping to use this over an SQLite localDB solution b/c zero-copy sounds extremely beneficial long term.

Any suggestions on how I would speed this up? Thanks!

Steps to Reproduce

The code sample below will show my:

  • Instantiation of the local realm db and the schema of the object I am mapping in
  • The current methodology with which I’ve attempted the benchmark. I’ve also tried w a begin/commitTransaction implementation but the results seemed the same.

Code Sample

Instantiation

import Realm from 'realm';
import { ListingsAllCall } from '../utils';

// Only 2 non optional properties: lid, pid, lat && ldt
const ListingsAllCallSchema = {
  name: ListingsAllCall,
  properties: {
    ad1: 'string?',
    age: 'string?',
    agp: 'string?',
    agt: 'string?',
    aid: 'string?',
    bbc: 'string?',
    bed: 'int?',
    bkg: 'string?',
    bld: 'string?',
    bmt: 'bool?',
    bth: 'int?',
    cpl: 'bool?',
    cty: 'string?',
    dom: 'string?',
    dty: 'string?',
    esl: 'string?',
    est: 'string?',
    hfe: 'int?',
    hoa: 'bool?',
    hsl: 'string?',
    img: { type: 'string[]', optional: true },
    lat: 'float',
    ldt: 'string',
    lid: 'string?',
    lon: 'float?',
    lsz: 'int?',
    ltp: 'string?',
    lvl: 'int?',
    mls: 'string?',
    mod: 'string?',
    msl: 'string?',
    num: 'string?',
    opr: 'int?',
    pid: 'string',
    pkc: 'int?',
    pkg: 'int?',
    pks: 'int?',
    pol: 'bool?',
    pps: 'float?',
    pri: 'int?',
    ptp: 'string?',
    rmk: 'string?',
    sdp: 'int?',
    sds: 'string?',
    sft: 'int?',
    sid: 'int?',
    ste: 'string?',
    str: 'int?',
    sub: 'string?',
    syn: 'bool?',
    xad: 'bool?',
    yrb: 'int?',
    zip: 'string?'
  }
};

const realmConfigs = {
  schema: [ListingsAllCallSchema]
};

export default new Realm(realmConfigs);


Implementation


import realm from '../configs/realm';

export const handleListingsAllCall = async data => {
  console.log('Map all call');
  console.log(data);

  try {
   //Items is an array of objects. The ListingsAllCall in the realm.create method is the exact schema to be mapped to
  const { items } = data;

  realm.write(() => {
    console.log('ListingAllCall map to realm start.');

    // The following takes 47 seconds to complete.
    items.forEach(obj => {
      realm.create(ListingsAllCall, obj);
     });
   });

   let t1 = performance.now();
   console.log(`Finished writing in ${(t1 - t0) / 1000} seconds...`);
  } catch (err) {
    console.log(err);
  }
};

Redux Async Action Dispatch

export const initialListingsAllCall = () => {
  return async dispatch => {
    const result = await listingsActiveAllCallAPI();
    await handleListingsAllCall(result);
    dispatch({ type: INITIAL_LISTINGS_ALL_CALL });
  };
};

Version of Realm and Tooling

  • Realm JS SDK Version: 2.17.0
  • Node or React Native: React Native 0.57.3
  • Client OS & Version: Mohave
  • Which debugger for React Native: Chrome console

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Comments: 37 (15 by maintainers)

Most upvoted comments

Ok I think I know what you are running into. You are testing this is a debugger/browser? realm-js is terrible slow when debugged. But when you run it normally - it’s fast.

const Realm = require('realm')

Realm.open({
    schema: [{
        name: 'Page',
        properties: {
            id: 'int'
        }
    }]
}).then(realm => {
    console.time('nothing')
    console.timeEnd('nothing')

    console.time('warmup')
    realm.write(() => {
        for (let i = 0; i < 10; i++) {
            realm.create('Page', {id: 5})
        }
    })
    console.timeEnd('warmup')

    for (let objects=0; objects<=1000; objects+=100) {
        let test = 'Objects ' + objects
        console.time(test)
        realm.write(() => {
            for (let i = 0; i < 100; i++) {
                realm.create('Page', {id: 5})
            }
        });
        console.timeEnd(test)
    }

    process.exit()
});

If I run this in node (on an old macbook) I get this:

nothing: 0.058ms
warmup: 0.946ms
Objects 0: 1.361ms
Objects 100: 0.810ms
Objects 200: 1.023ms
Objects 300: 1.201ms
Objects 400: 1.019ms
Objects 500: 0.964ms
Objects 600: 0.778ms
Objects 700: 0.693ms
Objects 800: 0.710ms
Objects 900: 0.686ms
Objects 1000: 0.816ms

so around 1 ms for 100 objects.

Hope this helps you 😃

@bmunkholm MUCH faster using a test flight build (not debug) that was it thanks!

You can already call Realm.delete() on a Realm.Results instance that contains multiple objects, such as a query like realm.objects(...).filtered(...). In any case, deleting a single object is fast enough because there’s no data transfer from JavaScript to C++.