* Performance: memory usage optimization for deck editor (improved search for low end computers, see #7177);

This commit is contained in:
Oleg Agafonov 2021-02-12 18:31:51 +04:00
parent 275e996c08
commit c1dea5b21e
5 changed files with 81 additions and 7 deletions

View file

@ -65,6 +65,16 @@
cardDimension = GUISizeHelper.editorCardDimension;
}
@Override
public Object getCardsStore() {
return this.cards;
}
@Override
public void clearCardsStoreBeforeUpdate() {
this.cards.clear();
}
@Override
public void loadCards(CardsView showCards, SortSetting sortSetting, BigCard bigCard, UUID gameId) {
this.loadCards(showCards, sortSetting, bigCard, gameId, true);

View file

@ -446,6 +446,17 @@
mainModel.addCardEventListener(listener);
}
@Override
public Object getCardsStore() {
return this.cards;
}
@Override
public void clearCardsStoreBeforeUpdate() {
this.cards.clear();
this.mageCards.clear();
}
@Override
public void loadCards(CardsView showCards, SortSetting sortSetting, BigCard bigCard, UUID gameId) {
this.loadCards(showCards, sortSetting, bigCard, gameId, true);

View file

@ -26,4 +26,11 @@ public interface ICardGrid {
void refresh();
int cardsSize();
// only for debug, return inner cards list
Object getCardsStore();
// specil memory optimization to clean inner cards list before new cards load, so you don't need 2x memory
// WARNING, you must call it in same code as new cards list prepare
void clearCardsStoreBeforeUpdate();
}

View file

@ -27,12 +27,15 @@ import mage.filter.predicate.other.ExpansionSetPredicate;
import mage.game.events.Listener;
import mage.view.CardView;
import mage.view.CardsView;
import org.apache.log4j.Logger;
import org.mage.card.arcane.ManaSymbolsCellRenderer;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import java.awt.*;
import java.awt.event.*;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.*;
@ -43,6 +46,8 @@ import static mage.client.dialog.PreferencesDialog.*;
*/
public class CardSelector extends javax.swing.JPanel implements ComponentListener, DragCardTarget {
private static final Logger logger = Logger.getLogger(CardSelector.class);
private final java.util.List<Card> cards = new ArrayList<>();
private BigCard bigCard;
private boolean limited = false;
@ -412,6 +417,11 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
FilterCard filter = buildFilter();
MageFrame.getDesktop().setCursor(new Cursor(Cursor.WAIT_CURSOR));
try {
// debug
//debugObjectMemorySize("Old cards size", this.currentView.getCardsStore());
this.currentView.clearCardsStoreBeforeUpdate();
java.util.List<Card> filteredCards = new ArrayList<>();
if (chkPennyDreadful.isSelected() && pdAllowed.isEmpty()) {
@ -426,21 +436,32 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
}
} else {
java.util.List<CardInfo> foundCards = CardRepository.instance.findCards(buildCriteria());
for (CardInfo cardInfo : foundCards) {
Card card = cardInfo.getMockCard();
if (filter.match(card, null)) {
if (chkPennyDreadful.isSelected()) {
if (!pdAllowed.containsKey(card.getName())) {
continue;
}
// filter by penny
if (chkPennyDreadful.isSelected()) {
if (!pdAllowed.containsKey(cardInfo.getName())) {
continue;
}
filteredCards.add(card);
}
// filter by settings
Card card = cardInfo.getMockCard();
if (!filter.match(card, null)) {
continue;
}
// found
filteredCards.add(card);
}
}
// force to list mode on too much cards
if (currentView instanceof CardGrid && filteredCards.size() > CardGrid.MAX_IMAGES) {
this.toggleViewMode();
}
// debug
//debugObjectMemorySize("New cards size", filteredCards);
this.currentView.loadCards(new CardsView(filteredCards), sortSetting, bigCard, null, false);
this.cardCount.setText(String.valueOf(filteredCards.size()));
} finally {
@ -448,6 +469,19 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
}
}
private void debugObjectMemorySize(String name, Object object) {
// just debug code, don't use it in production
// need 2x memory for find a size
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
logger.info(name + ": " + baos.size());
} catch (Throwable e) {
logger.fatal("Can't find object size: " + e.getMessage(), e);
}
}
public void setCardCount(int value) {
this.cardCount.setText(String.valueOf(value));
}
@ -1212,6 +1246,7 @@ public class CardSelector extends javax.swing.JPanel implements ComponentListene
this.limited = true;
cards.clear();
}
// accumulate boosters in one list
ExpansionSet expansionSet = Sets.getInstance().get(sets.get(0));
if (expansionSet != null) {
java.util.List<Card> booster = expansionSet.createBooster();

View file

@ -71,6 +71,17 @@ public class TableModel extends AbstractTableModel implements ICardGrid {
this.view.clear();
}
@Override
public Object getCardsStore() {
return this.cards;
}
@Override
public void clearCardsStoreBeforeUpdate() {
this.cards.clear();
this.view.clear();
}
@Override
public void loadCards(CardsView showCards, SortSetting sortSetting, BigCard bigCard, UUID gameId) {
this.loadCards(showCards, sortSetting, bigCard, gameId, true);