Я работаю над проектом, который пытается использовать нейронную сеть, чтобы научиться играть в шашки. Обучая мою сеть, я должен запускать симуляции многих игр (10000+ игр). При проверке памяти кучи с помощью программы просмотра памяти Intellij все выглядит нормально. Каждый объект CheckerGame и связанные с ним поля (CheckerPieces, GameBoard и т. Д.), Похоже, в конечном итоге перерабатываются сборщиком мусора java. Это означает, что как только игра с шашками закончится, ресурсы игры будут правильно утилизированы.Java-программа начинается нормально, но затем приводит к утечке памяти
После запуска программы обучения немного дольше, похоже, что сборщик мусора Java решает прекратить переработку моих игровых объектов, а затем я в конечном итоге получаю OutOfMemoryError, когда игровые объекты накапливаются. Вот пример того, что я говорю о .
Существует, очевидно, некоторая утечка памяти, но для меня это не имеет смысла, поскольку программа правильно перерабатывает игровые ресурсы большую часть времени.
EDIT: Код
public class CheckersGame {
private GameBoard board;
private Player redPlayer;
private Player bluePlayer;
private boolean isBlueTurn;
private int winner = -2;
private int redGamesWon = 0;
private int blueGamesWon = 0;
private int turnNumber = 0;
private int blueTurnNumber = 0;
public boolean gameover = false;
public CheckersGame() {
}
public void initializeGame() {
winner = -2;
redGamesWon = 0;
blueGamesWon = 0;
turnNumber = 0;
blueTurnNumber = 0;
redPlayer = new RedPlayer();
bluePlayer = new BluePlayer();
board = new GameBoard(redPlayer, bluePlayer);
redPlayer.setBoard(board);
bluePlayer.setBoard(board);
isBlueTurn = false;
board.setUpGameBoard();
}
public void turn() {
Random rng = new Random();
try {
LegalMove[] possibleMovesRed = redPlayer.getAllPossibleValidMoves();
LegalMove[] possibleMovesBlue = bluePlayer.getAllPossibleValidMoves();
if (turnNumber == 150) {
winner = 0;
System.out.println("Tie " + NeuralNet.testint + "/" + NeuralNet.otherint + " | " + blueTurnNumber);
NeuralNet.testint = 0;
NeuralNet.otherint = 0;
}
if (board.whoWon(possibleMovesBlue, possibleMovesRed) == redPlayer) {
winner = -1;
System.out.println("Red Won " + NeuralNet.testint + "/" + NeuralNet.otherint + " | " + blueTurnNumber);
NeuralNet.testint = 0;
NeuralNet.otherint = 0;
redGamesWon++;
} else if (board.whoWon(possibleMovesBlue, possibleMovesRed) == bluePlayer) {
winner = 1;
System.out.println("Blue Won " + NeuralNet.testint + "/" + NeuralNet.otherint + " | " + blueTurnNumber);
NeuralNet.testint = 0;
NeuralNet.otherint = 0;
blueGamesWon++;
} else {
if (isBlueTurn) { //Blue turn (NN)
LegalMove nextMove = NeuralNet.getMoveNN(bluePlayer.getNetwork(), bluePlayer.convertBoard(), possibleMovesBlue, bluePlayer);
bluePlayer.movePiece(nextMove);
isBlueTurn = false;
blueTurnNumber++;
} else { // Red's turn (random)
int upperBound = possibleMovesRed.length;
LegalMove randomMove = possibleMovesRed[(rng.nextInt(upperBound))];
redPlayer.movePiece(randomMove); // executes random move
isBlueTurn = true;
}
// gc
for (LegalMove move : possibleMovesBlue) {
move.clearTree();
}
for (LegalMove move : possibleMovesRed) {
move.clearTree();
}
possibleMovesBlue = null;
possibleMovesRed = null;
turnNumber++;
}
} catch (InvalidMoveException ime) {
ime.printCustomError();
}
}
}
Training Code (scorePlayer получает постоянно называют и результаты игры возвращается к нейронной сети):
public class NeuralPlayerRandom {
private NEATNetwork network;
private static int playerIteration = 1;
public NeuralPlayerRandom(NEATNetwork network) {
this.network = network;
}
public int scorePlayer() {
int n = 0;
System.out.println("Player Iteration: " + playerIteration);
for (int i = 0; i < 100; i++) {
System.out.print("I: " + i + " ");
n += this.doIteration();
}
playerIteration++;
return n/2;
}
}
private int doIteration() {
CheckersGame game = new CheckersGame();
game.initializeGame();
game.getBluePlayer().setNetwork(this.network);
while (game.getWinner() == -2) {
game.turn();
}
int winStatus = game.getWinner();
game = null;
return winStatus;
}
}
}
public class LegalMove {
private GameBoardTile oldTile;
private GameBoardTile newTile;
private GameBoardTile jumpedTile;
private LegalMove moveBefore;
private LegalMove moveAfter;
private MoveDirections direction;
public LegalMove(GameBoardTile oldTile, GameBoardTile newTile, LegalMove moveBefore, LegalMove moveAfter, GameBoardTile jumpedTile, MoveDirections direction) {
this.oldTile = oldTile;
this.newTile = newTile;
this.moveBefore = moveBefore;
this.moveAfter = moveAfter;
this.jumpedTile = jumpedTile;
this.direction = direction;
}
public LegalMove(GameBoardTile oldTile, GameBoardTile newTile, LegalMove moveBefore, LegalMove moveAfter, MoveDirections direction) {
this.oldTile = oldTile;
this.newTile = newTile;
this.moveBefore = moveBefore;
this.moveAfter = moveAfter;
this.direction = direction;
}
public ArrayList<GameBoardTile> getTotalJumpedTiles() {
ArrayList<GameBoardTile> totalJumpedTiles = new ArrayList<>();
LegalMove moveToCheck = this;
while (moveToCheck != null) {
totalJumpedTiles.add(moveToCheck.getJumpedTile());
moveToCheck = moveToCheck.getMoveBefore();
}
return totalJumpedTiles;
}
public GameBoardTile getJumpedTile() {
return jumpedTile;
}
public int returnNewY() {
return newTile.returnY();
}
public int returnNewX() {
return newTile.returnX();
}
public GameBoardTile getNewTile() {
return newTile;
}
public GameBoardTile getOldTile() {
return oldTile;
}
public void setMoveAfter(LegalMove moveAfter) {
this.moveAfter = moveAfter;
}
public ArrayList<LegalMove> getPastMoves() {
ArrayList<LegalMove> pastMoves = new ArrayList<>();
LegalMove moveToCheck = moveBefore;
while(moveToCheck != null) {
pastMoves.add(moveToCheck);
moveToCheck = moveToCheck.getMoveBefore();
}
Collections.reverse(pastMoves);
pastMoves.add(this);
return pastMoves;
}
public LegalMove getMoveBefore() {
return moveBefore;
}
public LegalMove getMoveAfter() {
return moveAfter;
}
public String toString() {
if (oldTile != null)
return "\nOld: " + oldTile + "\nNew: " + newTile + "\n";
else
return "\nOld: BEGINNING" + "\nNew: " + newTile + "\n";
}
// Returns the first that needs to be made in this move tree
public LegalMove getRootMove() {
LegalMove moveToCheck = this;
while(moveToCheck.getMoveBefore() != null) {
moveToCheck = moveToCheck.getMoveBefore();
}
return moveToCheck;
}
// Captures all "jumped" pieces up to this legal move
// Returns ArrayList of pieces captured
public ArrayList<CheckerPiece> captureJumpedPieces() {
ArrayList<CheckerPiece> jumpedPieces = new ArrayList<>();
LegalMove moveToCheck = this;
while (moveToCheck != null) {
if (moveToCheck.getJumpedTile() != null) {
jumpedPieces.add(moveToCheck.getJumpedTile().getCurrentPiece());
moveToCheck.getJumpedTile().getCurrentPiece().capturePiece();
moveToCheck = moveToCheck.getMoveBefore();
} else {
//System.out.println("Move " + this + " has no jumped pieces");
moveToCheck = moveToCheck.getMoveBefore();
}
}
return jumpedPieces;
}
public CheckerPiece getOldPiece() {
return oldTile.getCurrentPiece();
}
public MoveDirections getDirection() {
return direction;
}
public boolean equals(LegalMove move) {
return (oldTile == move.oldTile && newTile == move.newTile && jumpedTile == move.jumpedTile && direction == move.getDirection());
}
public void clearTree() {
LegalMove moveToCheck = moveBefore;
while (moveToCheck != null) {
LegalMove temp = moveToCheck;
moveToCheck = moveToCheck.getMoveBefore();
temp.moveAfter = null;
temp.jumpedTile = null;
temp.oldTile = null;
temp.newTile = null;
temp.moveAfter = null;
temp = null;
}
}
}
я ушел из серии участков кода и частей, которые не имеют отношения
Как мы можем найти утечку памяти без какого-либо кода? – shmosel
Это нехорошо, но мы не можем вам помочь, если вы не показываете код –
Также по какой-то причине утечка памяти происходит быстрее на моем ноутбуке linux, чем на моем рабочем столе Windows. – Smaugy