share code
This commit is contained in:
parent
01f92ed72f
commit
1614d02df0
|
@ -7,7 +7,7 @@ import com.facebook.react.shell.MainReactPackage;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import io.realm.react.RealmReactAndroid;
|
||||
import io.realm.react.RealmReactPackage;
|
||||
|
||||
public class MainActivity extends ReactActivity {
|
||||
|
||||
|
@ -36,8 +36,7 @@ public class MainActivity extends ReactActivity {
|
|||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
return Arrays.<ReactPackage>asList(
|
||||
new MainReactPackage(),
|
||||
new RealmReactPackage()
|
||||
new MainReactPackage(), new RealmReactPackage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,437 @@
|
|||
/**
|
||||
* Sample React Native App
|
||||
* https://github.com/facebook/react-native
|
||||
*/
|
||||
'use strict';
|
||||
import React, {
|
||||
AppRegistry,
|
||||
Component,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
ListView,
|
||||
TouchableHighlight
|
||||
} from 'react-native';
|
||||
|
||||
const Store = require('react-native-store');
|
||||
const SQLite = require('react-native-sqlite-storage');
|
||||
const Realm = require('realm');
|
||||
|
||||
// Make SQLite module use Promises.
|
||||
SQLite.enablePromise(true);
|
||||
|
||||
const TestObjectSchema = {
|
||||
name: "TestObject",
|
||||
properties: {
|
||||
int: "int",
|
||||
double: "double",
|
||||
date: "date",
|
||||
string: "string"
|
||||
}
|
||||
}
|
||||
|
||||
const TestObjectListSchema = {
|
||||
name: "TestObjectList",
|
||||
properties: {
|
||||
list: {type: "list", objectType: "TestObject", default: undefined}
|
||||
}
|
||||
}
|
||||
|
||||
const numTestObjects = 100;
|
||||
const numBatchTestObjects = numTestObjects * 100;
|
||||
const numRepeats = 1;
|
||||
const numQueryBuckets = 5;
|
||||
|
||||
class Tests {
|
||||
async setup(testName) {
|
||||
if (testName == 'enumeration') {
|
||||
await this.batchInsert(this.testObjects(numTestObjects));
|
||||
}
|
||||
if (testName == 'querycount' || testName == 'queryenum') {
|
||||
await this.batchInsert(this.testObjects(numBatchTestObjects));
|
||||
}
|
||||
}
|
||||
|
||||
async binsertions() {
|
||||
await this.batchInsert(this.testObjects(numBatchTestObjects));
|
||||
}
|
||||
|
||||
objectValues(object) {
|
||||
return Object.keys(TestObjectSchema.properties).map((prop) => object[prop])
|
||||
}
|
||||
|
||||
testObjects(count) {
|
||||
let objects = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
objects.push({ int: i % numQueryBuckets, double: i, date: new Date(i), string: "" + i });
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
}
|
||||
|
||||
class RealmTests extends Tests {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = 'Realm';
|
||||
}
|
||||
|
||||
async setup(testName) {
|
||||
Realm.clearTestState();
|
||||
this.realm = new Realm({schema: [TestObjectSchema, TestObjectListSchema]});
|
||||
|
||||
await super.setup(testName);
|
||||
}
|
||||
|
||||
async insertions() {
|
||||
var realm = this.realm;
|
||||
realm.write(() => {
|
||||
for (let i = 0; i < numTestObjects; i++) {
|
||||
realm.create("TestObject", { int: i % numQueryBuckets, double: i, date: new Date(i), string: "" + i });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async batchInsert(objects) {
|
||||
var realm = this.realm;
|
||||
realm.write(() => {
|
||||
realm.create("TestObjectList", { list: objects});
|
||||
});
|
||||
}
|
||||
|
||||
async enumeration() {
|
||||
let objects = this.realm.objects('TestObject');
|
||||
let len = objects.length;
|
||||
var obj;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
|
||||
async querycount() {
|
||||
let objects = this.realm.objects('TestObject', 'int = 0 and double < ' + numTestObjects / 2);
|
||||
let len = objects.length;
|
||||
console.log("length: " + len + " last: ", this.objectValues(objects[len - 1]));
|
||||
}
|
||||
|
||||
async queryenum() {
|
||||
let objects = this.realm.objects('TestObject', 'int = 0 and double < ' + numTestObjects / 2);
|
||||
var obj;
|
||||
let len = objects.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
}
|
||||
|
||||
class RNStoreTests extends Tests {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "RNStore";
|
||||
}
|
||||
|
||||
async setup(testName) {
|
||||
this.db = Store.model('objects');
|
||||
await this.db.destroy();
|
||||
|
||||
await super.setup(testName);
|
||||
}
|
||||
|
||||
async insertions() {
|
||||
for (var obj of this.testObjects(numTestObjects)) {
|
||||
await this.db.add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
async batchInsert(objects) {
|
||||
await this.db.multiAdd(objects);
|
||||
}
|
||||
|
||||
async enumeration() {
|
||||
let objects = await this.db.find();
|
||||
let len = objects.length;
|
||||
var obj;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
|
||||
async querycount() {
|
||||
let objects = await this.db.find({
|
||||
where: {
|
||||
and: [{ int: 0 }, { double: { lt: numTestObjects / 2 } }]
|
||||
},
|
||||
order: {
|
||||
age: 'ASC',
|
||||
}
|
||||
});
|
||||
let len = objects.length;
|
||||
console.log("length: " + len + " last: ", this.objectValues(objects[len - 1]));
|
||||
}
|
||||
|
||||
async queryenum() {
|
||||
let objects = await this.db.find({
|
||||
where: {
|
||||
and: [{ int: 0 }, { double: { lt: numTestObjects / 2 } }]
|
||||
},
|
||||
order: {
|
||||
age: 'ASC',
|
||||
}
|
||||
});
|
||||
let len = objects.length;
|
||||
var obj;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
}
|
||||
|
||||
class RNSqliteTests extends Tests {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "RNSqlite";
|
||||
}
|
||||
|
||||
async setup(testName) {
|
||||
try {
|
||||
await SQLite.deleteDatabase('test.db');
|
||||
} catch (e) {}
|
||||
|
||||
this.db = await SQLite.openDatabase("test.db", "1.0", "Test Database", 200000);
|
||||
|
||||
await this.db.transaction((tx) => {
|
||||
tx.executeSql('CREATE TABLE t1 (string VARCHAR(100), int INTEGER, double REAL, date INTEGER);');
|
||||
});
|
||||
|
||||
await super.setup(testName);
|
||||
}
|
||||
|
||||
async insertions() {
|
||||
await this.db.transaction((tx) => {
|
||||
for (let i = 0; i < numTestObjects; i++) {
|
||||
let values = ["" + i, i % numQueryBuckets, i, new Date(i).getTime()];
|
||||
tx.executeSql('INSERT INTO t1 (string, int, double, date) VALUES (?,?,?,?);', values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async batchInsert(objects) {
|
||||
await this.db.transaction((tx) => {
|
||||
for (var obj of objects) {
|
||||
let values = [obj.string, obj.int, obj.double, obj.date.getTime(), obj.string];
|
||||
tx.executeSql('INSERT INTO t1 (string, int, double, date) VALUES (?,?,?,?);', values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
var allValues = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
var object = this.testObjects[i];
|
||||
var values = Object.keys(object).map((key) => object[key]);
|
||||
Array.prototype.push.apply(allValues, values);
|
||||
}
|
||||
|
||||
await this.db.transaction((tx) => {
|
||||
var sql = "INSERT INTO t1 SELECT ? AS string, ? AS int, ? AS double, ? AS date)" +
|
||||
"UNION ALL SELECT ?, ?, ?, ?".repeat(count - 1);
|
||||
tx.executeSql(sql, allValues);
|
||||
});*/
|
||||
|
||||
async enumeration() {
|
||||
await this.db.readTransaction(async (tx) => {
|
||||
let [, results] = await tx.executeSql('SELECT * FROM t1;')
|
||||
let len = results.rows.length;
|
||||
var row;
|
||||
for (let i = 0; i < len; i++) {
|
||||
row = results.rows.item(i);
|
||||
row.int;
|
||||
row.double;
|
||||
row.string;
|
||||
new Date(row.date);
|
||||
}
|
||||
console.log("length: " + len + " last: ", this.objectValues(row));
|
||||
});
|
||||
}
|
||||
|
||||
async querycount() {
|
||||
await this.db.readTransaction(async (tx) => {
|
||||
let [, results] = await tx.executeSql('SELECT * FROM t1 WHERE int = 0 AND double < ' + numTestObjects/2 + ';');
|
||||
let len = results.rows.length;
|
||||
console.log("length: " + results.rows.length + " last: ", this.objectValues(results.rows.item(len - 1)));
|
||||
});
|
||||
}
|
||||
|
||||
async queryenum() {
|
||||
await this.db.readTransaction(async (tx) => {
|
||||
let [, results] = await tx.executeSql('SELECT * FROM t1 WHERE int = 0 AND double < ' + numTestObjects/2 + ';');
|
||||
let len = results.rows.length;
|
||||
var row;
|
||||
for (let i = 0; i < len; i++) {
|
||||
row = results.rows.item(i);
|
||||
row.int;
|
||||
row.double;
|
||||
row.string;
|
||||
new Date(row.date);
|
||||
}
|
||||
console.log("length: " + len + " last: ", this.objectValues(row));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const tests = ["insertions", "binsertions", "enumeration", "querycount", "queryenum"];
|
||||
const apiTests = [new RealmTests, new RNSqliteTests, new RNStoreTests];
|
||||
|
||||
class ReactNativeBenchmarks extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
dataSource: new ListView.DataSource({
|
||||
rowHasChanged: (row1, row2) => row1 !== row2,
|
||||
}),
|
||||
running: false,
|
||||
};
|
||||
|
||||
this._renderRow = this._renderRow.bind(this);
|
||||
this._runTests = this._runTests.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>
|
||||
ReactNative Storage Benchmarks
|
||||
</Text>
|
||||
<TouchableHighlight style={styles.button} onPress={this._runTests}>
|
||||
<Text style={styles.buttonText}>
|
||||
Run
|
||||
</Text>
|
||||
</TouchableHighlight>
|
||||
<ListView contentContainerStyle={styles.list}
|
||||
dataSource={this.state.dataSource}
|
||||
renderRow={this._renderRow}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderRow(rowData) {
|
||||
return (
|
||||
<Text style={styles.item}>{rowData.join('\t')}</Text>
|
||||
);
|
||||
}
|
||||
|
||||
async _runTests() {
|
||||
if (this.state.running) {
|
||||
console.log("DISABLED");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({running: true});
|
||||
|
||||
try {
|
||||
await this._runTestsAsync();
|
||||
} catch (e) {
|
||||
console.error('Error running tests:', e);
|
||||
}
|
||||
|
||||
this.setState({running: false});
|
||||
}
|
||||
|
||||
async _runTestsAsync() {
|
||||
var data = [apiTests.map((api) => api.name)];
|
||||
for (let test of tests) {
|
||||
data.push([test]);
|
||||
this.setState({
|
||||
dataSource: this.state.dataSource.cloneWithRows(data),
|
||||
});
|
||||
|
||||
for (var apiTest of apiTests) {
|
||||
var totalTime = 0;
|
||||
console.log("Running " + apiTest.name + "." + test);
|
||||
for (var i = 0; i < numRepeats; i++) {
|
||||
await apiTest.setup(test);
|
||||
|
||||
var startTime = Date.now();
|
||||
await apiTest[test]();
|
||||
var endTime = Date.now();
|
||||
|
||||
var time = endTime - startTime
|
||||
console.log("finished in " + time);
|
||||
totalTime += time;
|
||||
}
|
||||
|
||||
data = data.slice();
|
||||
let last = data.length-1;
|
||||
data[last] = data[last].slice();
|
||||
data[last].push(totalTime / numRepeats);
|
||||
|
||||
this.setState({
|
||||
dataSource: this.state.dataSource.cloneWithRows(data),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
textAlign: 'center',
|
||||
margin: 20,
|
||||
},
|
||||
instructions: {
|
||||
textAlign: 'center',
|
||||
color: '#333333',
|
||||
marginBottom: 5,
|
||||
},
|
||||
list: {
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
button: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#CCC',
|
||||
width: 100,
|
||||
height: 40
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
item: {
|
||||
textAlign: 'center',
|
||||
padding: 3,
|
||||
margin: 3,
|
||||
fontSize: 12
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ReactNativeBenchmarks;
|
|
@ -1,437 +1,8 @@
|
|||
/**
|
||||
* Sample React Native App
|
||||
* https://github.com/facebook/react-native
|
||||
*/
|
||||
'use strict';
|
||||
import React, {
|
||||
AppRegistry,
|
||||
Component,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
ListView,
|
||||
TouchableHighlight
|
||||
AppRegistry
|
||||
} from 'react-native';
|
||||
|
||||
const Store = require('react-native-store');
|
||||
const SQLite = require('react-native-sqlite-storage');
|
||||
const Realm = require('realm');
|
||||
|
||||
// Make SQLite module use Promises.
|
||||
SQLite.enablePromise(true);
|
||||
|
||||
const TestObjectSchema = {
|
||||
name: "TestObject",
|
||||
properties: {
|
||||
int: "int",
|
||||
double: "double",
|
||||
date: "date",
|
||||
string: "string"
|
||||
}
|
||||
}
|
||||
|
||||
const TestObjectListSchema = {
|
||||
name: "TestObjectList",
|
||||
properties: {
|
||||
list: {type: "list", objectType: "TestObject", default: undefined}
|
||||
}
|
||||
}
|
||||
|
||||
const numTestObjects = 10000;
|
||||
const numBatchTestObjects = numTestObjects * 100;
|
||||
const numRepeats = 1;
|
||||
const numQueryBuckets = 5;
|
||||
|
||||
class Tests {
|
||||
async setup(testName) {
|
||||
if (testName == 'enumeration') {
|
||||
await this.batchInsert(this.testObjects(numTestObjects));
|
||||
}
|
||||
if (testName == 'querycount' || testName == 'queryenum') {
|
||||
await this.batchInsert(this.testObjects(numBatchTestObjects));
|
||||
}
|
||||
}
|
||||
|
||||
async binsertions() {
|
||||
await this.batchInsert(this.testObjects(numBatchTestObjects));
|
||||
}
|
||||
|
||||
objectValues(object) {
|
||||
return Object.keys(TestObjectSchema.properties).map((prop) => object[prop])
|
||||
}
|
||||
|
||||
testObjects(count) {
|
||||
let objects = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
objects.push({ int: i % numQueryBuckets, double: i, date: new Date(i), string: "" + i });
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
}
|
||||
|
||||
class RealmTests extends Tests {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = 'Realm';
|
||||
}
|
||||
|
||||
async setup(testName) {
|
||||
Realm.clearTestState();
|
||||
this.realm = new Realm({schema: [TestObjectSchema, TestObjectListSchema]});
|
||||
|
||||
await super.setup(testName);
|
||||
}
|
||||
|
||||
async insertions() {
|
||||
var realm = this.realm;
|
||||
realm.write(() => {
|
||||
for (let i = 0; i < numTestObjects; i++) {
|
||||
realm.create("TestObject", { int: i % numQueryBuckets, double: i, date: new Date(i), string: "" + i });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async batchInsert(objects) {
|
||||
var realm = this.realm;
|
||||
realm.write(() => {
|
||||
realm.create("TestObjectList", { list: objects});
|
||||
});
|
||||
}
|
||||
|
||||
async enumeration() {
|
||||
let objects = this.realm.objects('TestObject');
|
||||
let len = objects.length;
|
||||
var obj;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
|
||||
async querycount() {
|
||||
let objects = this.realm.objects('TestObject', 'int = 0 and double < ' + numTestObjects / 2);
|
||||
let len = objects.length;
|
||||
console.log("length: " + len + " last: ", this.objectValues(objects[len - 1]));
|
||||
}
|
||||
|
||||
async queryenum() {
|
||||
let objects = this.realm.objects('TestObject', 'int = 0 and double < ' + numTestObjects / 2);
|
||||
var obj;
|
||||
let len = objects.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
}
|
||||
|
||||
class RNStoreTests extends Tests {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "RNStore";
|
||||
}
|
||||
|
||||
async setup(testName) {
|
||||
this.db = Store.model('objects');
|
||||
await this.db.destroy();
|
||||
|
||||
await super.setup(testName);
|
||||
}
|
||||
|
||||
async insertions() {
|
||||
for (var obj of this.testObjects(numTestObjects)) {
|
||||
await this.db.add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
async batchInsert(objects) {
|
||||
await this.db.multiAdd(objects);
|
||||
}
|
||||
|
||||
async enumeration() {
|
||||
let objects = await this.db.find();
|
||||
let len = objects.length;
|
||||
var obj;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
|
||||
async querycount() {
|
||||
let objects = await this.db.find({
|
||||
where: {
|
||||
and: [{ int: 0 }, { double: { lt: numTestObjects / 2 } }]
|
||||
},
|
||||
order: {
|
||||
age: 'ASC',
|
||||
}
|
||||
});
|
||||
let len = objects.length;
|
||||
console.log("length: " + len + " last: ", this.objectValues(objects[len - 1]));
|
||||
}
|
||||
|
||||
async queryenum() {
|
||||
let objects = await this.db.find({
|
||||
where: {
|
||||
and: [{ int: 0 }, { double: { lt: numTestObjects / 2 } }]
|
||||
},
|
||||
order: {
|
||||
age: 'ASC',
|
||||
}
|
||||
});
|
||||
let len = objects.length;
|
||||
var obj;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
}
|
||||
|
||||
class RNSqliteTests extends Tests {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "RNSqlite";
|
||||
}
|
||||
|
||||
async setup(testName) {
|
||||
try {
|
||||
await SQLite.deleteDatabase('test.db');
|
||||
} catch (e) {}
|
||||
|
||||
this.db = await SQLite.openDatabase("test.db", "1.0", "Test Database", 200000);
|
||||
|
||||
await this.db.transaction((tx) => {
|
||||
tx.executeSql('CREATE TABLE t1 (string VARCHAR(100), int INTEGER, double REAL, date INTEGER);');
|
||||
});
|
||||
|
||||
await super.setup(testName);
|
||||
}
|
||||
|
||||
async insertions() {
|
||||
await this.db.transaction((tx) => {
|
||||
for (let i = 0; i < numTestObjects; i++) {
|
||||
let values = ["" + i, i % numQueryBuckets, i, new Date(i).getTime()];
|
||||
tx.executeSql('INSERT INTO t1 (string, int, double, date) VALUES (?,?,?,?);', values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async batchInsert(objects) {
|
||||
await this.db.transaction((tx) => {
|
||||
for (var obj of objects) {
|
||||
let values = [obj.string, obj.int, obj.double, obj.date.getTime(), obj.string];
|
||||
tx.executeSql('INSERT INTO t1 (string, int, double, date) VALUES (?,?,?,?);', values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
var allValues = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
var object = this.testObjects[i];
|
||||
var values = Object.keys(object).map((key) => object[key]);
|
||||
Array.prototype.push.apply(allValues, values);
|
||||
}
|
||||
|
||||
await this.db.transaction((tx) => {
|
||||
var sql = "INSERT INTO t1 SELECT ? AS string, ? AS int, ? AS double, ? AS date)" +
|
||||
"UNION ALL SELECT ?, ?, ?, ?".repeat(count - 1);
|
||||
tx.executeSql(sql, allValues);
|
||||
});*/
|
||||
|
||||
async enumeration() {
|
||||
await this.db.readTransaction(async (tx) => {
|
||||
let [, results] = await tx.executeSql('SELECT * FROM t1;')
|
||||
let len = results.rows.length;
|
||||
var row;
|
||||
for (let i = 0; i < len; i++) {
|
||||
row = results.rows.item(i);
|
||||
row.int;
|
||||
row.double;
|
||||
row.string;
|
||||
new Date(row.date);
|
||||
}
|
||||
console.log("length: " + len + " last: ", this.objectValues(row));
|
||||
});
|
||||
}
|
||||
|
||||
async querycount() {
|
||||
await this.db.readTransaction(async (tx) => {
|
||||
let [, results] = await tx.executeSql('SELECT * FROM t1 WHERE int = 0 AND double < ' + numTestObjects/2 + ';');
|
||||
let len = results.rows.length;
|
||||
console.log("length: " + results.rows.length + " last: ", this.objectValues(results.rows.item(len - 1)));
|
||||
});
|
||||
}
|
||||
|
||||
async queryenum() {
|
||||
await this.db.readTransaction(async (tx) => {
|
||||
let [, results] = await tx.executeSql('SELECT * FROM t1 WHERE int = 0 AND double < ' + numTestObjects/2 + ';');
|
||||
let len = results.rows.length;
|
||||
var row;
|
||||
for (let i = 0; i < len; i++) {
|
||||
row = results.rows.item(i);
|
||||
row.int;
|
||||
row.double;
|
||||
row.string;
|
||||
new Date(row.date);
|
||||
}
|
||||
console.log("length: " + len + " last: ", this.objectValues(row));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const tests = ["insertions", "binsertions", "enumeration", "querycount", "queryenum"];
|
||||
const apiTests = [new RealmTests, new RNSqliteTests, new RNStoreTests];
|
||||
|
||||
class ReactNativeBenchmarks extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
dataSource: new ListView.DataSource({
|
||||
rowHasChanged: (row1, row2) => row1 !== row2,
|
||||
}),
|
||||
running: false,
|
||||
};
|
||||
|
||||
this._renderRow = this._renderRow.bind(this);
|
||||
this._runTests = this._runTests.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>
|
||||
ReactNative Storage Benchmarks
|
||||
</Text>
|
||||
<TouchableHighlight style={styles.button} onPress={this._runTests}>
|
||||
<Text style={styles.buttonText}>
|
||||
Run
|
||||
</Text>
|
||||
</TouchableHighlight>
|
||||
<ListView contentContainerStyle={styles.list}
|
||||
dataSource={this.state.dataSource}
|
||||
renderRow={this._renderRow}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderRow(rowData) {
|
||||
return (
|
||||
<Text style={styles.item}>{rowData.join('\t')}</Text>
|
||||
);
|
||||
}
|
||||
|
||||
async _runTests() {
|
||||
if (this.state.running) {
|
||||
console.log("DISABLED");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({running: true});
|
||||
|
||||
try {
|
||||
await this._runTestsAsync();
|
||||
} catch (e) {
|
||||
console.error('Error running tests:', e);
|
||||
}
|
||||
|
||||
this.setState({running: false});
|
||||
}
|
||||
|
||||
async _runTestsAsync() {
|
||||
var data = [apiTests.map((api) => api.name)];
|
||||
for (let test of tests) {
|
||||
data.push([test]);
|
||||
this.setState({
|
||||
dataSource: this.state.dataSource.cloneWithRows(data),
|
||||
});
|
||||
|
||||
for (var apiTest of apiTests) {
|
||||
var totalTime = 0;
|
||||
console.log("Running " + apiTest.name + "." + test);
|
||||
for (var i = 0; i < numRepeats; i++) {
|
||||
await apiTest.setup(test);
|
||||
|
||||
var startTime = Date.now();
|
||||
await apiTest[test]();
|
||||
var endTime = Date.now();
|
||||
|
||||
var time = endTime - startTime
|
||||
console.log("finished in " + time);
|
||||
totalTime += time;
|
||||
}
|
||||
|
||||
data = data.slice();
|
||||
let last = data.length-1;
|
||||
data[last] = data[last].slice();
|
||||
data[last].push(totalTime / numRepeats);
|
||||
|
||||
this.setState({
|
||||
dataSource: this.state.dataSource.cloneWithRows(data),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
textAlign: 'center',
|
||||
margin: 20,
|
||||
},
|
||||
instructions: {
|
||||
textAlign: 'center',
|
||||
color: '#333333',
|
||||
marginBottom: 5,
|
||||
},
|
||||
list: {
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
button: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#CCC',
|
||||
width: 100,
|
||||
height: 40
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
item: {
|
||||
textAlign: 'center',
|
||||
padding: 3,
|
||||
margin: 3,
|
||||
fontSize: 12
|
||||
}
|
||||
});
|
||||
const ReactNativeBenchmarks = require('./benchmarks');
|
||||
|
||||
AppRegistry.registerComponent('ReactNativeBenchmarks', () => ReactNativeBenchmarks);
|
|
@ -1,437 +1,8 @@
|
|||
/**
|
||||
* Sample React Native App
|
||||
* https://github.com/facebook/react-native
|
||||
*/
|
||||
'use strict';
|
||||
import React, {
|
||||
AppRegistry,
|
||||
Component,
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
ListView,
|
||||
TouchableHighlight
|
||||
AppRegistry
|
||||
} from 'react-native';
|
||||
|
||||
const Store = require('react-native-store');
|
||||
const SQLite = require('react-native-sqlite-storage');
|
||||
const Realm = require('realm');
|
||||
|
||||
// Make SQLite module use Promises.
|
||||
SQLite.enablePromise(true);
|
||||
|
||||
const TestObjectSchema = {
|
||||
name: "TestObject",
|
||||
properties: {
|
||||
int: "int",
|
||||
double: "double",
|
||||
date: "date",
|
||||
string: "string"
|
||||
}
|
||||
}
|
||||
|
||||
const TestObjectListSchema = {
|
||||
name: "TestObjectList",
|
||||
properties: {
|
||||
list: {type: "list", objectType: "TestObject", default: undefined}
|
||||
}
|
||||
}
|
||||
|
||||
const numTestObjects = 10000;
|
||||
const numBatchTestObjects = numTestObjects * 100;
|
||||
const numRepeats = 1;
|
||||
const numQueryBuckets = 5;
|
||||
|
||||
class Tests {
|
||||
async setup(testName) {
|
||||
if (testName == 'enumeration') {
|
||||
await this.batchInsert(this.testObjects(numTestObjects));
|
||||
}
|
||||
if (testName == 'querycount' || testName == 'queryenum') {
|
||||
await this.batchInsert(this.testObjects(numBatchTestObjects));
|
||||
}
|
||||
}
|
||||
|
||||
async binsertions() {
|
||||
await this.batchInsert(this.testObjects(numBatchTestObjects));
|
||||
}
|
||||
|
||||
objectValues(object) {
|
||||
return Object.keys(TestObjectSchema.properties).map((prop) => object[prop])
|
||||
}
|
||||
|
||||
testObjects(count) {
|
||||
let objects = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
objects.push({ int: i % numQueryBuckets, double: i, date: new Date(i), string: "" + i });
|
||||
}
|
||||
return objects;
|
||||
}
|
||||
}
|
||||
|
||||
class RealmTests extends Tests {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = 'Realm';
|
||||
}
|
||||
|
||||
async setup(testName) {
|
||||
Realm.clearTestState();
|
||||
this.realm = new Realm({schema: [TestObjectSchema, TestObjectListSchema]});
|
||||
|
||||
await super.setup(testName);
|
||||
}
|
||||
|
||||
async insertions() {
|
||||
var realm = this.realm;
|
||||
realm.write(() => {
|
||||
for (let i = 0; i < numTestObjects; i++) {
|
||||
realm.create("TestObject", { int: i % numQueryBuckets, double: i, date: new Date(i), string: "" + i });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async batchInsert(objects) {
|
||||
var realm = this.realm;
|
||||
realm.write(() => {
|
||||
realm.create("TestObjectList", { list: objects});
|
||||
});
|
||||
}
|
||||
|
||||
async enumeration() {
|
||||
let objects = this.realm.objects('TestObject');
|
||||
let len = objects.length;
|
||||
var obj;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
|
||||
async querycount() {
|
||||
let objects = this.realm.objects('TestObject', 'int = 0 and double < ' + numTestObjects / 2);
|
||||
let len = objects.length;
|
||||
console.log("length: " + len + " last: ", this.objectValues(objects[len - 1]));
|
||||
}
|
||||
|
||||
async queryenum() {
|
||||
let objects = this.realm.objects('TestObject', 'int = 0 and double < ' + numTestObjects / 2);
|
||||
var obj;
|
||||
let len = objects.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
}
|
||||
|
||||
class RNStoreTests extends Tests {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "RNStore";
|
||||
}
|
||||
|
||||
async setup(testName) {
|
||||
this.db = Store.model('objects');
|
||||
await this.db.destroy();
|
||||
|
||||
await super.setup(testName);
|
||||
}
|
||||
|
||||
async insertions() {
|
||||
for (var obj of this.testObjects(numTestObjects)) {
|
||||
await this.db.add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
async batchInsert(objects) {
|
||||
await this.db.multiAdd(objects);
|
||||
}
|
||||
|
||||
async enumeration() {
|
||||
let objects = await this.db.find();
|
||||
let len = objects.length;
|
||||
var obj;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
|
||||
async querycount() {
|
||||
let objects = await this.db.find({
|
||||
where: {
|
||||
and: [{ int: 0 }, { double: { lt: numTestObjects / 2 } }]
|
||||
},
|
||||
order: {
|
||||
age: 'ASC',
|
||||
}
|
||||
});
|
||||
let len = objects.length;
|
||||
console.log("length: " + len + " last: ", this.objectValues(objects[len - 1]));
|
||||
}
|
||||
|
||||
async queryenum() {
|
||||
let objects = await this.db.find({
|
||||
where: {
|
||||
and: [{ int: 0 }, { double: { lt: numTestObjects / 2 } }]
|
||||
},
|
||||
order: {
|
||||
age: 'ASC',
|
||||
}
|
||||
});
|
||||
let len = objects.length;
|
||||
var obj;
|
||||
for (let i = 0; i < len; i++) {
|
||||
obj = objects[i];
|
||||
obj.int;
|
||||
obj.double;
|
||||
obj.date;
|
||||
obj.string;
|
||||
}
|
||||
console.log("Enumerated " + len + " last: ", this.objectValues(obj));
|
||||
}
|
||||
}
|
||||
|
||||
class RNSqliteTests extends Tests {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = "RNSqlite";
|
||||
}
|
||||
|
||||
async setup(testName) {
|
||||
try {
|
||||
await SQLite.deleteDatabase('test.db');
|
||||
} catch (e) {}
|
||||
|
||||
this.db = await SQLite.openDatabase("test.db", "1.0", "Test Database", 200000);
|
||||
|
||||
await this.db.transaction((tx) => {
|
||||
tx.executeSql('CREATE TABLE t1 (string VARCHAR(100), int INTEGER, double REAL, date INTEGER);');
|
||||
});
|
||||
|
||||
await super.setup(testName);
|
||||
}
|
||||
|
||||
async insertions() {
|
||||
await this.db.transaction((tx) => {
|
||||
for (let i = 0; i < numTestObjects; i++) {
|
||||
let values = ["" + i, i % numQueryBuckets, i, new Date(i).getTime()];
|
||||
tx.executeSql('INSERT INTO t1 (string, int, double, date) VALUES (?,?,?,?);', values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async batchInsert(objects) {
|
||||
await this.db.transaction((tx) => {
|
||||
for (var obj of objects) {
|
||||
let values = [obj.string, obj.int, obj.double, obj.date.getTime(), obj.string];
|
||||
tx.executeSql('INSERT INTO t1 (string, int, double, date) VALUES (?,?,?,?);', values);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
var allValues = [];
|
||||
for (let i = 0; i < count; i++) {
|
||||
var object = this.testObjects[i];
|
||||
var values = Object.keys(object).map((key) => object[key]);
|
||||
Array.prototype.push.apply(allValues, values);
|
||||
}
|
||||
|
||||
await this.db.transaction((tx) => {
|
||||
var sql = "INSERT INTO t1 SELECT ? AS string, ? AS int, ? AS double, ? AS date)" +
|
||||
"UNION ALL SELECT ?, ?, ?, ?".repeat(count - 1);
|
||||
tx.executeSql(sql, allValues);
|
||||
});*/
|
||||
|
||||
async enumeration() {
|
||||
await this.db.readTransaction(async (tx) => {
|
||||
let [, results] = await tx.executeSql('SELECT * FROM t1;')
|
||||
let len = results.rows.length;
|
||||
var row;
|
||||
for (let i = 0; i < len; i++) {
|
||||
row = results.rows.item(i);
|
||||
row.int;
|
||||
row.double;
|
||||
row.string;
|
||||
new Date(row.date);
|
||||
}
|
||||
console.log("length: " + len + " last: ", this.objectValues(row));
|
||||
});
|
||||
}
|
||||
|
||||
async querycount() {
|
||||
await this.db.readTransaction(async (tx) => {
|
||||
let [, results] = await tx.executeSql('SELECT * FROM t1 WHERE int = 0 AND double < ' + numTestObjects/2 + ';');
|
||||
let len = results.rows.length;
|
||||
console.log("length: " + results.rows.length + " last: ", this.objectValues(results.rows.item(len - 1)));
|
||||
});
|
||||
}
|
||||
|
||||
async queryenum() {
|
||||
await this.db.readTransaction(async (tx) => {
|
||||
let [, results] = await tx.executeSql('SELECT * FROM t1 WHERE int = 0 AND double < ' + numTestObjects/2 + ';');
|
||||
let len = results.rows.length;
|
||||
var row;
|
||||
for (let i = 0; i < len; i++) {
|
||||
row = results.rows.item(i);
|
||||
row.int;
|
||||
row.double;
|
||||
row.string;
|
||||
new Date(row.date);
|
||||
}
|
||||
console.log("length: " + len + " last: ", this.objectValues(row));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const tests = ["insertions", "binsertions", "enumeration", "querycount", "queryenum"];
|
||||
const apiTests = [new RealmTests, new RNSqliteTests, new RNStoreTests];
|
||||
|
||||
class ReactNativeBenchmarks extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
dataSource: new ListView.DataSource({
|
||||
rowHasChanged: (row1, row2) => row1 !== row2,
|
||||
}),
|
||||
running: false,
|
||||
};
|
||||
|
||||
this._renderRow = this._renderRow.bind(this);
|
||||
this._runTests = this._runTests.bind(this);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>
|
||||
ReactNative Storage Benchmarks
|
||||
</Text>
|
||||
<TouchableHighlight style={styles.button} onPress={this._runTests}>
|
||||
<Text style={styles.buttonText}>
|
||||
Run
|
||||
</Text>
|
||||
</TouchableHighlight>
|
||||
<ListView contentContainerStyle={styles.list}
|
||||
dataSource={this.state.dataSource}
|
||||
renderRow={this._renderRow}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
_renderRow(rowData) {
|
||||
return (
|
||||
<Text style={styles.item}>{rowData.join('\t')}</Text>
|
||||
);
|
||||
}
|
||||
|
||||
async _runTests() {
|
||||
if (this.state.running) {
|
||||
console.log("DISABLED");
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({running: true});
|
||||
|
||||
try {
|
||||
await this._runTestsAsync();
|
||||
} catch (e) {
|
||||
console.error('Error running tests:', e);
|
||||
}
|
||||
|
||||
this.setState({running: false});
|
||||
}
|
||||
|
||||
async _runTestsAsync() {
|
||||
var data = [apiTests.map((api) => api.name)];
|
||||
for (let test of tests) {
|
||||
data.push([test]);
|
||||
this.setState({
|
||||
dataSource: this.state.dataSource.cloneWithRows(data),
|
||||
});
|
||||
|
||||
for (var apiTest of apiTests) {
|
||||
var totalTime = 0;
|
||||
console.log("Running " + apiTest.name + "." + test);
|
||||
for (var i = 0; i < numRepeats; i++) {
|
||||
await apiTest.setup(test);
|
||||
|
||||
var startTime = Date.now();
|
||||
await apiTest[test]();
|
||||
var endTime = Date.now();
|
||||
|
||||
var time = endTime - startTime
|
||||
console.log("finished in " + time);
|
||||
totalTime += time;
|
||||
}
|
||||
|
||||
data = data.slice();
|
||||
let last = data.length-1;
|
||||
data[last] = data[last].slice();
|
||||
data[last].push(totalTime / numRepeats);
|
||||
|
||||
this.setState({
|
||||
dataSource: this.state.dataSource.cloneWithRows(data),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#F5FCFF',
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
textAlign: 'center',
|
||||
margin: 20,
|
||||
},
|
||||
instructions: {
|
||||
textAlign: 'center',
|
||||
color: '#333333',
|
||||
marginBottom: 5,
|
||||
},
|
||||
list: {
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'column',
|
||||
flexWrap: 'wrap',
|
||||
},
|
||||
button: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#CCC',
|
||||
width: 100,
|
||||
height: 40
|
||||
},
|
||||
row: {
|
||||
flexDirection: 'row',
|
||||
},
|
||||
item: {
|
||||
textAlign: 'center',
|
||||
padding: 3,
|
||||
margin: 3,
|
||||
fontSize: 12
|
||||
}
|
||||
});
|
||||
const ReactNativeBenchmarks = require('./benchmarks');
|
||||
|
||||
AppRegistry.registerComponent('ReactNativeBenchmarks', () => ReactNativeBenchmarks);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"start": "react-native start"
|
||||
},
|
||||
"dependencies": {
|
||||
"react-native": "^0.18.0",
|
||||
"react-native": "0.18.0",
|
||||
"react-native-sqlite-storage": "^2.1.3",
|
||||
"react-native-store": "^0.4.1",
|
||||
"realm": "file:../.."
|
||||
|
|
Loading…
Reference in New Issue