-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Asynchronious scipting in sphere #11
Comments
I was actually thinking about integrating LUA but it seems to be a really huge work considering the old habits in the source. |
honestly I think that UO clients are not prepared to multi threading, it send/receive packets using a single linear thread. Also a multi thread scripting on server-side probably will create more headaches instead make the code execution faster just imagine a function like this: [FUNCTION lol] if for some reason the dialog got rendered before we set TAG.A on char, probably it wont work correctly because it will need TAG.A but the tag is not set yet but maybe we can turn some server behaviors into multi thread, splitting some heavy functions into new threads. Like a new thread only to handle CItem::OnTick(), CChar::OnTick(), etc (these functions are heavy and it runs forever at each 0.1s), while the other thread will handle the network, main functions, etc. Also it's a good idea (or even priority?) turn the worldsave into multi-thread, using 2 CPU cores to save chars + 2 cores to save world items, etc but these changes are not simple. Honestly I have no idea how to do this, it's just a idea if someone want go forward with it. This will be a pain to do, and also can create many problems, since many years ago sphere already had a frustrated try when changing some functions to multi-threading, making the server unstable and crashing a lot. Also currently we have a optional multi-thread network (NetworkThreads feature on sphere.ini) that when enabled I got a ping ~250ms, and disabled I got ping ~32ms. But if someone can really make an working engine, feel free to go forward :P |
@coruja747 , have you read the whole suggestion or only first part)
This is a sample what can happen. Multithreaded scripts should be written this way from the beginning. But again, my proposal is not that broking:
Also, while discussing, new limit arrived:
|
Well, having this working for saves, for example, after some work would reduce significantly the time spent on crowded servers, i've heard of servers needing almost 1m to complete the worldsave. This could be done because in saves every script is stopped until it finish, so it won't be any problem with multithreading. And if AI can be done, as you said it can, it will really improve the server's performance, there are a few triggers related to AI which will avoid doing a 100% LUA based AI, I know it's a little drastic to remove them but I'm sure someone can think of a nice way to bypass this problem like moving these triggers to fire before or after the LUA scripts. Anyway, AI is almost the most important issue to take care of because a few monsters active in the same sector will really eat the CPU. |
Regarding the saves, aren't background saves already buildin? Regarding AI - anything that is not required synchronization could be make async. For example if you wish on=gethit to run some logics instantly - you have no option - use scp. But actually most scripts do not require instant actions (if not implementing custom fight engine/etc modifying incoming damage or cancelling it) you can instead write async scripts that will trigger soon, and the delay most probably will not be noticeable by a player. |
The thing is background saves have nothing to do with multithreading as far as i know (or some of you guys changed that already since i touched the code last around August). The problem with multithreading and/or asynchronous scripts, or even starting a small asynchronous kernel is... There is no problem, as long as you dont touch stuff that gets touched by the sphere main engine thread in the meantime. And it's VERY hard to ensure that. You'll need something like locking or.. transactional memory and even with that you would need to implement rollback code.. I thought about this for some time now but i dont see any easy solution to it. Scripting in sphere is, like you already said, event driven. I thought about maybe locking on a per-sector basis. And then go and tick sectors in parallel (Yes!!). But its difficult. Imagine thread #1 ticks sector 1 which has a script which accesses an item in sector 2. This is the main problem with multithreading in Sphere i think. If you could resolve that particular situation, we should absolutely try parallel Sector-Ticking. I'm talking about Server::OnTick, do that stuff in parallel. One solution i though about MIGHT be: Example: Item1 morex: 20 Thread1: Sum = 0; Sum += 20; Access morex of item2; Oh fuck locked.. i have to sleep. Is sum 42? Because that's the purpose of locking. You want your data to be consistent and your calculations to be deterministic. If we had a way to ensure that calculations or modifications to items by threads which Or we could just say we dont care, or implement some concept which would enable users to ENSURE Its difficult. No question :) But this is the only way i see. |
yep that's the problem: it's too difficult and requires a lot of huge changes. I'm not saying that we can't or won't do it, but on past, sphere already tried many features like this. Most of these things got broken or incomplete for many years, and after 5/10/15 years these codes finally got removed because even after many years they still not working (and obsolete) that's why I said it's better focus on small things instead try something bigger that probably will bring us many headaches instead improvements. Instead a huge change on the entire code, we can just turn worldsaves into multi-thread, or improve the current multi-thread network which doesn't work correctly, or even optimize some heavy functions like OnTick, etc (lightweight codes = more performance) |
I agree. In the initial comment from lintax i think he also means things like a database query or stuff that is completely independant from sphere's doing. This would be less of a problem. But if you wanted to do something like
As lintax already says.. But it's not optional. You NEED to ensure that access to sphere internal things is EXCLUSIVE for threads. Otherwise the emulators behaviour will become unpredictable. When i remember correctly from my experiences with RunUO, this Server is also not multi-threaded. When it comes to scripting i mainly had two tricks to get some 'performance'. Well.. its only a dirty trick but:
I'm just splitting the processing of elements above multiple server Ticks. With Timerd=0 the stuff will be executed in the next tick again. Cooperative scheduling if you will, but this extremely improves the gameplay experience for all people on the server if you code exhausting stuff this way. Maybe we should put some more effort in an interface to Files / SQL / Bash. We did a lot of work for DB processing etc. with SYSCMD. Bash scripts also execute on another core ;) |
@jfmu, your solution regarding delayed calculation via SCP is good one, but still not enough. For example, I wish an AI to scan for all characters nearby, sort them by their equipment, stats, abilities, etc, and then ask all friends with enemies with priority at least twice as lower then the selected target attack him... Moreover, if total damage is too high, only part should be sent to attack this victim, the rest should select another target. Plus unit C can cast stone wall behind him to be not able to escape, and a stone wall before him will decay in 3 seconds so it safe to run forward instead of using builtin sphere pathfinding)
@coruja747 why do we need multithreaded save at all? Background saves works perfectly... Using separate thread is not safe by itself since we are saving property-by-property with no lock, so any transaction held by scripts or c++ code could be partially saved and partially not (since was not available at the time, for example, two connected-by-logics char tags). Moreover, we save to the same text file. so anyhow are limited to the time to actually write to disk) Regarding optimization with OnTick transactions - this also in not possible without hurting current scripts - or - as jfmu suggested, implementing a transactional memory with data locks. First will ruin lots of custom scripts, second just makes no sense - we are not implementing an ACID object database by ourselves, right? Refactoring whole objects storage to use some nosql database is also not an option. The 3rd option - extra script engine with some limitations over execution injected specially for such async actions might be a solution. Surely, problems comes when it meets current script engine so probably it should NOT trigger it anyhow. |
We want to support advanced scripting, especially multi-threaded.
PROBLEM.
SOLUTION:
This still leaves several questions, for example if async script will decide to execute "damage(victim, 10)" it should probably pass through the normal operational cycle including SCP event Damage to be triggered.
The text was updated successfully, but these errors were encountered: