JSON data file performance

I’m using Twine 2 to create a ‘choose your own adventure’ type story, and I’m outputting the text and structure as a JSON file. I’m reading/decoding the JSON file and then reading from the Lua table (I think, I might be mistaken) with each page render to get the text.

The issue I find is that the pause before rendering is noticeable (in the simulator) and the scrollview is sluggish compared to getting text from a Lua table. Can anyone advise how I can improve this? How would I go about copying out relevant data from the JSON file to a Lua table (if that would lead to better performance)? Any tips would be greatly appreciated.

I’m not sure if ‘t’ below is a Lua table, or why using that would lead to slower performance.

Here’s an excerpt of what i have:

[lua]

local json = require “json”

–Read/decode the json file

local jsonFile = function( filename, base )

if not base then base = system.ResourceDirectory; end

local path = system.pathForFile( filename, base )

local contents

local file = io.open( path, “r” )

if file then

  contents = file:read( “*a” )

  io.close( file )

end

return contents

end

– Create Lua table from JSON file?

local t = json.decode( jsonFile( “data2.json” ) )

– An example of accessing a data value from t

print (t[“passages”][2][‘text’])

[/lua]

Once I have access to the JSON text values I’m rendering them inside a scrollview:

[lua]

local group = display.newGroup()

local scrollView = widget.newScrollView

{

   top = display.screenOriginY,

   left = 0,

   width = display.actualContentWidth,

   height = display.actualContentHeight,

   scrollWidth = display.actualContentWidth,

   scrollHeight = 8000,

   backgroundColor = { 0.05, 0.05, 0.05 },

   --hideBackground = true,

   horizontalScrollDisabled = true,

   friction = 0.95,

   hideScrollBar = true,

   bottomPadding = 30

}

local options = 

{

   text = (t[“passages”][#num][“text”]),

   width = display.actualContentWidth-30,

   font = native.newFont( “Paciencia-Regular”, 32 ),

   fontSize = 15,

   align = “left”,

   parent = group

}

local paragraph = display.newText( options )

paragraph.anchorX = 0.5

paragraph.anchorY = 0

paragraph.x = display.actualContentWidth/2

paragraph.y = 380

paragraph:setFillColor( 0.95, 0.95, 0.95 )

scrollView:insert( paragraph )

[/lua]

So are you using json.decode every time you draw a new scrollView, or just once at the beginning?

‘t’ is a lua table, but if you’re re-populating it each time that might cause a delay. Might be better to import all your text into lua tables right at the beginning.

Hi Nick, thank you very much for your advice. I moved the json.decode to the beginning and that helped. I might have another issue because I notice the Corona simulator seems to slow down if I keep reloading rather than closing down and restarting - but you put me on the right track.

There is no hit in loading hundreds of JSON entries into a local table and referencing that throughout your project.  Avoid file I/O if possible and only do it once.

If your JSON data file is massive (i.e. thousands of rows of text) then lazy load it on demand for better performance.

Hi Adrian, thanks. Maybe a silly question but what do you mean by ‘lazy load’?

Once the JSON data is in a Lua table, I’m getting values, for example, by:

[lua]

local rawText = _G.t[“passages”][number][“text”]

[/lua]

Where ‘number’ is a variable, e.g. ‘2’.

(yes, I’m using _G - I could’t get it to work otherwise.)

And at the risk of straying from my original question, any idea how I can check if a value exists in the table?

I’m trying:

[lua]

if ( _G.t[“passages”][number][“links”][3][“link”] ~= nil )

   then optionThreeExists = true

end

[/lua]

but this gives the following error:

Attempt to index field ‘?’ (a nil value)

So are you using json.decode every time you draw a new scrollView, or just once at the beginning?

‘t’ is a lua table, but if you’re re-populating it each time that might cause a delay. Might be better to import all your text into lua tables right at the beginning.

Hi Nick, thank you very much for your advice. I moved the json.decode to the beginning and that helped. I might have another issue because I notice the Corona simulator seems to slow down if I keep reloading rather than closing down and restarting - but you put me on the right track.

There is no hit in loading hundreds of JSON entries into a local table and referencing that throughout your project.  Avoid file I/O if possible and only do it once.

If your JSON data file is massive (i.e. thousands of rows of text) then lazy load it on demand for better performance.

Hi Adrian, thanks. Maybe a silly question but what do you mean by ‘lazy load’?

Once the JSON data is in a Lua table, I’m getting values, for example, by:

[lua]

local rawText = _G.t[“passages”][number][“text”]

[/lua]

Where ‘number’ is a variable, e.g. ‘2’.

(yes, I’m using _G - I could’t get it to work otherwise.)

And at the risk of straying from my original question, any idea how I can check if a value exists in the table?

I’m trying:

[lua]

if ( _G.t[“passages”][number][“links”][3][“link”] ~= nil )

   then optionThreeExists = true

end

[/lua]

but this gives the following error:

Attempt to index field ‘?’ (a nil value)