dexie/Dexie.js

Performance limitations or incorrect usage?

Open

#721 创建于 2018年6月22日

在 GitHub 查看
 (6 评论) (8 反应) (0 负责人)JavaScript (10,304 star) (625 fork)batch import
Help wanted

描述

I've been working with dexie for a few months now, it's integrated into a large web application which I'm intending to launch in the next few months, and I'm concerned about the performance that I'm seeing from reads to the indexeddb. I'll try to lay out the scenario as best as possible because I'm very worried about the scaling issues I'm seeing.

When we display data, we are seeing ~ 250ms to do a series of lookups / pseudo-joins from the local database - what concerns me is that I can get our local server to do the same lookups, with a return, 10x faster - this sort of defeats any reason to use local data storage outside of persistence.

As a note, I'm not terribly interested in persisting this data past a refresh - It would be a bonus. But my primary concern is performance. At 250ms + the time it takes to render these items, the frontend isn't performing as well as I want - there's a visible lag or stutter, and the app doesn't feel responsive.

Right now the database has roughly 500 objects in it, spread across a dozen or so tables.

I'm really looking for help to figure out what we're doing wrong, or if we've hit a hard limit with indexeddb / dexie and should look to replace the library with something else. This won't be a minor refactor, and I'll need to commit a few days to replacing it.

We instantiate the database like this:

//Global namespaced object that contains dexie and a lot of different classes / references
var Alpaca =
{
 class_example : new ClassWhatever(),
 db : new Dexie('appname'),
 models: {
  users: new Users(),
  things: new Things(),
  thing_attachments: new ThingAttachments() //etc -- we have around a dozen of these
 }
}

//Loop through classes (which have table names, fields, etc), and use those to generate the Dexie schema
var schema = {};

for(var model in Alpaca.models)
{
    schema[Alpaca.models[model].schema.table_name] = Alpaca.models[model].schema.fields
    Alpaca.tables.push(Alpaca.models[model].schema.table_name) //Array of tables with the table name, ie ["users","things","thing_attachments"]
}

Alpaca.db.version(1).stores(schema)
Alpaca.db.open();
//Db is now open - and we do a series of bulkPuts to populate it once the server returns the initial data

We load the data, and then do a call like this when switching view contexts:

var query = {creation_context:'context',context_id:'some_id'}
Alpaca.db.things.where(query).toArray(things => 
{
  Alpaca.models.things.get_mappedthings(things).then(mapped_things =>
  {
   //Have mapped things (this takes about 250ms to get to this point) 
   //After this we use that data to render about 100 items and bulk append them to the dom
  })
})

Here's what our mapping looks like, roughly - And it's where we're seeing the major slowdown

get_mappedthings(things)
{
 return Alpaca.db.transaction('r',Alpaca.tables,function()
 {
  //We run a series of simple conditionals, and then join in data as needed from other tables
  //About 10 of these run, but for brevity I've only included one
  // We utilize get(), where(), count() and where().or() queries
  for(var i = 0;i < things.length;i++)
  {
   let thing = things[i]
   if(thing.some_condition)
   {
    Alpaca.db.users.get({some_key:thing.some_value}).then(function(value){thing.whatever = value})
   }
  }
 }).then(function()
 {
  return things
})
}

So my big questions are, is there anything obvious that we're doing wrong. If not, did we make a bad choice choosing dexie? Is there anything we could possibly do to speed this stuff up or are we looking at a refactor into something else to make this work?

I'm pretty desperate to squeeze the performance out - any help is appreciated!

贡献者指南