More optimizations: don't load OsuFile array fields until needed.
When cached, defer loading of timing points, breaks, and combo colors until directly before a game. Potentially cuts loading time by 50%, and saves a bit of memory. Other changes: - Don't store the default combo colors in the cache. - Removed some PreparedStatements that only get executed once. Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
parent
f8e91cba64
commit
f9878f4fa4
|
@ -165,7 +165,7 @@ public class OsuFile implements Comparable<OsuFile> {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** All timing points. */
|
/** All timing points. */
|
||||||
public ArrayList<OsuTimingPoint> timingPoints = new ArrayList<OsuTimingPoint>();
|
public ArrayList<OsuTimingPoint> timingPoints;
|
||||||
|
|
||||||
/** Song BPM range. */
|
/** Song BPM range. */
|
||||||
public int bpmMin = 0, bpmMax = 0;
|
public int bpmMin = 0, bpmMax = 0;
|
||||||
|
@ -374,6 +374,7 @@ public class OsuFile implements Comparable<OsuFile> {
|
||||||
* @param s the string
|
* @param s the string
|
||||||
*/
|
*/
|
||||||
public void timingPointsFromString(String s) {
|
public void timingPointsFromString(String s) {
|
||||||
|
this.timingPoints = new ArrayList<OsuTimingPoint>();
|
||||||
if (s == null)
|
if (s == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -390,10 +391,10 @@ public class OsuFile implements Comparable<OsuFile> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link #combo} field formatted as a string,
|
* Returns the {@link #combo} field formatted as a string,
|
||||||
* or null if the field is null.
|
* or null if the field is null or the default combo.
|
||||||
*/
|
*/
|
||||||
public String comboToString() {
|
public String comboToString() {
|
||||||
if (combo == null)
|
if (combo == null || combo == Utils.DEFAULT_COMBO)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
@ -416,6 +417,7 @@ public class OsuFile implements Comparable<OsuFile> {
|
||||||
* @param s the string
|
* @param s the string
|
||||||
*/
|
*/
|
||||||
public void comboFromString(String s) {
|
public void comboFromString(String s) {
|
||||||
|
this.combo = Utils.DEFAULT_COMBO;
|
||||||
if (s == null)
|
if (s == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,10 @@ public class OsuParser {
|
||||||
// load cached entries from database
|
// load cached entries from database
|
||||||
if (!cachedOsuFiles.isEmpty()) {
|
if (!cachedOsuFiles.isEmpty()) {
|
||||||
status = Status.CACHE;
|
status = Status.CACHE;
|
||||||
OsuDB.load(cachedOsuFiles);
|
|
||||||
|
// Load array fields only when needed to save time/memory.
|
||||||
|
// Change flag to 'LOAD_ALL' to load them immediately.
|
||||||
|
OsuDB.load(cachedOsuFiles, OsuDB.LOAD_NONARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add group entries to OsuGroupList
|
// add group entries to OsuGroupList
|
||||||
|
@ -198,6 +201,7 @@ public class OsuParser {
|
||||||
*/
|
*/
|
||||||
private static OsuFile parseFile(File file, File dir, ArrayList<OsuFile> osuFiles, boolean parseObjects) {
|
private static OsuFile parseFile(File file, File dir, ArrayList<OsuFile> osuFiles, boolean parseObjects) {
|
||||||
OsuFile osu = new OsuFile(file);
|
OsuFile osu = new OsuFile(file);
|
||||||
|
osu.timingPoints = new ArrayList<OsuTimingPoint>();
|
||||||
|
|
||||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
|
try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"))) {
|
||||||
String line = in.readLine();
|
String line = in.readLine();
|
||||||
|
|
|
@ -49,11 +49,14 @@ public class OsuDB {
|
||||||
/** Minimum batch size to invoke batch insertion. */
|
/** Minimum batch size to invoke batch insertion. */
|
||||||
private static final int INSERT_BATCH_MIN = 100;
|
private static final int INSERT_BATCH_MIN = 100;
|
||||||
|
|
||||||
|
/** OsuFile loading flags. */
|
||||||
|
public static final int LOAD_NONARRAY = 1, LOAD_ARRAY = 2, LOAD_ALL = 3;
|
||||||
|
|
||||||
/** Database connection. */
|
/** Database connection. */
|
||||||
private static Connection connection;
|
private static Connection connection;
|
||||||
|
|
||||||
/** Query statements. */
|
/** Query statements. */
|
||||||
private static PreparedStatement insertStmt, selectStmt, selectAllStmt, lastModStmt, deleteMapStmt, deleteGroupStmt;
|
private static PreparedStatement insertStmt, selectStmt, deleteMapStmt, deleteGroupStmt;
|
||||||
|
|
||||||
// This class should not be instantiated.
|
// This class should not be instantiated.
|
||||||
private OsuDB() {}
|
private OsuDB() {}
|
||||||
|
@ -80,8 +83,6 @@ public class OsuDB {
|
||||||
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " +
|
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, " +
|
||||||
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
);
|
);
|
||||||
lastModStmt = connection.prepareStatement("SELECT dir, file, lastModified FROM beatmaps");
|
|
||||||
selectAllStmt = connection.prepareStatement("SELECT * FROM beatmaps");
|
|
||||||
selectStmt = connection.prepareStatement("SELECT * FROM beatmaps WHERE dir = ? AND file = ?");
|
selectStmt = connection.prepareStatement("SELECT * FROM beatmaps WHERE dir = ? AND file = ?");
|
||||||
deleteMapStmt = connection.prepareStatement("DELETE FROM beatmaps WHERE dir = ? AND file = ?");
|
deleteMapStmt = connection.prepareStatement("DELETE FROM beatmaps WHERE dir = ? AND file = ?");
|
||||||
deleteGroupStmt = connection.prepareStatement("DELETE FROM beatmaps WHERE dir = ?");
|
deleteGroupStmt = connection.prepareStatement("DELETE FROM beatmaps WHERE dir = ?");
|
||||||
|
@ -277,8 +278,10 @@ public class OsuDB {
|
||||||
/**
|
/**
|
||||||
* Loads OsuFile fields from the database.
|
* Loads OsuFile fields from the database.
|
||||||
* @param osu the OsuFile object
|
* @param osu the OsuFile object
|
||||||
|
* @param flag whether to load all fields (LOAD_ALL), non-array
|
||||||
|
* fields (LOAD_NONARRAY), or array fields (LOAD_ARRAY)
|
||||||
*/
|
*/
|
||||||
public static void load(OsuFile osu) {
|
public static void load(OsuFile osu, int flag) {
|
||||||
if (connection == null)
|
if (connection == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -286,8 +289,12 @@ public class OsuDB {
|
||||||
selectStmt.setString(1, osu.getFile().getParentFile().getName());
|
selectStmt.setString(1, osu.getFile().getParentFile().getName());
|
||||||
selectStmt.setString(2, osu.getFile().getName());
|
selectStmt.setString(2, osu.getFile().getName());
|
||||||
ResultSet rs = selectStmt.executeQuery();
|
ResultSet rs = selectStmt.executeQuery();
|
||||||
if (rs.next())
|
if (rs.next()) {
|
||||||
|
if ((flag & LOAD_NONARRAY) > 0)
|
||||||
setOsuFileFields(rs, osu);
|
setOsuFileFields(rs, osu);
|
||||||
|
if ((flag & LOAD_ARRAY) > 0)
|
||||||
|
setOsuFileArrayFields(rs, osu);
|
||||||
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
ErrorHandler.error("Failed to load OsuFile from database.", e, true);
|
ErrorHandler.error("Failed to load OsuFile from database.", e, true);
|
||||||
|
@ -297,8 +304,10 @@ public class OsuDB {
|
||||||
/**
|
/**
|
||||||
* Loads OsuFile fields from the database in a batch.
|
* Loads OsuFile fields from the database in a batch.
|
||||||
* @param batch a list of OsuFile objects
|
* @param batch a list of OsuFile objects
|
||||||
|
* @param flag whether to load all fields (LOAD_ALL), non-array
|
||||||
|
* fields (LOAD_NONARRAY), or array fields (LOAD_ARRAY)
|
||||||
*/
|
*/
|
||||||
public static void load(List<OsuFile> batch) {
|
public static void load(List<OsuFile> batch, int flag) {
|
||||||
if (connection == null)
|
if (connection == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -306,11 +315,11 @@ public class OsuDB {
|
||||||
int size = batch.size();
|
int size = batch.size();
|
||||||
if (size < LOAD_BATCH_MIN) {
|
if (size < LOAD_BATCH_MIN) {
|
||||||
for (OsuFile osu : batch)
|
for (OsuFile osu : batch)
|
||||||
load(osu);
|
load(osu, flag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try (Statement stmt = connection.createStatement()) {
|
||||||
// create map
|
// create map
|
||||||
HashMap<String, HashMap<String, OsuFile>> map = new HashMap<String, HashMap<String, OsuFile>>();
|
HashMap<String, HashMap<String, OsuFile>> map = new HashMap<String, HashMap<String, OsuFile>>();
|
||||||
for (OsuFile osu : batch) {
|
for (OsuFile osu : batch) {
|
||||||
|
@ -326,8 +335,9 @@ public class OsuDB {
|
||||||
|
|
||||||
// iterate through database to load OsuFiles
|
// iterate through database to load OsuFiles
|
||||||
int count = 0;
|
int count = 0;
|
||||||
selectAllStmt.setFetchSize(100);
|
stmt.setFetchSize(100);
|
||||||
ResultSet rs = selectAllStmt.executeQuery();
|
String sql = "SELECT * FROM beatmaps";
|
||||||
|
ResultSet rs = stmt.executeQuery(sql);
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
String parent = rs.getString(1);
|
String parent = rs.getString(1);
|
||||||
HashMap<String, OsuFile> m = map.get(parent);
|
HashMap<String, OsuFile> m = map.get(parent);
|
||||||
|
@ -335,7 +345,10 @@ public class OsuDB {
|
||||||
String name = rs.getString(2);
|
String name = rs.getString(2);
|
||||||
OsuFile osu = m.get(name);
|
OsuFile osu = m.get(name);
|
||||||
if (osu != null) {
|
if (osu != null) {
|
||||||
|
if ((flag & LOAD_NONARRAY) > 0)
|
||||||
setOsuFileFields(rs, osu);
|
setOsuFileFields(rs, osu);
|
||||||
|
if ((flag & LOAD_ARRAY) > 0)
|
||||||
|
setOsuFileArrayFields(rs, osu);
|
||||||
if (++count >= size)
|
if (++count >= size)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -348,7 +361,7 @@ public class OsuDB {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets all OsuFile fields using a given result set.
|
* Sets all OsuFile non-array fields using a given result set.
|
||||||
* @param rs the result set containing the fields
|
* @param rs the result set containing the fields
|
||||||
* @param osu the OsuFile
|
* @param osu the OsuFile
|
||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
|
@ -387,6 +400,15 @@ public class OsuDB {
|
||||||
osu.widescreenStoryboard = rs.getBoolean(34);
|
osu.widescreenStoryboard = rs.getBoolean(34);
|
||||||
osu.epilepsyWarning = rs.getBoolean(35);
|
osu.epilepsyWarning = rs.getBoolean(35);
|
||||||
osu.bg = OsuParser.getDBString(rs.getString(36));
|
osu.bg = OsuParser.getDBString(rs.getString(36));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets all OsuFile array fields using a given result set.
|
||||||
|
* @param rs the result set containing the fields
|
||||||
|
* @param osu the OsuFile
|
||||||
|
* @throws SQLException
|
||||||
|
*/
|
||||||
|
private static void setOsuFileArrayFields(ResultSet rs, OsuFile osu) throws SQLException {
|
||||||
osu.timingPointsFromString(rs.getString(37));
|
osu.timingPointsFromString(rs.getString(37));
|
||||||
osu.breaksFromString(rs.getString(38));
|
osu.breaksFromString(rs.getString(38));
|
||||||
osu.comboFromString(rs.getString(39));
|
osu.comboFromString(rs.getString(39));
|
||||||
|
@ -400,10 +422,11 @@ public class OsuDB {
|
||||||
if (connection == null)
|
if (connection == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
try {
|
try (Statement stmt = connection.createStatement()) {
|
||||||
Map<String, Long> map = new HashMap<String, Long>();
|
Map<String, Long> map = new HashMap<String, Long>();
|
||||||
ResultSet rs = lastModStmt.executeQuery();
|
String sql = "SELECT dir, file, lastModified FROM beatmaps";
|
||||||
lastModStmt.setFetchSize(100);
|
ResultSet rs = stmt.executeQuery(sql);
|
||||||
|
stmt.setFetchSize(100);
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
String path = String.format("%s/%s", rs.getString(1), rs.getString(2));
|
String path = String.format("%s/%s", rs.getString(1), rs.getString(2));
|
||||||
long lastModified = rs.getLong(3);
|
long lastModified = rs.getLong(3);
|
||||||
|
@ -460,9 +483,7 @@ public class OsuDB {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
insertStmt.close();
|
insertStmt.close();
|
||||||
lastModStmt.close();
|
|
||||||
selectStmt.close();
|
selectStmt.close();
|
||||||
selectAllStmt.close();
|
|
||||||
deleteMapStmt.close();
|
deleteMapStmt.close();
|
||||||
deleteGroupStmt.close();
|
deleteGroupStmt.close();
|
||||||
connection.close();
|
connection.close();
|
||||||
|
|
|
@ -1284,8 +1284,13 @@ public class SongMenu extends BasicGameState {
|
||||||
SoundController.playSound(SoundEffect.MENUHIT);
|
SoundController.playSound(SoundEffect.MENUHIT);
|
||||||
OsuFile osu = MusicController.getOsuFile();
|
OsuFile osu = MusicController.getOsuFile();
|
||||||
Display.setTitle(String.format("%s - %s", game.getTitle(), osu.toString()));
|
Display.setTitle(String.format("%s - %s", game.getTitle(), osu.toString()));
|
||||||
|
|
||||||
|
// load any missing data
|
||||||
|
if (osu.timingPoints == null || osu.combo == null)
|
||||||
|
OsuDB.load(osu, OsuDB.LOAD_ARRAY);
|
||||||
OsuParser.parseHitObjects(osu);
|
OsuParser.parseHitObjects(osu);
|
||||||
HitSound.setDefaultSampleSet(osu.sampleSet);
|
HitSound.setDefaultSampleSet(osu.sampleSet);
|
||||||
|
|
||||||
MultiClip.destroyExtraClips();
|
MultiClip.destroyExtraClips();
|
||||||
((Game) game.getState(Opsu.STATE_GAME)).setRestart(Game.Restart.NEW);
|
((Game) game.getState(Opsu.STATE_GAME)).setRestart(Game.Restart.NEW);
|
||||||
game.enterState(Opsu.STATE_GAME, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
game.enterState(Opsu.STATE_GAME, new FadeOutTransition(Color.black), new FadeInTransition(Color.black));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user