node-java icon indicating copy to clipboard operation
node-java copied to clipboard

The performance for using jdbc to get data from database

Open 10229428 opened this issue 3 years ago • 1 comments

The table in database for testing has 80000+ records. I use Java and nodejs with 'node-java' to test the cost separately.

1、 Use Java code,the simplest code,only contains get data:

try {
	long begin = System.currentTimeMillis();
	Class.forName(DRIVER);
	Connection conn = DriverManager.getConnection(URL);
	String sql = "select * from dim_ci limit 100000;";
	Statement statement = conn.createStatement();
	ResultSet resultSet = statement.executeQuery(sql);

	ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
	int columnCount = resultSetMetaData.getColumnCount();
	System.out.println("column count ===========> " + columnCount);

	List<MetaData> colsMetadata = new ArrayList<>();
	for (int i = 1; i <= columnCount; i++) {
		colsMetadata.add(new MetaData(resultSetMetaData.getColumnLabel(i), resultSetMetaData.getColumnType(i)));
	}

	long mid = System.currentTimeMillis();
	System.out.println("query cost ===========> " + (mid - begin));

	List<Object> data = new ArrayList<>();
	while (resultSet.next()) {
		List<Object> row = new ArrayList<>();
		for (MetaData metadata : colsMetadata) {
			String value = resultSet.getString(metadata.label);
			row.add(value);
		}
		data.add(row);
	}
	System.out.println("convert cost ===========> " + (System.currentTimeMillis() - mid));
	System.out.println("data ===========> " + data.size());

	resultSet.close();
	statement.close();
	conn.close();
} catch (Exception e) {
	e.printStackTrace();
}

The result is: image The convert cost is only 364 ms。

2、Use nodejs codes in file test.js:

const jinst = require("./jinst");

if (!jinst.isJvmCreated()) {
    jinst.addOption("-Xrs");
    jinst.addAsyncOption({
        asyncSuffix: "Async",
        syncSuffix: "",
        ifReadOnlySuffix: "_alt"
    })
    jinst.setupClasspath(['./gbase-connector-java-8.3.81.53-build55.2.1-bin.jar']);
}
const java = jinst.getInstance();

(async () => {
    let conn, statement, resultSet;
    try {
        conn = await getConnection();
        statement = conn.createStatement();

        const time1 = +new Date();
        resultSet = statement.executeQuery("select * from dim_ci limit 100000;");
        const resultSetMetadata = resultSet.getMetaData();
        const colCount = resultSetMetadata.getColumnCount();
        const colsMetadata = new Array(colCount).fill(0).map((item, i) => ({
            label: resultSetMetadata.getColumnLabel(i + 1),
            type: resultSetMetadata.getColumnType(i + 1)
        }));
        const time2 = +new Date();
        console.log('query cost =====> ', time2 - time1, ', column count: ', colCount);

        const allData = [];
        while (resultSet.next()) {
            const data = colsMetadata.map(cmd => resultSet.getString(cmd.label));
            allData.push(data);
        }
        console.log(' get data =====> ', allData.length, ', cost: ', +new Date() - time2);
    } catch (e) {
        console.error(e);
    } finally {
        if (statement) {
            statement.close();
        }
        if (resultSet) {
            resultSet.close;
        }
        if (conn) {
            conn.close();
        }
    }
})();

async function getConnection() {
    return new Promise(resolve => {
        const url = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
        java.callStaticMethod("java.sql.DriverManager", "getConnection", url, function (err, conn) {
            if (err) {
                console.error('failed to get connection: ', err);
            }
            resolve(conn);
        });
    });
}

codes in file jinst.js:

var java = require('java');

function isJvmCreated() {
    return typeof java.onJvmCreated !== 'function';
}

var jinst = module.exports = {
    isJvmCreated: function () {
        return isJvmCreated();
    },
    addOption: function (option) {
        if (!isJvmCreated() && option) {
            java.options.push(option);
        } else if (isJvmCreated()) {
            console.error("You've tried to add an option to an already running JVM!");
            console.error("This isn't currently supported.  Please add all option entries before calling any java methods");
            console.error("You can test for a running JVM with the isJvmCreated funtion.");
        }
    },
    addAsyncOption: function (option) {
        if (!isJvmCreated() && option) {
            java.asyncOptions = java.asyncOptions || {};
            for(let props in option) {
                java.asyncOptions[props] = option[props];
            }
        } else if (isJvmCreated()) {
            console.error("You've tried to add an option to an already running JVM!");
            console.error("This isn't currently supported.  Please add all option entries before calling any java methods");
            console.error("You can test for a running JVM with the isJvmCreated funtion.");
        }
    },
    setupClasspath: function (dependencyArr) {
        if (!isJvmCreated() && dependencyArr) {
            java.classpath.push.apply(java.classpath, dependencyArr);
        } else if (isJvmCreated()) {
            console.error("You've tried to add an entry to the classpath of an already running JVM!");
            console.error("This isn't currently supported.  Please add all classpath entries before calling any java methods");
            console.error("You can test for a running JVM with the isJvmCreated funtion.");
        }
    },
    getInstance: function () {
        return java;
    }
};

Then, the result is : image

The time overhead of using nodejs is almost 80 times that of using Java directly! Is this performance overhead normal? Or am I using it the wrong way? Thanks!

10229428 avatar Mar 16 '22 07:03 10229428

@joeferner Any help please? Thanks!

10229428 avatar Mar 22 '22 04:03 10229428