Skip to content

Commit

Permalink
Optimize the loading performance when dealing with a large number of …
Browse files Browse the repository at this point in the history
…data entries

- Fixed APP stuck on black screen when there are a large number of game
  data entries
- Optimized the loading performance of the game data enteries.
- Add debug traces.
- Bump to v1.5.2

Signed-off-by: Damien Zhao <[email protected]>
  • Loading branch information
zdm65477730 committed Nov 16, 2024
1 parent 1129748 commit d6cf467
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 64 deletions.
2 changes: 1 addition & 1 deletion Application/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ FORWARDER := $(ROMFS)/exefs.nsp
#---------------------------------------------------------------------------------
VER_MAJOR := 1
VER_MINOR := 5
VER_MICRO := 1
VER_MICRO := 2

#---------------------------------------------------------------------------------
# Options for .nacp information
Expand Down
15 changes: 15 additions & 0 deletions Application/include/utils/Debug.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma once
#ifndef DEBUG_HPP
#define DEBUG_HPP

#include <string>
#include <mutex>

//#define ENABLE_DEBUG

namespace Utils {
extern std::mutex mutex;
void write_log(const std::string& msg);
};

#endif
18 changes: 18 additions & 0 deletions Application/source/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "utils/Lang.hpp"
#include "utils/UpdateUtils.hpp"
#include "utils/Utils.hpp"
#include "utils/Debug.hpp"

