我正在做一个小项目/测试,在那里我接受一个large文本输入并处理它以创建一个文本输出。 为此,我开始使用本地 SQLite db 和 JDBC lib(因为我在 Java 中这样做)。
问题是(出于某种原因)内存(RAM使用)随着输入的增加而不断增加,但是我需要程序使用非常有限的HEAP。
虽然该程序适用于我的测试用例,但它并没有以最佳方式运行,也就是说没有按预期运行。
上图不好的原因是因为我的数据库存储在本地,我只在需要时提取选定数量的 (100) 个数据库条目,所以无论出于何种原因,HEAP 或它的使用都应该增加。 我还想稍后添加线程以提高处理速度,因为当我从写入 RAM 切换到写入本地文件时,执行速度从 14 秒直线下降到 10 分钟。 班级: 主要 -> https://pastebin.com/rh27xsqr
import java.io.*;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("input.txt"));
BufferedWriter writer = new BufferedWriter(new FileWriter("output.txt"));
Connection connection = DriverManager.getConnection("jdbc:sqlite:temp.db")) {
Class.forName("org.sqlite.JDBC");
Table table = new Table(connection);
String line = reader.readLine();
while (line != null) {
String[] command = line.split(",");
switch (command[0]) {
case "u":
int apples = Integer.parseInt(command[1]);
int size = Integer.parseInt(command[2]);
switch (command[3]) {
case "bid":
table.setBids(apples, size);
break;
case "ask":
table.setAsks(apples, size);
break;
}
break;
case "q":
String data = "";
switch (command[1]) {
case "best_bid":
data = table.getBestbid();
break;
case "best_ask":
data = table.getBestask();
break;
case "size":
data = table.getDesiredSize(Integer.parseInt(command[2]));
break;
}
if (!data.equals("")) {
writer.append(data).append("\n");
}
break;
case "o":
int size2 = Integer.parseInt(command[2]);
switch (command[1]) {
case "buy":
table.buy(size2);
break;
case "sell":
table.sell(size2);
break;
}
break;
default:
System.err.println("Error: unknown command - \"" + command[0] + "\"");
break;
}
line = reader.readLine();
}
} catch (IOException | SQLException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
smalldb -> https://pastebin.com/PdkqgPZT
import java.sql.*;
import java.util.Collections;
import java.util.Objects;
import java.util.TreeMap;
public class Smalldb {
private Connection connection;
private PreparedStatement preparedStatement;
private Statement statement;
private ResultSet resultSet;
public Smalldb(Connection connection) {
try {
this.connection = connection;
//create db
statement = connection.createStatement();
statement.execute("CREATE TABLE IF NOT EXISTS asks (id INTEGER PRIMARY KEY, apples INT, amount INT)");
statement.execute("CREATE TABLE IF NOT EXISTS bids (id INTEGER PRIMARY KEY, apples INT, amount INT)");
} catch (SQLException e) {
e.printStackTrace();
throw new Error("Problem", e);
}
}
public void updateAsks(int apples, int amount) throws SQLException {
preparedStatement = this.connection.prepareStatement("SELECT * FROM asks WHERE apples=?");
preparedStatement.setInt(1, apples);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
preparedStatement = this.connection.prepareStatement("UPDATE asks SET amount=? WHERE apples = ?");
preparedStatement.setInt(1, amount);
preparedStatement.setInt(2, apples);
preparedStatement.executeUpdate();
} else {
preparedStatement = this.connection.prepareStatement("INSERT INTO asks (apples, amount) VALUES (?, ?)");
preparedStatement.setInt(1, apples);
preparedStatement.setInt(2, amount);
preparedStatement.executeUpdate();
}
resultSet.close();
preparedStatement.close();
}
public void updateBids(int apples, int amount) throws SQLException {
preparedStatement = this.connection.prepareStatement("SELECT * FROM bids WHERE apples=?");
preparedStatement.setInt(1, apples);
resultSet = preparedStatement.executeQuery();
if(resultSet.next()) {
preparedStatement = this.connection.prepareStatement("UPDATE bids SET amount=? WHERE apples = ?");
preparedStatement.setInt(1, amount);
preparedStatement.setInt(2, apples);
preparedStatement.executeUpdate();
} else {
preparedStatement = this.connection.prepareStatement("INSERT INTO bids (apples, amount) VALUES (?, ?)");
preparedStatement.setInt(1, apples);
preparedStatement.setInt(2, amount);
preparedStatement.executeUpdate();
}
resultSet.close();
preparedStatement.close();
}
public String getBestASK() throws SQLException {
preparedStatement = this.connection.prepareStatement("SELECT * FROM asks WHERE apples=(SELECT MIN(apples) FROM asks WHERE amount != 0)");
resultSet = preparedStatement.executeQuery();
resultSet.next();
String best_ask = resultSet.getInt("apples") + "," + resultSet.getInt("amount");
resultSet.close();
preparedStatement.close();
return best_ask;
}
public String getBestBID() throws SQLException {
preparedStatement = this.connection.prepareStatement("SELECT * FROM bids WHERE apples=(SELECT MAX(apples) FROM bids WHERE amount != 0)");
resultSet = preparedStatement.executeQuery();
resultSet.next();
String best_bid = resultSet.getInt("apples") + "," + resultSet.getInt("amount");
resultSet.close();
preparedStatement.close();
return best_bid;
}
public String getDesiredSize(int apples) throws SQLException {
preparedStatement = this.connection.prepareStatement("SELECT * FROM bids WHERE apples=?");
preparedStatement.setInt(1, apples);
resultSet = preparedStatement.executeQuery();
if (!resultSet.next()) {
preparedStatement = this.connection.prepareStatement("SELECT * FROM asks WHERE apples=?");
preparedStatement.setInt(1, apples);
resultSet = preparedStatement.executeQuery();
resultSet.next();
}
String desired_size = resultSet.getString("amount");
resultSet.close();
preparedStatement.close();
return desired_size != null && !Objects.equals(desired_size, "") ? desired_size : "0";
}
public TreeMap<Integer, Integer> get100bestasks() throws SQLException {
TreeMap<Integer, Integer> data = new TreeMap<>();
statement = this.connection.createStatement();
resultSet = statement.executeQuery("SELECT * FROM asks ORDER BY apples LIMIT 100");
while (resultSet.next()) {
int apples = resultSet.getInt("apples");
int amount = resultSet.getInt("amount");
data.put(apples, amount);
}
resultSet.close();
statement.close();
return data;
}
public TreeMap<Integer, Integer> get100bestbids() throws SQLException {
TreeMap<Integer, Integer> data = new TreeMap<>(Collections.reverseOrder());
statement = this.connection.createStatement();
resultSet = statement.executeQuery("SELECT * FROM bids ORDER BY apples DESC LIMIT 100");
while (resultSet.next()) {
int apples = resultSet.getInt("apples");
int amount = resultSet.getInt("amount");
data.put(apples, amount);
}
resultSet.close();
statement.close();
return data;
}
}
表 -> https://pastebin.com/Ytwn5raM
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.TreeMap;
public class Table {
Smalldb db;
private TreeMap<Integer, Integer> bids = new TreeMap<>(Collections.reverseOrder());
private TreeMap<Integer, Integer> asks = new TreeMap<>();
public Table(Connection connection) throws SQLException {
this.db = new Smalldb(connection);
}
public void setBids(Integer apples, Integer amount) throws SQLException {
this.db.updateBids(apples,amount);
}
public void setAsks(Integer apples, Integer amount) throws SQLException {
this.db.updateAsks(apples,amount);
}
public void buy(Integer size) throws SQLException {
int check=size;
while(size>0){
asks = db.get100bestasks();
for (Integer key:this.asks.keySet()) {
if (size<=0) break;
Integer value = this.asks.get(key);
if(value >=size) {
this.asks.replace(key, value-size);
db.updateAsks(key,value-size);
}
else if (value <size) {
this.asks.replace(key,0);
db.updateAsks(key,0);
}
size-=value;
}//100 entries passed
if(check==size || this.asks.size()<=100) size=0;//bad input checker
}
}
public void sell(Integer size) throws SQLException {
int check=size;
while(size>0){
bids = db.get100bestbids();
for (Integer key:this.bids.keySet()) {
if (size<=0) break;
Integer value = this.bids.get(key);
if(value >=size) {
this.bids.replace(key, value-size);
db.updateBids(key,value-size);
}
else if (value <size) {
this.bids.replace(key,0);
db.updateBids(key,0);
}
size-=value;
}//100 entries passed
if(check==size || this.bids.size()<=100) size=0;//bad input checker
}
}
public String getBestbid() throws SQLException {
String data;
data=this.db.getBestBID();
return data;
}
public String getBestask() throws SQLException {
String data;
data=this.db.getBestASK();
return data;
}
public String getDesiredSize(Integer s) throws SQLException {
return this.db.getDesiredSize(s);
}
}
我还尝试了以下网站的解决方案:https://www.sqlite.org/inmemorydb.html
然而,这只会在内存中创建与我想要的相反的数据库。
感谢所有提示和答案。