Skip to content

Commit 38cd621

Browse files
committed
refactor: add globalEngineSnapshot to improve performance
1 parent 31fdfbf commit 38cd621

File tree

6 files changed

+89
-59
lines changed

6 files changed

+89
-59
lines changed

src/legacy/api/EventAPI.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
#include "mc/world/item/VanillaItemNames.h"
5858
#include "mc/world/level/dimension/Dimension.h"
5959

60+
#include <atomic>
61+
6062
#ifdef LSE_BACKEND_NODEJS
6163
#include "legacy/main/NodeJsHelper.h"
6264
#endif
@@ -966,17 +968,14 @@ void InitBasicEventListeners() {
966968
}
967969
#ifndef LSE_BACKEND_NODEJS
968970
try {
969-
std::list<std::shared_ptr<ScriptEngine>> tmpList;
970-
{
971-
std::shared_lock lock(globalShareData->engineListLock);
972-
// low efficiency
973-
tmpList = globalShareData->globalEngineList;
974-
}
975-
for (auto& engine : tmpList) {
976-
if (EngineManager::isValid(engine.get())
977-
&& EngineManager::getEngineType(engine) == LLSE_BACKEND_TYPE) {
978-
EngineScope enter(engine.get());
979-
engine->messageQueue()->loopQueue(script::utils::MessageQueue::LoopType::kLoopOnce);
971+
auto snapshot = globalShareData->globalEngineSnapshot.load(std::memory_order_acquire);
972+
if (snapshot) {
973+
for (auto& engine : *snapshot) {
974+
if (EngineManager::isValid(engine.get())
975+
&& EngineManager::getEngineType(engine) == LLSE_BACKEND_TYPE) {
976+
EngineScope enter(engine.get());
977+
engine->messageQueue()->loopQueue(script::utils::MessageQueue::LoopType::kLoopOnce);
978+
}
980979
}
981980
}
982981
} catch (...) {

src/legacy/api/NetworkAPI.cpp

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,13 @@ void WSClientClass::initListeners_s() {
168168
ws->OnTextReceived([nowList{&listeners[static_cast<int>(WSClientEvents::onTextReceived)]},
169169
engine = EngineScope::currentEngine()](WebSocketClient&, std::string msg) {
170170
keepThis([nowList, engine, msg = std::move(msg)]() -> CoroTask<> {
171-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
171+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
172172
|| engine->isDestroying())
173173
co_return;
174174

175175
co_await ll::chrono::ticks(1);
176176
try {
177-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
177+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
178178
|| engine->isDestroying())
179179
co_return;
180180

@@ -190,13 +190,13 @@ void WSClientClass::initListeners_s() {
190190
ws->OnBinaryReceived([nowList{&listeners[static_cast<int>(WSClientEvents::onBinaryReceived)]},
191191
engine = EngineScope::currentEngine()](WebSocketClient&, std::vector<uint8_t> data) {
192192
keepThis([nowList, engine, data = std::move(data)]() mutable -> CoroTask<> {
193-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
193+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
194194
|| engine->isDestroying())
195195
co_return;
196196

197197
co_await ll::chrono::ticks(1);
198198
try {
199-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
199+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
200200
|| engine->isDestroying())
201201
co_return;
202202

@@ -212,13 +212,13 @@ void WSClientClass::initListeners_s() {
212212
ws->OnError([nowList{&listeners[static_cast<int>(WSClientEvents::onError)]},
213213
engine = EngineScope::currentEngine()](WebSocketClient&, std::string msg) {
214214
keepThis([nowList, engine, msg = std::move(msg)]() -> CoroTask<> {
215-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
215+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
216216
|| engine->isDestroying())
217217
co_return;
218218

219219
co_await ll::chrono::ticks(1);
220220
try {
221-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
221+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
222222
|| engine->isDestroying())
223223
co_return;
224224

@@ -234,13 +234,13 @@ void WSClientClass::initListeners_s() {
234234
ws->OnLostConnection([nowList{&listeners[static_cast<int>(WSClientEvents::onLostConnection)]},
235235
engine = EngineScope::currentEngine()](WebSocketClient&, int code) {
236236
keepThis([nowList, engine, code]() -> CoroTask<> {
237-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
237+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
238238
|| engine->isDestroying())
239239
co_return;
240240

241241
co_await ll::chrono::ticks(1);
242242
try {
243-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
243+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
244244
|| engine->isDestroying())
245245
co_return;
246246

@@ -333,7 +333,7 @@ Local<Value> WSClientClass::connectAsync(Arguments const& args) {
333333
} catch (std::runtime_error const&) {
334334
result = false;
335335
}
336-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
336+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
337337
|| engine->isDestroying())
338338
return;
339339
EngineScope enter(engine);
@@ -436,11 +436,11 @@ void ADD_CALLBACK(
436436
);
437437
auto receiveMethod =
438438
[engine = EngineScope::currentEngine(), method, callbacks](Request const& req, Response& resp) {
439-
if ((ll::getGamingStatus() == ll::GamingStatus::Stopping) || !EngineManager::isValid(engine)
439+
if (ll::getGamingStatus() == ll::GamingStatus::Stopping || !EngineManager::isValid(engine)
440440
|| engine->isDestroying())
441441
return;
442442
keepThis([engine, req, &resp, method, callbacks]() -> CoroTask<> {
443-
if ((ll::getGamingStatus() == ll::GamingStatus::Stopping) || !EngineManager::isValid(engine)
443+
if (ll::getGamingStatus() == ll::GamingStatus::Stopping || !EngineManager::isValid(engine)
444444
|| engine->isDestroying())
445445
co_return;
446446

@@ -598,12 +598,12 @@ Local<Value> HttpServerClass::onPreRouting(Arguments const& args) {
598598
try {
599599
preRoutingCallback = {EngineScope::currentEngine(), script::Global{args[0].asFunction()}};
600600
svr->set_pre_routing_handler([this, engine = EngineScope::currentEngine()](Request const& req, Response& resp) {
601-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
601+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
602602
|| engine->isDestroying())
603603
return Server::HandlerResponse::Unhandled;
604604
bool handled = false;
605605
keepThis([this, engine, req, &resp, &handled]() -> CoroTask<> {
606-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
606+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
607607
|| engine->isDestroying())
608608
co_return;
609609

@@ -636,12 +636,12 @@ Local<Value> HttpServerClass::onPostRouting(Arguments const& args) {
636636
postRoutingCallback = {EngineScope::currentEngine(), script::Global{args[0].asFunction()}};
637637
svr->set_post_routing_handler([this,
638638
engine = EngineScope::currentEngine()](Request const& req, Response& resp) {
639-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
639+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
640640
|| engine->isDestroying())
641641
return;
642642

643643
keepThis([this, engine, req, &resp]() -> CoroTask<> {
644-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
644+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
645645
|| engine->isDestroying())
646646
co_return;
647647

@@ -667,12 +667,12 @@ Local<Value> HttpServerClass::onError(Arguments const& args) {
667667
try {
668668
errorCallback = {EngineScope::currentEngine(), script::Global{args[0].asFunction()}};
669669
svr->set_error_handler([this, engine = EngineScope::currentEngine()](Request const& req, Response& resp) {
670-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
670+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
671671
|| engine->isDestroying())
672672
return;
673673

674674
keepThis([this, engine, req, &resp]() -> CoroTask<> {
675-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
675+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
676676
|| engine->isDestroying())
677677
co_return;
678678

@@ -702,12 +702,12 @@ Local<Value> HttpServerClass::onException(Arguments const& args) {
702702
Response& resp,
703703
std::exception_ptr e
704704
) {
705-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
705+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
706706
|| engine->isDestroying())
707707
return;
708708

709709
keepThis([this, engine, req, &resp, e]() -> CoroTask<> {
710-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
710+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
711711
|| engine->isDestroying())
712712
co_return;
713713

@@ -1178,7 +1178,7 @@ Local<Value> NetworkClass::httpGet(Arguments const& args) {
11781178

11791179
auto lambda = [callback{std::move(callbackFunc)},
11801180
engine{EngineScope::currentEngine()}](int status, string const& body) {
1181-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
1181+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
11821182
|| engine->isDestroying())
11831183
return;
11841184

@@ -1226,7 +1226,7 @@ Local<Value> NetworkClass::httpPost(Arguments const& args) {
12261226

12271227
auto lambda = [callback{std::move(callbackFunc)},
12281228
engine{EngineScope::currentEngine()}](int status, string const& body) {
1229-
if ((ll::getGamingStatus() != ll::GamingStatus::Running) || !EngineManager::isValid(engine)
1229+
if (ll::getGamingStatus() != ll::GamingStatus::Running || !EngineManager::isValid(engine)
12301230
|| engine->isDestroying())
12311231
return;
12321232

src/legacy/engine/EngineManager.cpp

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,27 @@
77
#include "legacy/main/NodeJsHelper.h"
88
#endif
99

10+
#include <atomic>
1011
#include <mutex>
11-
#include <shared_mutex>
1212

1313
using namespace script;
1414

15+
namespace {
16+
17+
void refreshEngineSnapshotLocked() {
18+
auto snapshot = std::make_shared<std::vector<std::shared_ptr<ScriptEngine>>>(
19+
globalShareData->globalEngineList.begin(),
20+
globalShareData->globalEngineList.end()
21+
);
22+
globalShareData->globalEngineSnapshot.store(snapshot, std::memory_order_release);
23+
}
24+
25+
std::shared_ptr<std::vector<std::shared_ptr<ScriptEngine>>> loadEngineSnapshot() {
26+
return globalShareData->globalEngineSnapshot.load(std::memory_order_acquire);
27+
}
28+
29+
} // namespace
30+
1531
///////////////////////////////// API /////////////////////////////////
1632

1733
bool EngineManager::unregisterEngine(std::shared_ptr<ScriptEngine> const& toDelete) {
@@ -20,6 +36,7 @@ bool EngineManager::unregisterEngine(std::shared_ptr<ScriptEngine> const& toDele
2036
++engine) {
2137
if (*engine == toDelete) {
2238
globalShareData->globalEngineList.erase(engine);
39+
refreshEngineSnapshotLocked();
2340
return true;
2441
}
2542
}
@@ -29,6 +46,7 @@ bool EngineManager::unregisterEngine(std::shared_ptr<ScriptEngine> const& toDele
2946
bool EngineManager::registerEngine(std::shared_ptr<ScriptEngine> const& engine) {
3047
std::unique_lock lock(globalShareData->engineListLock);
3148
globalShareData->globalEngineList.push_back(engine);
49+
refreshEngineSnapshotLocked();
3250
return true;
3351
}
3452

@@ -52,8 +70,10 @@ std::shared_ptr<ScriptEngine> EngineManager::newEngine(std::string const& plugin
5270
}
5371

5472
bool EngineManager::isValid(ScriptEngine* engine, bool onlyCheckLocal) {
55-
std::shared_lock lock(globalShareData->engineListLock);
56-
for (auto& i : globalShareData->globalEngineList) {
73+
auto snapshot = loadEngineSnapshot();
74+
if (!snapshot) return false;
75+
76+
for (auto& i : *snapshot) {
5777
if (i.get() == engine) {
5878
if (engine->isDestroying()) return false;
5979
if (onlyCheckLocal && getEngineType(engine) != LLSE_BACKEND_TYPE) return false;
@@ -68,8 +88,10 @@ bool EngineManager::isValid(std::shared_ptr<ScriptEngine> const& engine, bool on
6888
}
6989

7090
std::shared_ptr<ScriptEngine> EngineManager::checkAndGet(ScriptEngine* engine, bool onlyCheckLocal) {
71-
std::shared_lock lock(globalShareData->engineListLock);
72-
for (auto& i : globalShareData->globalEngineList) {
91+
auto snapshot = loadEngineSnapshot();
92+
if (!snapshot) return nullptr;
93+
94+
for (auto& i : *snapshot) {
7395
if (i.get() == engine) {
7496
if (engine->isDestroying()) return nullptr;
7597
if (onlyCheckLocal && getEngineType(engine) != LLSE_BACKEND_TYPE) return nullptr;
@@ -81,25 +103,27 @@ std::shared_ptr<ScriptEngine> EngineManager::checkAndGet(ScriptEngine* engine, b
81103

82104
std::vector<std::shared_ptr<ScriptEngine>> EngineManager::getLocalEngines() {
83105
std::vector<std::shared_ptr<ScriptEngine>> res;
84-
std::shared_lock lock(globalShareData->engineListLock);
85-
for (auto& engine : globalShareData->globalEngineList) {
106+
auto snapshot = loadEngineSnapshot();
107+
if (!snapshot) return res;
108+
109+
for (auto& engine : *snapshot) {
86110
if (getEngineType(engine) == LLSE_BACKEND_TYPE) res.push_back(engine);
87111
}
88112
return res;
89113
}
90114

91115
std::vector<std::shared_ptr<ScriptEngine>> EngineManager::getGlobalEngines() {
92-
std::vector<std::shared_ptr<ScriptEngine>> res;
93-
std::shared_lock lock(globalShareData->engineListLock);
94-
for (auto& engine : globalShareData->globalEngineList) {
95-
res.push_back(engine);
96-
}
97-
return res;
116+
auto snapshot = loadEngineSnapshot();
117+
if (!snapshot) return {};
118+
119+
return *snapshot;
98120
}
99121

100122
std::shared_ptr<ScriptEngine> EngineManager::getEngine(std::string const& name, bool onlyLocalEngine) {
101-
std::shared_lock lock(globalShareData->engineListLock);
102-
for (auto& engine : globalShareData->globalEngineList) {
123+
auto snapshot = loadEngineSnapshot();
124+
if (!snapshot) return nullptr;
125+
126+
for (auto& engine : *snapshot) {
103127
if (onlyLocalEngine && getEngineType(engine) != LLSE_BACKEND_TYPE) continue;
104128
auto ownerData = getEngineData(engine);
105129
if (ownerData->pluginName == name) return engine;

src/legacy/engine/GlobalShareData.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
#include "legacy/engine/LocalShareData.h"
55

66
#include <Windows.h>
7+
#include <atomic>
78
#include <string>
9+
#include <vector>
810

911
// 全局共享数据
1012
GlobalDataType* globalShareData = nullptr;
@@ -40,4 +42,12 @@ void InitGlobalShareData() {
4042
localShareData->isFirstInstance = false;
4143
globalShareData = static_cast<GlobalDataType*>(address);
4244
}
45+
46+
globalShareData->globalEngineSnapshot.store(
47+
std::make_shared<std::vector<std::shared_ptr<ScriptEngine>>>(
48+
globalShareData->globalEngineList.begin(),
49+
globalShareData->globalEngineList.end()
50+
),
51+
std::memory_order_release
52+
);
4353
}

src/legacy/engine/GlobalShareData.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include "legacy/api/APIHelp.h"
33

44
#include <Windows.h>
5-
#include <list>
5+
#include <atomic>
66
#include <map>
77
#include <shared_mutex>
88
#include <string>
@@ -27,8 +27,9 @@ struct MessageHandlers {
2727
// 全局共享数据
2828
struct GlobalDataType {
2929
// 引擎管理器表
30-
std::shared_mutex engineListLock;
31-
std::list<std::shared_ptr<ScriptEngine>> globalEngineList;
30+
std::shared_mutex engineListLock;
31+
std::vector<std::shared_ptr<ScriptEngine>> globalEngineList;
32+
std::atomic<std::shared_ptr<std::vector<std::shared_ptr<ScriptEngine>>>> globalEngineSnapshot;
3233

3334
// 注册过的命令
3435
std::unordered_map<std::string, std::string> playerRegisteredCmd;

src/legacy/engine/MessageSystem.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
#include "ll/api/event/EventBus.h"
1010
#include "ll/api/event/server/ServerStoppingEvent.h"
1111
#include "ll/api/service/GamingStatus.h"
12-
#include "ll/api/service/ServerInfo.h"
1312

14-
#include <mutex>
13+
#include <atomic>
1514
#include <processthreadsapi.h>
1615

1716
using namespace script;
@@ -323,13 +322,10 @@ bool ModuleMessageResult::cancel() const {
323322
void MessageSystemLoopOnce() {
324323
// if (!messageLoopLock.try_lock())
325324
// return;
326-
std::list<std::shared_ptr<ScriptEngine>> tmpList;
327-
{
328-
std::unique_lock lock(globalShareData->engineListLock);
329-
// low efficiency
330-
tmpList = globalShareData->globalEngineList;
331-
}
332-
for (auto& engine : tmpList) {
325+
auto snapshot = globalShareData->globalEngineSnapshot.load(std::memory_order_acquire);
326+
if (!snapshot) return;
327+
328+
for (auto& engine : *snapshot) {
333329
if (EngineManager::isValid(engine) && EngineManager::getEngineType(engine) == LLSE_BACKEND_TYPE) {
334330
try {
335331
if (EngineScope::currentEngine() == engine.get())

0 commit comments

Comments
 (0)