Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Mockup & CodeGen, iPhone & iPad
($9.99)

Make your own iPhone apps
and run them live!
(free)

Manu
($0.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 11-29-2009, 05:13 PM   #1 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 67
Question sqlite3 memory and performance tips

Hi,

I know there's many threads on this great forum regarding sqlite3 memory but my situation is different.

I'm using sqlite3 as a dictionary for a word game (like Twisty Text).
Every time the player double taps, the word is checked to see if it exists in the dictionary sqlite file. Currently, I'm opening and closing the database for every single query. I do use the reset, finalize and close statements after the prepare statements in the WordQuery() function.

I notice that as the game progresses and more queries are performed, my app becomes very sluggish on 3GS 3.1.2 and crashes with memory error on 3G 3.0. If i let the game run w/o using any query, I don't run into memory issue as bad as using the queries.

My first thought is to speedup the sql lookup by passing the wordlength as well was the word.

What would be the correct sql statement to search an existence of a word given the word and its length?

Another thought, as recommended by others on this forum, is to open the database on application launch and and only close it when application exists?
I know that memory will be higher but will it level off?
What will this memory be given a database file of 2mb?

My other question is how does sqlite3 work on the iphone?
Does it load the entire database and access it as a memory or only load certain portion of data like regular SQL? In other words, does the iphone treat the database just like any other file?

For example, if my sqlite file is about 2mb. when opening this database does it occupy 2mb or more?

This is what I've noticed after a quick test:
The time it takes loading and grabbing 100 words from a database of 183,000 words vs 9,400 on iphone 3G 3.0 and iphone 3GS 3.1.2
(the 3GS test only uses the 9,400 database)
I rebooted the 3G for every test, and exited and relaunched for 3GS

(Time in seconds)
Trial -----------3G 3.0 (183,000) -------3G 3.0 (9,400)---- 3GS 3.1.2 (9,400)
1----------------------3.9s-------------------2.9s----------------1.1s
2----------------------3.5s-------------------3.1s----------------1.4s
3----------------------3.9s-------------------3.0s----------------1.1s


I apologize for the lengthy post but I thought it would be easier to keep it in one post.

Please share your thoughts and experience regarding sqlite performance and memory. (how do you set up sqlite from cvs file, indexing (ascending?), etc)

Thanks,

-FerrariX
FerrariX is offline   Reply With Quote
Old 11-29-2009, 06:15 PM   #2 (permalink)
Registered Member
 
Join Date: Nov 2009
Location: London
Posts: 226
Default

Quote:
Originally Posted by FerrariX View Post
What would be the correct sql statement to search an existence of a word given the word and its length?
If you're going to do this, it's probably best to create a separate "word length" column in your database. Asking SQLite to calculate the length of each word every time you query is likely to slow things down further.

Quote:
Another thought, as recommended by others on this forum, is to open the database on application launch and and only close it when application exists?
I know that memory will be higher but will it level off?
What will this memory be given a database file of 2mb?

My other question is how does sqlite3 work on the iphone?
Does it load the entire database and access it as a memory or only load certain portion of data like regular SQL? In other words, does the iphone treat the database just like any other file?
I believe (but I can't find a supporting web page at the moment) that SQLite mem-maps its datafile. This is faster than loading it all into memory and means that the VM system is free to free up memory when it's not in use.

Also, I don't think that the overhead of keeping the database open through out your application will out weigh the speed bump you get by not having to open it each time you want to look something up, so do that.

What's your table schema like? If you're worried about performance, that's probably the first place to look. A quick Google found this page on optimising SQLite. I suggest that as a minimum you employ the UNIQUE keyword for your word column (although this will probably result in a slightly larger database file).

(But having typed all that.. for my word game "Lexical", I used a custom binary-tree like structure which was a little more complicated to set up but faster to work with and compressed about 50,000 words of seven letters or less into about 560k.)
__________________
SimCap - Simple iPhone and iPad Simulator screen capture
_sjc_ is offline   Reply With Quote
Old 11-29-2009, 07:03 PM   #3 (permalink)
Registered Member
 
opetopic's Avatar
 
Join Date: Nov 2009
Location: Brooklyn, NY
Posts: 83
Default

I too am working on a word game, however I am not having the issues you described. I open the database each time I query (160,000+ words, 6mb), and it runs fine on a 1st gen ipod touch (3.0 firmware). I of course have an index on my word column (which doubles the size of the db), but it is not a unique index (for various reasons).

Are you sure you are closing all results and the database? You could try using the FMDB wrapper of sqlite (trunk/fmdb - flycode - Project Hosting on Google Code), which takes care of the closing/finalizing crap for you.
__________________
Opetopic
IsoWords (iTunes)
Twitter @opetopic
opetopic is offline   Reply With Quote
Old 11-29-2009, 07:08 PM   #4 (permalink)
Registered Member
 
opetopic's Avatar
 
Join Date: Nov 2009
Location: Brooklyn, NY
Posts: 83
Default

Hey, I just looked at your numbers... that definitely does not look right. Post your table schema.
__________________
Opetopic
IsoWords (iTunes)
Twitter @opetopic
opetopic is offline   Reply With Quote
Old 11-29-2009, 08:14 PM   #5 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 67
Default

Quote:
Originally Posted by _sjc_ View Post
If you're going to do this, it's probably best to create a separate "word length" column in your database. Asking SQLite to calculate the length of each word every time you query is likely to slow things down further.
Thanks for your help sjc,

I check for the word length first to see if the length >= 3, then also check to see if it also exists in AlreadyFound[], if both of these conditions are met, then I send it to Query function.

Please tell me what is the statement to check if the word exist by passing it the word and its length.

Quote:
I believe (but I can't find a supporting web page at the moment) that SQLite mem-maps its datafile. This is faster than loading it all into memory and means that the VM system is free to free up memory when it's not in use.
this is great , i don't have to worry about db size that much.

Quote:
What's your table schema like? If you're worried about performance, that's probably the first place to look. A quick Google found this page on optimising SQLite. I suggest that as a minimum you employ the UNIQUE keyword for your word column (although this will probably result in a slightly larger database file).

(But having typed all that.. for my word game "Lexical", I used a custom binary-tree like structure which was a little more complicated to set up but faster to work with and compressed about 50,000 words of seven letters or less into about 560k.)
Thanks for the link. Would you please explain the UNIQUE key word?
I will definitely try the bst once I get the simple sqlite working properly.

Thanks again,

-Ferrari
FerrariX is offline   Reply With Quote
Old 11-29-2009, 08:40 PM   #6 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 67
Default

Quote:
Originally Posted by opetopic View Post
Hey, I just looked at your numbers... that definitely does not look right. Post your table schema.
Hi opetopic,
Thanks for your help

The numbers is not for just grabbing the 100 words from the database. It initializes variables among other things. For those tests, I've kept everything the same except changing the database size to see how it would affect speed.

I use two SQLite files, one is for dictionary and the other for word selection that has been randomized. I randomized the second database of words so the iPhone doesn't have to do this processing, just select a chunk of word from a randomly chosen starting index. Would it be better to combined the randomized table into the dictionary table as another column?
I know this will increase the size.

The Dictionary database is the one I send queries to.
I use Sqlite Manager pluggin for FireFox to create my Sqlite database.

I choose to import the cvs file then give it a table name "EnglishD"
then selected "First row contain name columns" and left everything default.
I then clicked okay. it then ask me if i want to modify it. I click okay.
Under Define column, my column names are word and length
I change the data type to TEXT, should I make this int? any gain in performance?

There is an option for "allow null", should I check that or not? I left it default as checked.

I then created an index and selected "Ascending" for both columns.

I guess my schema would be a column of unique words shorted in ascending order and another column with length also sorted in ascending order.

Is it acceptable for me to post sqlite file on this forum?

Thanks for all your help,

-FerrariX
FerrariX is offline   Reply With Quote
Old 11-29-2009, 09:10 PM   #7 (permalink)
Registered Member
 
opetopic's Avatar
 
Join Date: Nov 2009
Location: Brooklyn, NY
Posts: 83
Default

I don't think you need a separate database for randomized words. It isn't worth the extra space when there are easy ways to do it. First, do you select the 100 random words seldom (say at the beginning of a game)? If so, then you might be able to get away with the following query for getting 100 random words:

Code:
SELECT * FROM words ORDER BY RANDOM() LIMIT 100
This is usually a no-no, but with only ~150,000 the execution time should be negligible.

Also, drop the length column as it will not speed up your queries. If your columns are properly indexed searching for a word should be instant. Further, change the "word" column's data type to VARCHAR.

You say that you have an ASCENDING index on both the word column and length column. Such an index will be used only if you are using BOTH of those columns in an AND clause in your query. Just put one ASCENDING index on the word column.

Finally, after doing all of this run the VACUUM command on your database (I believe this is under Database > Compact Database in the Firefox extension you mentioned). See if that helps any...

P.S. I don't see any reason why you couldn't upload the sqlite file, but I don't know if the forum has attachment size restrictions.
__________________
Opetopic
IsoWords (iTunes)
Twitter @opetopic
opetopic is offline   Reply With Quote
Old 11-29-2009, 09:52 PM   #8 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 67
Default

Thank you for advice and time, opetopic,

I only select the 100 random words once during start up unless the player has used up all the words. I should've said scrambled words instead of randomized. They are randomly sorted in a column.

The scrambled words are what appear the beginning of each level.
For example, the word PERFORMANCE may appear as OMRPRECENA.
I do this for infinite mode (no timer).

Can you or anyone else suggest a different tool to for working with SQLite?

There's a 97.7kb limit for file attachment.
I'll find someway to link it.

-FerrariX
FerrariX is offline   Reply With Quote
Old 11-30-2009, 04:18 AM   #9 (permalink)
Registered Member
 
Join Date: Nov 2009
Location: London
Posts: 226
Default

Quote:
Originally Posted by FerrariX View Post
Can you or anyone else suggest a different tool to for working with SQLite?
I use this SQLite Database Browser.
__________________
SimCap - Simple iPhone and iPad Simulator screen capture
_sjc_ is offline   Reply With Quote
Old 12-01-2009, 09:33 PM   #10 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 67
Default

Quote:
Originally Posted by _sjc_ View Post
Thanks for the link sjc,
FerrariX is offline   Reply With Quote
Old 12-01-2009, 09:38 PM   #11 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 67
Default

Quote:
Originally Posted by opetopic View Post
I don't think you need a separate database for randomized words. It isn't worth the extra space when there are easy ways to do it. First, do you select the 100 random words seldom (say at the beginning of a game)? If so, then you might be able to get away with the following query for getting 100 random words:

Code:
SELECT * FROM words ORDER BY RANDOM() LIMIT 100
This is usually a no-no, but with only ~150,000 the execution time should be negligible.

Also, drop the length column as it will not speed up your queries. If your columns are properly indexed searching for a word should be instant. Further, change the "word" column's data type to VARCHAR.

You say that you have an ASCENDING index on both the word column and length column. Such an index will be used only if you are using BOTH of those columns in an AND clause in your query. Just put one ASCENDING index on the word column.

Finally, after doing all of this run the VACUUM command on your database (I believe this is under Database > Compact Database in the Firefox extension you mentioned). See if that helps any...

P.S. I don't see any reason why you couldn't upload the sqlite file, but I don't know if the forum has attachment size restrictions.
Hi opetopic,

i'm back with more quesitons (work was overwhelming yesterday, not complaining, it's good to still have a job nowadays)

This is the link for my sqlite file, I have not ran VACCUM yet:

RapidShare: 1-CLICK Web hosting - Easy Filehosting

So it would also be better if I combined my dictionaries for other languages into one sqlite file and just use multiple columns?

Please let me know if my sqlite file is missing something such as KEYWORD.

Thanks again for all your help,

-FerrariX
FerrariX is offline   Reply With Quote
Old 12-02-2009, 01:04 AM   #12 (permalink)
Registered Member
 
opetopic's Avatar
 
Join Date: Nov 2009
Location: Brooklyn, NY
Posts: 83
Default

You sqlite file actually looks fine ... I changed your word column to be a VARCHAR, and then compacted it and it reduced the file size by half, but I guess that is not necessary.

Perhaps you should post the code that is running slowly as I do not have any more ideas.

Also, I do _not_ think you should combine multiple languages into one table. You could combine them into one sqlite file but many tables if you wanted, or just keep it as separate sqlite files.
__________________
Opetopic
IsoWords (iTunes)
Twitter @opetopic
opetopic is offline   Reply With Quote
Old 12-03-2009, 11:25 AM   #13 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 67
Default

Hi opetopic,

Thanks for your help.

I'm currently pulling words from the table as text.
Will changing it to VARCHAR affect or break my code?

-FerrariX
FerrariX is offline   Reply With Quote
Old 12-03-2009, 11:39 AM   #14 (permalink)
Registered Member
 
Join Date: Nov 2009
Location: London
Posts: 226
Default

Quote:
Originally Posted by FerrariX View Post
Will changing it to VARCHAR affect or break my code?
It shouldn't make any difference at all, since SQLite doesn't actually have an explicit VARCHAR storage type, only TEXT.
__________________
SimCap - Simple iPhone and iPad Simulator screen capture
_sjc_ is offline   Reply With Quote
Old 12-03-2009, 12:56 PM   #15 (permalink)
Registered Member
 
opetopic's Avatar
 
Join Date: Nov 2009
Location: Brooklyn, NY
Posts: 83
Default

Quote:
Originally Posted by _sjc_ View Post
It shouldn't make any difference at all, since SQLite doesn't actually have an explicit VARCHAR storage type, only TEXT.
Ah, interesting!
__________________
Opetopic
IsoWords (iTunes)
Twitter @opetopic
opetopic is offline   Reply With Quote
Old 12-03-2009, 08:44 PM   #16 (permalink)
Registered Member
 
Join Date: Jun 2009
Posts: 67
Default

Thanks for the replies
FerrariX is offline   Reply With Quote
Reply

Bookmarks

Tags
memory, performance, sqlite

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Stats
Members: 158,884
Threads: 89,229
Posts: 380,763
Top Poster: BrianSlick (7,129)
Welcome to our newest member, karlam963
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 02:17 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0