Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
tweak(scripting/mono): use 'fast' code path for Windows server
The supposed memory corruption claims that made this code path not used
for server were likely specific to Linux.

As such, we should be able to safely use this code path for the Windows
server build, which reduces overhead for common server-related tasks by
a lot (vMenu, a resource with a very small server implementation, even
went down from ~700us to ~30us tick time on my dev workstation) as the
very slow .NET remoting stuff doesn't get used anymore.

This doesn't replace the need for the .NET/Mono ScRT being reworked
entirely somewhen, but at least should make server-side use of such a
bit faster on supported platforms such as Windows.
  • Loading branch information
blattersturm committed Apr 10, 2022
1 parent 76a2919 commit 62e1a14
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 10 deletions.
8 changes: 4 additions & 4 deletions code/client/clrcore/MonoScriptRuntime.cs
Expand Up @@ -90,7 +90,7 @@ public void Create(IScriptHost host)
m_intManager.SetResourceName(resourceName);

// TODO: figure out a cleaner solution to Mono JIT corruption so server doesn't have to be slower
#if IS_FXSERVER
#if IS_FXSERVER && !OS_WIN
m_intManager.SetScriptHost(new WrapScriptHost(host), m_instanceId);
#else
m_intManager.SetScriptHost(Marshal.GetIUnknownForObject(host), m_instanceId);
Expand Down Expand Up @@ -166,7 +166,7 @@ public void Tick()
{
using (GetPushRuntime())
{
#if IS_FXSERVER
#if IS_FXSERVER && !OS_WIN
m_intManager?.Tick();
#else
// we *shouldn't* do .Id here as that's yet another free remoting call
Expand All @@ -182,7 +182,7 @@ public void Tick()
private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

private static FastMethod<Action<AppDomain>> ms_fastTickInDomain =
#if IS_FXSERVER
#if IS_FXSERVER && !OS_WIN
null;
#else
BuildFastTick();
Expand Down Expand Up @@ -291,7 +291,7 @@ public void WalkStack(byte[] boundaryStart, int boundaryStartLength, byte[] boun

var frames = (IEnumerable<object>)MsgPackDeserializer.Deserialize(data);

#if !IS_FXSERVER
#if !IS_FXSERVER || OS_WIN
visitor = new DirectVisitor(visitor);
#endif

Expand Down
8 changes: 4 additions & 4 deletions code/client/clrcore/PushRuntime.cs
Expand Up @@ -7,7 +7,7 @@ namespace CitizenFX.Core
internal struct PushRuntime : IDisposable
{
private readonly IntPtr m_runtime;
#if IS_FXSERVER
#if IS_FXSERVER && !OS_WIN
private readonly IScriptRuntime m_actualRuntime;
#endif
private static IScriptRuntimeHandler ms_runtimeHandler;
Expand All @@ -21,7 +21,7 @@ static PushRuntime()
{
ms_runtimeHandler = InternalManager.CreateInstance<IScriptRuntimeHandler>(new Guid(0xc41e7194, 0x7556, 0x4c02, 0xba, 0x45, 0xa9, 0xc8, 0x4d, 0x18, 0xad, 0x43));

#if !IS_FXSERVER
#if !IS_FXSERVER || OS_WIN
ms_pushMethod = new FastMethod<Action<IntPtr, IntPtr>>("PushRuntime", ms_runtimeHandler, typeof(IScriptRuntimeHandler), 0);
ms_popMethod = new FastMethod<Action<IntPtr, IntPtr>>("PopRuntime", ms_runtimeHandler, typeof(IScriptRuntimeHandler), 2);

Expand All @@ -32,7 +32,7 @@ static PushRuntime()
[SecuritySafeCritical]
public PushRuntime(IScriptRuntime runtime, IntPtr comRuntime = default)
{
#if !IS_FXSERVER
#if !IS_FXSERVER || OS_WIN
ms_pushMethod.method(ms_runtimeHandlerIface, comRuntime);

m_runtime = comRuntime;
Expand All @@ -46,7 +46,7 @@ public PushRuntime(IScriptRuntime runtime, IntPtr comRuntime = default)

public void Dispose()
{
#if IS_FXSERVER
#if IS_FXSERVER && !OS_WIN
ms_runtimeHandler.PopRuntime(m_actualRuntime);
#else
ms_popMethod.method(ms_runtimeHandlerIface, m_runtime);
Expand Down
Expand Up @@ -376,7 +376,7 @@ static bool GI_WalkStackBoundary(MonoString* resourceName, MonoArray* start, Mon
return true;
}

#ifndef IS_FXSERVER
#if !defined(IS_FXSERVER) || defined(_WIN32)
MonoMethod* g_tickMethod;

extern "C" DLL_EXPORT void GI_TickInDomain(MonoAppDomain* domain)
Expand Down Expand Up @@ -540,7 +540,7 @@ static void InitMono()
method_search("CitizenFX.Core.RuntimeManager:CreateObjectInstance", g_createObjectMethod);
method_search("System.Diagnostics.EnhancedStackTrace:GetMethodDisplayString", g_getMethodDisplayStringMethod);

#ifndef IS_FXSERVER
#if !defined(IS_FXSERVER) || defined(_WIN32)
method_search("CitizenFX.Core.InternalManager:TickGlobal", g_tickMethod);
#endif

Expand Down
1 change: 1 addition & 0 deletions code/premake5.lua
Expand Up @@ -419,6 +419,7 @@ if _OPTIONS['game'] ~= 'launcher' then
end

if os.istarget('windows') then
defines { 'OS_WIN' }
nuget {
"Microsoft.DotNet.GenAPI:6.0.0-beta.21063.5",
"Microsoft.DotNet.GenFacades:6.0.0-beta.21063.5",
Expand Down

0 comments on commit 62e1a14

Please sign in to comment.