我正在为我的下一个项目评估Realm数据库(Android)。我决定编写一个测试应用程序来插入100万个对象并检查Realm数据库的性能。测试应用程序是一个简单的Android应用程序。 用户可以指定要创建的特定模型类的随机对象的数量,并在后台的IntentService中创建对象。在创建对象时,活动将显示领域中的对象总数。
IntentService,用于创建随机对象。
package example.com.realmcrashapplication;
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import io.realm.Realm;
public class BackendService extends IntentService {
public static final String TASK_DETAILS = "taskDetails";
public static final String INSERTION_COUNT = "insertionCount";
private static final int insertsPerTransaction = 1000;
private int remainingInsertions = 0;
public BackendService() {
super(BackendService.class.getName());
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle args = intent.getBundleExtra(TASK_DETAILS);
if(args != null) {
if(args.containsKey(INSERTION_COUNT)){
final int count = args.getInt(INSERTION_COUNT);
if(count>0){
remainingInsertions = count;
while(remainingInsertions>0){
final int c;
if(remainingInsertions>insertsPerTransaction){
c=insertsPerTransaction;
}else{
c=remainingInsertions;
}
Realm realm = Realm.getDefaultInstance();
final Person p = Person.getRandomPerson();
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
for(int i=0;i<c;++i) {
realm.copyToRealm(p);
}
}
});
realm.close();
remainingInsertions-=c;
}
}
}
}
}
}
每当我尝试创建超过100k的对象(我的目标是创建100万个对象)时,应用程序崩溃时会出现以下错误。注意:内存消耗(从Android监视器看到)在8.0MB到11MB之间变化插入。
example.com.realmcrashapplication D/REALM: jni: ThrowingException 11, mmap() failed: Out of memory size: 671088640 offset: 0 in io_realm_internal_SharedGroup.cpp line 188, .
example.com.realmcrashapplication D/REALM: Exception has been throw: Unrecoverable error. mmap() failed: Out of memory size: 671088640 offset: 0 in io_realm_internal_SharedGroup.cpp line 188
example.com.realmcrashapplication W/dalvikvm: threadid=13: thread exiting with uncaught exception (group=0x41bc2c08)
example.com.realmcrashapplication E/AndroidRuntime: FATAL EXCEPTION: IntentService[example.com.realmcrashapplication.BackendService]
Process: example.com.realmcrashapplication, PID: 27140
io.realm.exceptions.RealmError: Unrecoverable error. mmap() failed: Out of memory size: 671088640 offset: 0 in io_realm_internal_SharedGroup.cpp line 188
at io.realm.internal.SharedGroup.nativeCommitAndContinueAsRead(Native Method)
at io.realm.internal.SharedGroup.commitAndContinueAsRead(SharedGroup.java:149)
at io.realm.internal.ImplicitTransaction.commitAndContinueAsRead(ImplicitTransaction.java:62)
at io.realm.internal.SharedGroupManager.commitAndContinueAsRead(SharedGroupManager.java:118)
at io.realm.BaseRealm.commitTransaction(BaseRealm.java:362)
at io.realm.BaseRealm.commitTransaction(BaseRealm.java:349)
at io.realm.Realm.commitTransaction(Realm.java:121)
at io.realm.Realm.executeTransaction(Realm.java:967)
at example.com.realmcrashapplication.BackendService.onHandleIntent(BackendService.java:42)
at android.app.IntentService$ServiceHandler.handleMessage(IntentService.java:65)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.os.HandlerThread.run(HandlerThread.java:61)
我已经尝试将每个事务的插入次数从1000减少到10,但结果是一样的。我的手机中有足够的空间。所以它不是关于存储我猜。 100K插入后的文件大小超过600MB(在145K对象后为704MB)
Realm Library 1.0.1 Android Java
测试:三星Galaxy Note 2 Android 4.4.2 API 19。
模型类
人
package example.com.realmcrashapplication;
import java.util.Date;
import io.realm.RealmList;
import io.realm.RealmObject;
public class Person extends RealmObject{
private int field1;
private String field2;
private Date field3;
private String field4;
private Date field5;
private String field6;
private String field7;
private int field8;
private double field9;
private String field10;
private int field11;
private int field12;
private double field13;
private double field14;
private int field15;
private String field16;
private double field17;
private boolean field18;
private String field19;
private double field20;
private boolean field21;
private boolean field22;
private int field23;
private ExtraInfo1 field24;
private ExtraInfo1 field25;
private ExtraInfo1 field26;
private ExtraInfo1 field27;
private ExtraInfo1 field28;
private RealmList<ExtraInfo2> field29;
private Integer field30;
private String field31;
private String field32;
private String field33;
private String field34;
private String field35;
private String field36;
private Address field37;
private boolean field38;
private Date field39;
private int field40;
private int field41;
private double field42;
private double field43;
private String field44;
private String field45;
private String field46;
private Address field47;
private int field48;
private String field49;
private Date field50;
private String field51;
private boolean field52;
private RealmList<ExtraInfo3> field53;
private double field54;
private double field55;
private double field56;
private RealmList<Person> family;
public void setField1(int field1) {
this.field1 = field1;
}
public void setField2(String field2) {
this.field2 = field2;
}
public void setField3(Date field3) {
this.field3 = field3;
}
public void setField4(String field4) {
this.field4 = field4;
}
public void setField5(Date field5) {
this.field5 = field5;
}
public void setField6(String field6) {
this.field6 = field6;
}
public void setField7(String field7) {
this.field7 = field7;
}
public void setField8(int field8) {
this.field8 = field8;
}
public void setField9(double field9) {
this.field9 = field9;
}
public void setField10(String field10) {
this.field10 = field10;
}
public void setField11(int field11) {
this.field11 = field11;
}
public void setField12(int field12) {
this.field12 = field12;
}
public void setField13(double field13) {
this.field13 = field13;
}
public void setField14(double field14) {
this.field14 = field14;
}
public void setField15(int field15) {
this.field15 = field15;
}
public void setField16(String field16) {
this.field16 = field16;
}
public void setField17(double field17) {
this.field17 = field17;
}
public void setField18(boolean field18) {
this.field18 = field18;
}
public void setField19(String field19) {
this.field19 = field19;
}
public void setField20(double field20) {
this.field20 = field20;
}
public void setField21(boolean field21) {
this.field21 = field21;
}
public void setField22(boolean field22) {
this.field22 = field22;
}
public void setField23(int field23) {
this.field23 = field23;
}
public void setField24(ExtraInfo1 field24) {
this.field24 = field24;
}
public void setField25(ExtraInfo1 field25) {
this.field25 = field25;
}
public void setField26(ExtraInfo1 field26) {
this.field26 = field26;
}
public void setField27(ExtraInfo1 field27) {
this.field27 = field27;
}
public void setField28(ExtraInfo1 field28) {
this.field28 = field28;
}
public void setField29(RealmList<ExtraInfo2> field29) {
this.field29 = field29;
}
public void setField30(Integer field30) {
this.field30 = field30;
}
public void setField31(String field31) {
this.field31 = field31;
}
public void setField32(String field32) {
this.field32 = field32;
}
public void setField33(String field33) {
this.field33 = field33;
}
public void setField34(String field34) {
this.field34 = field34;
}
public void setField35(String field35) {
this.field35 = field35;
}
public void setField36(String field36) {
this.field36 = field36;
}
public void setField37(Address field37) {
this.field37 = field37;
}
public void setField38(boolean field38) {
this.field38 = field38;
}
public void setField39(Date field39) {
this.field39 = field39;
}
public void setField40(int field40) {
this.field40 = field40;
}
public void setField41(int field41) {
this.field41 = field41;
}
public void setField42(double field42) {
this.field42 = field42;
}
public void setField43(double field43) {
this.field43 = field43;
}
public void setField44(String field44) {
this.field44 = field44;
}
public void setField45(String field45) {
this.field45 = field45;
}
public void setField46(String field46) {
this.field46 = field46;
}
public void setField47(Address field47) {
this.field47 = field47;
}
public void setField48(int field48) {
this.field48 = field48;
}
public void setField49(String field49) {
this.field49 = field49;
}
public void setField50(Date field50) {
this.field50 = field50;
}
public void setField51(String field51) {
this.field51 = field51;
}
public void setField52(boolean field52) {
this.field52 = field52;
}
public void setField53(RealmList<ExtraInfo3> field53) {
this.field53 = field53;
}
public void setField54(double field54) {
this.field54 = field54;
}
public void setField55(double field55) {
this.field55 = field55;
}
public void setField56(double field56) {
this.field56 = field56;
}
public void setFamily(RealmList<Person> family) {
this.family = family;
}
public static Person getRandomPerson(){
Person p = new Person();
p.setField1(9);
p.setField2(HelperClass.getRandomString(15));
p.setField3(HelperClass.getRandomDate());
p.setField4(HelperClass.getRandomString(15));
p.setField5(HelperClass.getRandomDate());
p.setField6(HelperClass.getRandomString(24));
p.setField7(HelperClass.getRandomString(100));
p.setField8(9);
p.setField9(0.567);
p.setField10(HelperClass.getRandomString(3));
p.setField11(9);
p.setField12(1);
p.setField13(45.00);
p.setField14(0);
p.setField15(1);
p.setField16(HelperClass.getRandomString(15));
p.setField17(5);
p.setField18(true);
p.setField19(HelperClass.getRandomString(15));
p.setField20(5);
p.setField21(true);
p.setField22(true);
p.setField23(5);
p.setField24(ExtraInfo1.getRandomExtraInfo1());
p.setField25(ExtraInfo1.getRandomExtraInfo1());
p.setField26(ExtraInfo1.getRandomExtraInfo1());
p.setField27(ExtraInfo1.getRandomExtraInfo1());
p.setField28(ExtraInfo1.getRandomExtraInfo1());
RealmList<ExtraInfo2> extraInfo2Items = new RealmList<>();
for (int i = 0; i < 10; ++i) {
ExtraInfo2 extraInfo2 = ExtraInfo2.getRandomExtraInfo2();
extraInfo2Items.add(extraInfo2);
}
p.setField29(extraInfo2Items);
p.setField30(1);
p.setField31(HelperClass.getRandomString(24));
p.setField32(HelperClass.getRandomString(24));
p.setField33(HelperClass.getRandomString(10));
p.setField34(HelperClass.getRandomString(10));
p.setField35(HelperClass.getRandomString(128));
p.setField36(HelperClass.getRandomString(10));
p.setField37(Address.getRandomAddress());
p.setField38(true);
p.setField39(HelperClass.getRandomDate());
p.setField40(1);
p.setField41(1);
p.setField42(10);
p.setField43(0.00);
p.setField44(HelperClass.getRandomString(24));
p.setField45(HelperClass.getRandomString(100));
p.setField46(HelperClass.getRandomString(30));
p.setField47(Address.getRandomAddress());
p.setField48(30);
p.setField49(HelperClass.getRandomString(30));
p.setField50(HelperClass.getRandomDate());
p.setField51(HelperClass.getRandomString(100));
p.setField52(true);
RealmList<ExtraInfo3> extraInfo3List = new RealmList<>();
for (int i = 0; i < 5; ++i) {
ExtraInfo3 extraInfo3 = ExtraInfo3.getRandomExtraInfo3();
extraInfo3List.add(extraInfo3);
}
p.setField53(extraInfo3List);
p.setField54(100);
p.setField55(100);
p.setField56(0);
return p;
}
}
地址
package example.com.realmcrashapplication;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;
import io.realm.RealmObject;
public class Address extends RealmObject{
private String line1;
private String line2;
private String zip;
private String city;
private String state;
private String country;
private int type;
public String getLine1() {
return line1;
}
public void setLine1(String line1) {
this.line1 = line1;
}
public String getLine2() {
return line2;
}
public void setLine2(String line2) {
this.line2 = line2;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public static Address getRandomAddress(){
Address a = new Address();
a.setLine1(HelperClass.getRandomString(49));
a.setLine2(HelperClass.getRandomString(49));
a.setZip(HelperClass.getRandomString(10));
a.setCity(HelperClass.getRandomString(24));
a.setState(HelperClass.getRandomString(20));
a.setCountry(HelperClass.getRandomString(30));
a.setType(1);
return a;
}
}
ExtraInfo1
package example.com.realmcrashapplication;
import io.realm.RealmObject;
public class ExtraInfo1 extends RealmObject {
private String field1;
private boolean field2;
private int field3;
private int field4;
private double field5;
private double field6;
private int field7;
private boolean field8;
private String field9;
private double field10;
private String field11;
private double field12;
private boolean field13;
public void setField1(String field1) {
this.field1 = field1;
}
public void setField2(boolean field2) {
this.field2 = field2;
}
public void setField3(int field3) {
this.field3 = field3;
}
public void setField4(int field4) {
this.field4 = field4;
}
public void setField5(double field5) {
this.field5 = field5;
}
public void setField6(double field6) {
this.field6 = field6;
}
public void setField7(int field7) {
this.field7 = field7;
}
public void setField8(boolean field8) {
this.field8 = field8;
}
public void setField9(String field9) {
this.field9 = field9;
}
public void setField10(double field10) {
this.field10 = field10;
}
public void setField11(String field11) {
this.field11 = field11;
}
public void setField12(double field12) {
this.field12 = field12;
}
public void setField13(boolean field13) {
this.field13 = field13;
}
public static ExtraInfo1 getRandomExtraInfo1(){
ExtraInfo1 info = new ExtraInfo1();
info.setField1(HelperClass.getRandomString(10));
info.setField2(true);
info.setField3(1);
info.setField4(1);
info.setField5(0);
info.setField6(0);
info.setField7(1);
info.setField8(true);
info.setField9(HelperClass.getRandomString(15));
info.setField10(5);
info.setField11(HelperClass.getRandomString(15));
info.setField12(5);
info.setField13(true);
return info;
}
}
ExtraInfo2
package example.com.realmcrashapplication;
import io.realm.RealmObject;
public class ExtraInfo2 extends RealmObject {
private int field1;
private String field2;
private double field3;
private boolean field4;
private double field5;
private String field6;
private double field7;
private int field8;
private double field9;
private double field10;
private String field11;
private boolean field12;
private String field13;
private double field14;
private String field15;
private double field16;
private boolean field17;
public void setField1(int field1) {
this.field1 = field1;
}
public void setField2(String field2) {
this.field2 = field2;
}
public void setField3(double field3) {
this.field3 = field3;
}
public void setField4(boolean field4) {
this.field4 = field4;
}
public void setField5(double field5) {
this.field5 = field5;
}
public void setField6(String field6) {
this.field6 = field6;
}
public void setField7(double field7) {
this.field7 = field7;
}
public void setField8(int field8) {
this.field8 = field8;
}
public void setField9(double field9) {
this.field9 = field9;
}
public void setField10(double field10) {
this.field10 = field10;
}
public void setField11(String field11) {
this.field11 = field11;
}
public void setField12(boolean field12) {
this.field12 = field12;
}
public void setField13(String field13) {
this.field13 = field13;
}
public void setField14(double field14) {
this.field14 = field14;
}
public void setField15(String field15) {
this.field15 = field15;
}
public void setField16(double field16) {
this.field16 = field16;
}
public void setField17(boolean field17) {
this.field17 = field17;
}
public static ExtraInfo2 getRandomExtraInfo2(){
ExtraInfo2 extraInfo2 = new ExtraInfo2();
extraInfo2.setField1(1);
extraInfo2.setField2(HelperClass.getRandomString(15));
extraInfo2.setField3(18.0);
extraInfo2.setField4(true);
extraInfo2.setField5(9.0);
extraInfo2.setField6("value");
extraInfo2.setField7(1.0);
extraInfo2.setField8(1);
extraInfo2.setField9(0.0);
extraInfo2.setField10(0.0);
extraInfo2.setField11(HelperClass.getRandomString(100));
extraInfo2.setField12(true);
extraInfo2.setField13(HelperClass.getRandomString(15));
extraInfo2.setField14(5);
extraInfo2.setField15(HelperClass.getRandomString(15));
extraInfo2.setField16(5);
extraInfo2.setField17(true);
return extraInfo2;
}
}
ExtraInfo3
package example.com.realmcrashapplication;
import java.util.Date;
import io.realm.RealmObject;
public class ExtraInfo3 extends RealmObject {
private Date field1;
private int field2;
private String field3;
private double field4;
private String field5;
private String field6;
public void setField1(Date field1) {
this.field1 = field1;
}
public void setField2(int field2) {
this.field2 = field2;
}
public void setField3(String field3) {
this.field3 = field3;
}
public void setField4(double field4) {
this.field4 = field4;
}
public void setField5(String field5) {
this.field5 = field5;
}
public void setField6(String field6) {
this.field6 = field6;
}
public static ExtraInfo3 getRandomExtraInfo3(){
ExtraInfo3 extraInfo3 = new ExtraInfo3();
extraInfo3.setField1(HelperClass.getRandomDate());
extraInfo3.setField2(1);
extraInfo3.setField3(HelperClass.getRandomString(10));
extraInfo3.setField4(10.00);
extraInfo3.setField5(HelperClass.getRandomString(10));
extraInfo3.setField6(HelperClass.getRandomString(24));
return extraInfo3;
}
}
MainActivity
package example.com.realmcrashapplication;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.Window;
import android.widget.TextView;
import io.realm.Realm;
import io.realm.RealmChangeListener;
import io.realm.RealmResults;
import io.realm.Sort;
public class MainActivity extends AppCompatActivity {
private Realm realm;
private RealmResults<Person> persons;
private RealmChangeListener personsChangeListener;
private TextView personCountTextView;
private Intent backgroundIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
personCountTextView = (TextView)findViewById(R.id.personCountText);
TextView locationText = (TextView)findViewById(R.id.locationText);
locationText.setText(MyApplication.location);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
InsertPersonsDialogFragment newFragment = new InsertPersonsDialogFragment();
newFragment.setClickListener(new InsertPersonsDialogFragment.ClickListener() {
@Override
public void onInsertItems(int count) {
insertPersons(count);
}
});
newFragment.show(getSupportFragmentManager(), "insertPersonsDialog");
}
});
backgroundIntent = new Intent(MainActivity.this,BackendService.class);
}
@Override
public void onStart() {
super.onStart();
realm = Realm.getDefaultInstance();
persons = realm.where(Person.class).findAllSortedAsync("field3", Sort.DESCENDING);
personsChangeListener = new RealmChangeListener<RealmResults<Person>>() {
@Override
public void onChange(final RealmResults<Person> personsList) {
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if(personCountTextView!=null) {
String size = Integer.toString(personsList.size());
personCountTextView.setText("Number of persons : "+size);
}
}
});
}
};
persons.addChangeListener(personsChangeListener);
}
@Override
public void onStop() {
super.onStop();
if(personsChangeListener!=null){
realm.removeChangeListener(personsChangeListener);
}
realm.close();
}
private void insertPersons(final int count) {
Bundle args = new Bundle();
args.putInt(BackendService.INSERTION_COUNT, count);
backgroundIntent.putExtra(BackendService.TASK_DETAILS, args);
startService(backgroundIntent);
}
}
所有MyApplication
public class MyApplication extends Application {
public static String location = "";
@Override
public void onCreate() {
super.onCreate();
File dir = new File("/sdcard/realm2");
if(!dir.exists()){
dir.mkdirs();
}
location = dir.getAbsolutePath();
RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(dir).
deleteRealmIfMigrationNeeded().
build();
Realm.setDefaultConfiguration(realmConfiguration);
}
}