#include "ui/screen/AdjustPlaytime.hpp"
#include "ui/screen/AllActivity.hpp"
Expand All @@ -24,22 +25,28 @@ namespace Main {
// Start all required services
Utils::NX::startServices();
Utils::Curl::init();
Utils::write_log("Services started and Crul init finished!");

// Create config object and read in values
this->config_ = new Config();
this->config_->readConfig();
Utils::write_log("Read config file finished!");

// Set language
if (!Utils::Lang::setLanguage(this->config_->gLang())) {
this->window->exit();
}
Utils::write_log("Set language finished!");

this->playdata_ = new NX::PlayData();
Utils::write_log("NX::PlayData() finished!");
this->theme_ = new Theme(this->config_->gTheme());
Utils::write_log("Theme(this->config_->gTheme()) finished!");

// Start update thread
this->hasUpdate_ = false;
this->updateThread = std::async(std::launch::async, &Application::checkForUpdate, this);
Utils::write_log("Start update thread finished!");

// Check if launched via user page and if so only use the chosen user
NX::User * u = Utils::NX::getUserPageUser();
Expand All @@ -48,6 +55,7 @@ namespace Main {
this->isUserPage_ = true;
this->users.push_back(u);
}
Utils::write_log("Check user page finished!");

// Set view to today and by day
this->tm = Utils::Time::getTmForCurrentTime();
Expand All @@ -67,12 +75,14 @@ namespace Main {
}
this->tmCopy = this->tm;
this->viewTypeCopy = this->viewType;
Utils::write_log("Set view to today and by day finished!");

// Populate users vector
if (!this->isUserPage_) {
this->users = Utils::NX::getUserObjects();
}
this->userIdx = 0;
Utils::write_log("Populate users vector finished!");

// Populate titles vector
this->titles = Utils::NX::getTitleObjects(this->users);
Expand All @@ -81,24 +91,28 @@ namespace Main {
this->titles.push_back(title);
}
this->titleIdx = 0;
Utils::write_log("Populate titles vector finished!");

// Create Aether instance (ignore log messages for now)
this->window = new Aether::Window("NX-Activity-Log", 1280, 720, [](const std::string message, const bool important) {

});
// this->window->showDebugInfo(true);
Utils::write_log("Create Aether instance finished!");

// Create overlays
this->dtpicker = nullptr;
this->periodpicker = new Aether::PopupList("common.view.heading"_lang);
this->periodpicker->setBackLabel("common.buttonHint.back"_lang);
this->periodpicker->setOKLabel("common.buttonHint.ok"_lang);
Utils::write_log("Create overlays finished!");

// Setup screens
this->setDisplayTheme();
this->createReason = ScreenCreate::Normal;
this->createScreens();
this->reinitScreens_ = ReinitState::False;
Utils::write_log("Setup screens finished!");

if (this->isUserPage_) {
// Skip UserSelect screen if launched via user page
Expand All @@ -109,6 +123,7 @@ namespace Main {
this->window->setFadeOut(true);
this->setScreen(ScreenID::UserSelect);
}
Utils::write_log("Start screens finished!");
}

void Application::checkForUpdate() {
Expand Down Expand Up @@ -455,13 +470,16 @@ namespace Main {
// Check if screens should be recreated
if (this->reinitScreens_ == ReinitState::Wait) {
this->reinitScreens_ = ReinitState::True;
Utils::write_log("Waiting for reinit screens...");
} else if (this->reinitScreens_ == ReinitState::True) {
Utils::write_log("Reinit screens start!");
this->reinitScreens_ = ReinitState::False;
this->window->removeScreen();
this->deleteScreens();
this->setDisplayTheme();
this->createScreens();
this->setScreen(this->screen);
Utils::write_log("Reinit screens finished!");
}
}
}
Expand Down
57 changes: 28 additions & 29 deletions Application/source/nx/PlayData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
#include "nx/PlayData.hpp"
#include "utils/NX.hpp"
#include "utils/Time.hpp"
#include "utils/Debug.hpp"

// Maximum number of entries to process in one iteration
#define MAX_PROCESS_ENTRIES_PER_TIME 100
#define MAX_PROCESS_ENTRIES 4096

namespace NX {
std::vector<PD_Session> PlayData::getPDSessions(TitleID titleID, AccountUid userID, u64 start_ts, u64 end_ts) {
Expand Down Expand Up @@ -164,32 +165,24 @@ namespace NX {
}

PlayEventsAndSummaries PlayData::readPlayDataFromPdm() {
Utils::write_log("readPlayDataFromPdm() enter");

PlayEventsAndSummaries ret;
Result rc;

// Position of first and last event to read
s32 startEntryIndex = -1;
s32 endEntryIndex = -1;
// Position of first event to read
s32 offset = 0;
// Total events read in iteration
s32 totalEntries = -1;
s32 total_read = 1;

rc = pdmqryGetAvailablePlayEventRange(&totalEntries, &startEntryIndex, &endEntryIndex);
if (R_FAILED(rc) || !totalEntries)
return ret;
// Array to store read events
PdmPlayEvent * pEvents = new PdmPlayEvent[MAX_PROCESS_ENTRIES];

s32 count = totalEntries;
s32 offset = startEntryIndex;
// Read all events
while (count) {
s32 total_read = -1;

// Array to store read events
PdmPlayEvent * pEvents = new PdmPlayEvent[MAX_PROCESS_ENTRIES_PER_TIME];
Result rc = pdmqryQueryPlayEvent(offset, pEvents, MAX_PROCESS_ENTRIES_PER_TIME, &total_read);
while (total_read > 0) {
Result rc = pdmqryQueryPlayEvent(offset, pEvents, MAX_PROCESS_ENTRIES, &total_read);
if (R_SUCCEEDED(rc)) {
// Set next read position to next event
offset += total_read;
count -= total_read;

// Process read events
for (s32 i = 0; i < total_read; i++) {
Expand Down Expand Up @@ -253,7 +246,6 @@ namespace NX {
break;
}
break;

// Do nothing for other event types
default:
continue;
Expand All @@ -268,18 +260,23 @@ namespace NX {
ret.first.push_back(event);
}
}
// Free memory allocated to array
delete[] pEvents;
Utils::write_log("pdmqryQueryPlayEvent() called, rc=" + std::to_string(rc) + " offset=" + std::to_string(offset) + " total_read=" + std::to_string(total_read));
}

// Free memory allocated to array
delete[] pEvents;

Utils::write_log("readPlayDataFromPdm() exit");
return ret;
}

PlayEventsAndSummaries PlayData::readPlayDataFromImport() {
PlayEventsAndSummaries ret;

Utils::write_log("readPlayDataFromImport() enter");
// Abort if no file
if (!std::filesystem::exists("/switch/NX-Activity-Log/importedData.json")) {
Utils::write_log("readPlayDataFromImport() exit");
return ret;
}

Expand Down Expand Up @@ -308,7 +305,7 @@ namespace NX {
if (event["clockTimestamp"] != nullptr && event["steadyTimestamp"] != nullptr && event["type"] != nullptr) {
EventType type = static_cast<EventType>(event["type"]);

PlayEvent * evt = new PlayEvent;
PlayEvent *evt = new PlayEvent;
evt->type = (type == Account_Active || type == Account_Inactive ? PlayEvent_Account : PlayEvent_Applet);
evt->userID = {user["id"][0], user["id"][1]};
evt->titleID = title["id"];
Expand Down Expand Up @@ -340,24 +337,23 @@ namespace NX {

// Store data if entry added
if (hasEntry) {
std::vector<std::pair<u64, std::string>>::iterator it = std::find_if(this->titles.begin(), this->titles.end(), [title](std::pair<u64, std::string> entry) {
return (title["id"] == entry.first);
});
if (it == this->titles.end()) {
if (title["id"] != 0) {
this->titles.push_back(std::make_pair(title["id"], title["name"]));
}
if (std::find_if(this->titles.begin(), this->titles.end(), [title](std::pair<u64, std::string> entry) { return (title["id"] == entry.first && title["id"] != 0); }) == this->titles.end()) {
this->titles.push_back(std::make_pair(title["id"], title["name"]));
}
}
}

Utils::write_log("Parse user data from importedData.json finished!");
}

Utils::write_log("readPlayDataFromImport() exit");
return ret;
}

std::vector<PlayEvent *> PlayData::mergePlayEvents(std::vector<PlayEvent *> & one, std::vector<PlayEvent *> & two) {
std::vector<PlayEvent *> merged = one;

Utils::write_log("mergePlayEvents enter");
for (PlayEvent * event : two) {
std::vector<PlayEvent *>::iterator it = std::find_if(one.begin(), one.end(), [event](PlayEvent * pot) {
return (event->type == pot->type && event->titleID == pot->titleID &&
Expand All @@ -374,6 +370,7 @@ namespace NX {

one.clear();
two.clear();
Utils::write_log("mergePlayEvents exit");
return merged;
}

Expand All @@ -389,8 +386,10 @@ namespace NX {
PlayEventsAndSummaries pdmData = pdmThread.get();
PlayEventsAndSummaries impData = impThread.get();

Utils::write_log("Read in all data simultaneously finished");
this->events = this->mergePlayEvents(pdmData.first, impData.first);
this->summaries = impData.second;
Utils::write_log("mergePlayEvents() finished");
}

std::vector<Title *> PlayData::getMissingTitles(std::vector<Title *> passed) {
Expand Down
1 change: 1 addition & 0 deletions Application/source/ui/screen/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ namespace Screen {
body->addElement(tb);
this->msgbox->setBodySize(bw, tb->y() + tb->h() + 40);
this->msgbox->setBody(body);
this->app->addOverlay(this->msgbox);
}

void Settings::setupLangOverlay() {
Expand Down
23 changes: 23 additions & 0 deletions Application/source/utils/Debug.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

#include <fstream>
#include <ctime>
#include "utils/Debug.hpp"

namespace Utils {
std::mutex mutex;
void write_log(const std::string& msg) {
#ifdef ENABLE_DEBUG
std::time_t currentTime = std::time(nullptr);
std::tm* time = std::localtime(&currentTime);
char buffer[30];
strftime(buffer, sizeof(buffer), "[%Y-%m-%d %H:%M:%S] ", time);
std::string timestamp(buffer);

std::lock_guard<std::mutex> lock(Utils::mutex);
std::ofstream file("/switch/NX-Activity-Log/debug.log", std::ios::app);
if (file.is_open()) {
file << timestamp + msg << std::endl;
}
#endif
}
};
Loading

0 comments on commit d6cf467

Please sign in to comment.