• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

C# - how efficient does this look?

Red Squirrel

No Lifer
In terms of cpu and memory, how efficient would this system be?


/*
##############################
Official Age of Valor Script
http://www.uovalor.com

Coded by Red Squirrel
redsquirrel@iceteks.com
##############################
*/

using Server;
using System;
using System.Collections.Generic;

namespace Server.Items
{

//to make an item/ability use this system simply add another entry in this list:

public enum DelayContextType
{
TestItem1,
TestItem2,
TestItem3,
Spell,
WeaponAbility,
Potion,
};



public class UseDelaySystem
{
/*
Functions:
AddContext(Mobile m, DelayContextType type, TimeSpan delay) //set a use delay
RemoveContext(Mobile m,DelayContextType type) //prematurely remove a delay (returns true if it existed already)
CheckContext(Mobile m, DelayContextType type) //check if a delay exists for specified abiliy (returns true if it exists)
*/

//----START SYSTEM----


public class DelayContextArray
{
private Dictionary<DelayContextType,DateTime> Contexts = new Dictionary<DelayContextType,DateTime>();

public DelayContextArray()
{
}

public bool Contains(DelayContextType dct)
{
DateTime context;

if(Contexts.TryGetValue(dct,out context))
{
//Console.WriteLine("context: {0}",context);//debug
if(context>DateTime.Now)return true;
else Contexts.Remove(dct);
}
//Console.WriteLine("-context: {0}",context);//debug
return false;
}

public bool Remove(DelayContextType dct)
{
DateTime context;

if(Contexts.TryGetValue(dct,out context))
{
if(context>DateTime.Now)
{
Contexts.Remove(dct);
return true;
}
}
return false;
}

public void Add(DelayContextType dct,TimeSpan delay)
{
DateTime context;

if(Contexts.TryGetValue(dct,out context))
{
//Console.WriteLine("contains {0}, removing... {1}",dct,context);//debug
Contexts.Remove(dct);
}

//Console.WriteLine("Adding...{0} {1}",dct,delay);//debug
Contexts[dct] = DateTime.Now+delay;
}
}


private static Dictionary<Mobile, DelayContextArray> UseDelayMain = new Dictionary<Mobile, DelayContextArray>();


//checks if m is still being delayed by "type" context (ex: need to wait again to use that ability type)
public static bool CheckContext(Mobile m, DelayContextType type)
{
DelayContextArray array;

if(UseDelayMain.TryGetValue(m,out array))
{
return array.Contains(type);
}

return false;
}


//removes context. Returns true if it did exist, or false if it did not
public static bool RemoveContext(Mobile m,DelayContextType type)
{
DelayContextArray array;

if(UseDelayMain.TryGetValue(m,out array))
{
if(array.Remove(type)) return true;
}
return false;
}




//tries to add a context with a delay
public static void AddContext(Mobile m, DelayContextType type,TimeSpan delay)
{
DelayContextArray array;

if(!UseDelayMain.TryGetValue(m,out array))
{
//Console.WriteLine("Cant find array, adding...");//debug
array = new DelayContextArray();
UseDelayMain[m] = array;
}

array.Add(type,delay);
}

}
}




I'd be calling up the 3 bottom functions directly at all times, kind of like this:


public override void OnDoubleClick( Mobile from )
{
if(UseDelaySystem.CheckContext(from,DelayContextType.TestItem2))
{
from.SendMessage("You must wait to use this again");
return;
}

from.SendMessage("You use UseDelayTestItem2");

UseDelaySystem.AddContext(from, DelayContextType.TestItem2,TimeSpan.FromSeconds(10));
}




In terms of scale, lets assume theres over 100k active mobiles in the program and my enum has maybe 30 entries. (currently I have 36k total, let alone active, but that grows over time)

I originally was going to use hash tables but decided to use dictionaries as I was told they're better, and I can also loop through them. (I'll be making a cleanup process to go through and delete all the entries that have expired but never been checked)
 
I usually use timers around my objects for which I need to estimate (more like guesstimate) the speed/performance ratio. You can always run a loop around methods that you think are "resource intensive" and monitor the CPU/Memory/PF usage from the task manager. Just write a unit test that will instantiate the object and try to mimic your actual work-load scenario using loops...

Coming back to your original question, I think you'll have to nail down exactly where the .NET Framework will have to implicitly cast reference types to value types and vice versa. It is a good thing that you're using a Dictionary as opposed to a HashTable, but Generics will optimize the code based on types. In your case, DateTime objects are value types, and hence storing them in a Dictionary will not slow things down. Again, the first optimization technique I would recommend is to figure out where else in your code you might be forcing an explicit/implicit cast from reference types to value types and vice versa. Then try and optimize those portions by removing the casts - use more generics, create structs, etc.
 
Back
Top