Eliminating visitor pattern in C# - c#

I have code that looks like this:
var visitor = new ImplementsVisitor();
for(int i = 0; i < array.Length; ++i)
arrray[i].Accept(visitor);
Each element in the array implements IItem interface, which has an Accept(IVisitor) method. Nothing but the standard visitor pattern.
While measuring performance, I came to the conclusion that the call by interface is too slow, and in this code is performance is critical. From your experience, what would be the best option of eliminating any virtual or interface calls? An if statement that checks for the concrete type? An enum on each element with a switch/case (in this case, the code's structure is such that no cast will be required)? Something else?
P.S. I cannot sort the items in the array. The order is important. Thus, I cannot sort them by concrete type to help branch prediction.

I created the following program. On my laptop the loop runs a million times in 8ms (that's a Release build, Debug is 11ms or so). That is approximately 0.000008ms to do the virtual dispatch and increment an int. Exactly how fast do you need it to be? I'd suspect that something has gone wrong with either your performance test or mine. If mine I'd be interested to hear suggestions for improvement.
Generally if performance at this level isn't good enough then using C# is probably a problem in itself. Its garbage collector has a habit of freezing threads in the middle of loops for example. If 0.000008ms on a loop iteration really is an issue, I'd suspect Assembly language or C would be a better choice.
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
const int count = 1000000;
IList<IItem> items = new List<IItem>(count);
for (int i = 0; i < count; i++)
{
var rnd = new Random();
if (rnd.NextDouble() > 0.5)
{
items.Add(new ClassA());
}
else
{
items.Add(new ClassB());
}
}
var visitor = new MyVisitor();
Stopwatch s = Stopwatch.StartNew();
for (int i = 0; i < items.Count; i++)
{
items[i].Accept(visitor);
}
s.Stop();
Console.WriteLine("ExecTime = {0}, Per Cycle = {1}", s.ElapsedMilliseconds, (double)s.ElapsedMilliseconds / count);
visitor.Output();
}
interface IVisitor
{
void Process(ClassA item);
void Process(ClassB item);
}
interface IItem
{
void Accept(IVisitor visitor);
}
abstract class BaseVisitor : IVisitor
{
public virtual void Process(ClassA item)
{
}
public virtual void Process(ClassB item)
{
}
}
class ClassA : IItem
{
public void Accept(IVisitor visitor)
{
visitor.Process(this);
}
}
class ClassB : IItem
{
public void Accept(IVisitor visitor)
{
visitor.Process(this);
}
}
class MyVisitor : BaseVisitor
{
int a = 0;
int b = 0;
public override void Process(ClassA item)
{
a++;
}
public override void Process(ClassB item)
{
b++;
}
public void Output()
{
Console.WriteLine("a = {0}, b = {1}", a, b);
}
}
}
}

You don't have one virtual call here, you have two, but you only need one. First your array presumably has a virtual call through IItem - but if these are all the same type, and you know the type (and it is sealed) a virtual call is unnecessary.
Then within the visited object, you need to do whatever operation the visitor wants to do. This will probably also involve a virtual call.
You might do better with a typed IVisitor:
interface IItem<TVisitor> : IItem
where TVisitor : IVisitor
{
void Accept(TVisitor visitor);
}
// Then
SpecialVisitor visitor = ImplementsSpecialVisitor();
foreach(var item in arrayOfSpecialItems){
item.Accept<SpecialVisitor>(visitor);
}

Related

I can't use a foreach loop twice in my code, why?

I am currently trying to learn C# and I am giving it a shot to implement Queue from scratch.
Currently I am trying to implement foreach functionality so I can print out my queue.
I have an issue when I use a foreach loop twice in my code it wont print anything the second time I use it. I have managed to see that my Current method in the Queue class isn't being used the second time I use the foreach loop (with help of the print statement of the int position variable, which doesnt print out anything the second time a foreach is being used).
I appreciate any help to understand why I can't use a foreach loop twice in my code. And if there is anything else which can be improved with my code, that would be greatly appreciated as well.
The RunTest class below is where I test my implementation of my Queue class.
namespace RunTest
{
class RunTest
{
public static void Main(string[] args){
Queue<string> queueOfStrings = new Queue<string>();
queueOfStrings.Enqueue("Dog");
queueOfStrings.Enqueue("Cat");
queueOfStrings.Enqueue("Mouse");
queueOfStrings.Enqueue("Bird");
System.Console.WriteLine("Foreach: \n");
foreach(string item in queueOfStrings){
System.Console.WriteLine(item);
}
System.Console.WriteLine("\n");
System.Console.WriteLine("Peek: "+queueOfStrings.Peek());
System.Console.WriteLine("Dequeue : "+queueOfStrings.Dequeue());
System.Console.WriteLine("Peek: "+queueOfStrings.Peek());
System.Console.WriteLine("Foreach: ");
foreach(string item2 in queueOfStrings){
System.Console.WriteLine(item2);
}
}
}
}
And here is my Queue class:
using System;
using System.Collections;
using System.Collections.Generic;
public class Queue<T> : IEnumerator,IEnumerable{
private LinkedList<T> list = new LinkedList<T>();
private T[] storeElements;
private int position = -1;
public Queue()
{
Console.WriteLine("Queue initialized \n");
}
public void Enqueue(T data){
list.AddFirst(data);
}
public int Count(){
return list.Count;
}
public void Clear(){
list.Clear();
}
public T Dequeue(){
T data = list.Last.Value;
list.RemoveLast();
return data;
}
public T Peek(){
return list.Last.Value;
}
private void ToArray(){
storeElements = new T[Count()];
list.CopyTo(storeElements, 0);
Array.Reverse(storeElements);
}
//IEnumerator and IEnumerable require these methods.
public IEnumerator GetEnumerator()
{
ToArray();
return (IEnumerator)this;
}
//IEnumerator
public bool MoveNext()
{
position++;
return (position < Count());
}
//IEnumerable
public void Reset()
{
position = 0;
}
//IEnumerable
public object Current
{
get { System.Console.WriteLine(position); return storeElements[position];}
}
}
Using the queue itself as the enumerator isn't a great idea-- it will really limit how the class can be used. Imagine for example if you wanted to check the queue for duplicates-- you'd have to create a nested loop, which means two simultaneous enumerators. It simply wouldn't work because there is only one position variable.
Take a look at how built-in classes do it. They return a new instance of a separate enumerator class (e.g. an array will create a SZArrayEnumerator). In your case, you can probably leverage the enumerator provided by the backing field itself, like this:
public IEnumerator GetEnumerator()
{
ToArray();
return storeElements.GetEnumerator();
}

Why aren't delegate instances always cached?

Why does the C# compiler not create code which caches the delegate instance of Action(SomeMethod) in this case:
void MyMethod() {
Decorator(SomeMethod);
}
void Decorator(Action a) { a(); }
void SomeMethod() { }
It does it only when SomeMethod is static:
static void SomeMethod() { }
EDIT:
To be clearer, let's take the following code:
class A {
public void M1() {
var b = new B();
b.Decorate(M2);
}
public void M2() {
}
}
class B {
public void Decorate(Action a) {
Console.WriteLine("Calling");
a();
}
}
If you want to avoid the delegate allocation every time M1 is called, you can do it easily but it's quite ugly:
using System;
class A {
Action _m2;
public A() {
_m2 = new Action(M2);
}
public void M1() {
var b = new B();
b.Decorate(_m2);
}
public void M2() {
}
}
class B {
public void Decorate(Action a) {
Console.WriteLine("Calling");
a();
}
}
So my question was, what's the reason the compiler cannot generate a similar code? I can't see any side effects.
I'm not saying there's no reason, the people working on the compiler are much smarter than I will probably ever be. I'm only looking to understand which scenarios this won't work.
It can't cache it for instance methods because the target instance is part of the delegate, and it really wants to use a static field for the cache. A static method call that doesn't capture any variables etc can be cached very cheaply, but it gets a lot more complex when state is involved, and this counts as state.
Yes, I suppose is could use an instance field to cache () => this.SomeMethod(), but frankly, this being the target is a relatively rare case and doesn't solve the general problem.
However, it also only does this for lambda syntax, i.e. even if SomeMethod is static
Decorator(SomeMethod); // not cached
Decorator(() => SomeMethod()); // cached
You can see the difference here
This is because the difference is detectable (different object refs vs same object ref) and could in theory lead to different program behavior in existing code that used the original (non-lambda) syntax; so the cache provision has not to-date been applied retrospectively to the old syntax. Compatibility reasons. This has been discussed for years, though; IMO it is one of those things like the change to foreach L-value captures, that could probably be changed without breaking the world as much as we imagine.
To see the theoretical difference in an example based on the edited question:
using System;
class A
{
static void Main()
{
var obj = new A();
Console.WriteLine("With cache...");
for (int i = 0; i < 5; i++) obj.WithCache();
Console.WriteLine("And without cache...");
for (int i = 0; i < 5; i++) obj.WithoutCache();
}
Action _m2;
B b = new B();
public void WithCache() => b.Decorate(_m2 ??= M2);
public void WithoutCache() => b.Decorate(M2);
public void M2() => Console.WriteLine("I'm M2");
}
class B
{
private object _last;
public void Decorate(Action a)
{
if (_last != (object)a)
{
a();
_last = a;
}
else
{
Console.WriteLine("No do-overs!");
}
}
}
This currently outputs:
With cache...
I'm M2
No do-overs!
No do-overs!
No do-overs!
No do-overs!
And without cache...
I'm M2
I'm M2
I'm M2
I'm M2
I'm M2

How should an abstract class be written to override method with additional parameters

I am wondering how I should have written the following code?
I wanted to have a base class, and have one of the derived classes override one of the methods in the base class. But I need a different signature for the method that is to be overridden (To complicate things more, that method is buried in a loop).
How should I have properly structured the following code to accomplish the equivalent of overriding a method with a different signature?
(Getting rid of the abstract declaration is OK to do)
abstract class ClassBase
{
public void LoopThroughStuff(int i)
{
for (i = 0; i < 10; i++)
{
//DO A BUNCH OF STUFF
var k = (something determined in loop) //THIS IS USED IN Class2's DoSomething(i,k)
DoSomething(i); //THIS NEEDS TO BE OVERRIDDEN IN Class2 WITH ADDITIONAL PARAMETER, WHICH I KNOW CAN'T BE DONE
//DO A BUNCH OF STUFF
}
}
public virtual void DoSomething1(int x)
{
//DO STUFF
}
}
public class Class1 : ClassBase
{
}
public class Class2 : ClassBase
{
public override void DoSomething1(int j, int k) //I KNOW THIS CAN NOT BE DONE
{
//DO STUFF
}
}
There are a number of options. Here's one: use generics.
abstract class ClassBase<T>
{
public abstract void DoSomething(T args);
}
public class Class1 : ClassBase<Class1Args>
{
public void DoSomething(Class1Args args);
}
public class Class1Args
{
public int x;
}
public class Class2 : ClassBase<Class2Args>
{
public void DoSomething(Class2Args args);
}
public class Class2Args
{
public int j;
public int k;
}
Inheritance may be overkill for what you're doing. Reverse your thinking and try a functional style instead.
Start with an array or list (of any type) then use the Select method with a lamba or Func object that will "map" or perform a transform on each element of the array and return a new array or list.
string [] array = {"element1", "element2"};
Func<string, string> DoSomething = (x) => x.ToUpper();
var result = array.Select(DoSomething);
or more succinctly:
var result = array.Select(x => x.ToUpper());
Do the base class like the following code, which uses Function overloading which is a type of Polymorphism. a starting reference for basic OOP can be found here
abstract class ClassBase
{
public virtual void LoopThroughStuff(int i)
{
for (i = 0; i < 10; i++)
{
//DO A BUNCH OF STUFF
DoSomething(i);
//DO A BUNCH OF STUFF
}
}
public virtual void DoSomething1(int x)
{
//DO STUFF
}
public virtual void DoSomething1(int j, int k)
{
//you can keep this empty, as you will override it in Class2
}
}
public class Class2 : ClassBase
{
public override void LoopThroughStuff(int i)
{
for (i = 0; i < 10; i++)
{
//DO A BUNCH OF STUFF
// set k here as you like
DoSomething(i,k);
//DO A BUNCH OF STUFF
}
}
public override void DoSomething1(int j, int k)
{
//DO STUFF
}
}

With Statement in C# like that of AS3/GML

I'm making a game using Monogame, and I've been trying to figure out how to implement a function that acts similarly to AS3's and GML's with statement.
So far I have a system that works, but not entirely the way I want it to. I store my GameObjects in a Dictionary of Lists. This is so I can get to the specific type of object I want to access without having to loop through a list of ALL objects. The key used is the name of the type.
public static Dictionary<string, List<GameObject>> All =
new Dictionary<string, List<GameObject>>();
I access all of a specific type of object using AllOf. If a List containing that type exists in the Dictionary, it returns that List, else it returns an empty list.
public static List<GameObject> AllOf(Type type)
{
string key = type.Name;
if(All.ContainsKey(key))
{
return All[key];
}
return new List<GameObject>();
}
An example of how these are implemented
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
}
}
But I'd rather use something similar to the AS3/GML with statement, which would also allow for other, non-member codes to be executed.
with(typeof(Dummy))
{
Update(gameTime);
foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
Is there a way to accomplish this? My end goal is just to make my code look a little cleaner, and make it easier to make a lot of changes without having to type out a for loop each time.
No such syntax exists in C#, but you can access methods within the for that have nothing to do with the collection:
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
}
Note that you can also use foreach, which is a little cleaner if you don't need the indexer:
foreach(var item in list)
{
item.Update(gameTime);
item.foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
try
using(Object myObject = new Object()){
}
i think this might be what your looking to use?
I have a small solution for this use case. This may be a bit of a necropost, but it is a pretty neat solution. Additionally, I think all of the C# features that are required existed back when this question was asked.
You can do something very similar to the GML with(x){} by using some form of delegate as a parameter to a static method, and passing a lambda as that parameter. The function can even be genericised, and you can call it without the class name by the using static statement. You will need to explicitly provide the typed/named parameter, but it is possible. You would need to hook it up to your own types, but the general idea is:
namespace NiftyStuff {
public static class With {
public static void with<T>(Action<T> proc) where T : GameObj {
var typeName = typeof(T).Name;
foreach (var item in GameObj.AllOf(typeName)) { proc((T)item); }
}
}
public class GameObj {
private static Dictionary<string, List<GameObj>> All = new Dictionary<string, List<GameObj>>();
public static List<GameObj> AllOf(string name) {
return All.ContainsKey(name) ? All[name] : null;
}
public static void Add(GameObj foo) {
string typeName = foo.GetType().Name;
List<GameObj> foos = All.ContainsKey(typeName) ? All[typeName] : (All[typeName] = new List<GameObj>());
foos.Add(foo);
}
public float x, y, angle;
public GameObj() { x = y = angle = 0; }
public void Destroy() { AllOf(GetType().Name)?.Remove(this); }
}
public class Enemy : GameObj {
public float maxHealth, curHealth;
public Enemy() : base() { maxHealth = curHealth = 300; }
public Enemy(float health) : base() { maxHealth = curHealth = health; }
public bool Damage(float amt) {
if (curHealth > 0) {
curHealth -= amt;
return curHealth <= 0;
}
return false;
}
}
public class Pumpkin : GameObj {
public bool exists = false;
public Pumpkin() : base() { exists = true; }
public bool LookAt() { return (exists = !exists); }
}
}
Actually using the above code would work as follows:
using NiftyStuff;
using static NiftyStuff.With;
//...
with ((Enemy e) => {
if (e.Damage(50)) {
Log("Made a kill!"); // Whatever log function you have...
}
});
with ((Pumpkin p) => {
if (p.LookAt()) {
Log("You see the pumpkin");
} else {
Log("You no longer see the pumpkin");
}
});
While not exactly like GML's with statement, it would at least let you run code against all of the registered objects of some type.
One important note is that you can't destroy objects inside of a with this way (due to concurrent modification of a collection while iterating it). You would need to collect all objects to be destroyed, and then remove them from the list in All, typically in a game loop this is done at the end of a frame.
Hope this helps, despite being 2 years out of date.

Faster enumeration: Leveraging Array Enumeration

So, I have a class with an array inside. Currently, my strategy for enumerating over the class's items is to use the code, foreach (item x in classInstance.InsideArray) . I would much rather use foreach (item x in classInstance) and make the array private. My main concern is that I really need to avoid anything slow; the array gets hit a lot (and has a couple hundred items). It is vital that enumerating over this array is cheap. One thought was to just have the class implement IEnumerable<item>, but InsideArray.getEnumerator() only gives me a non-generic enumerator. I also tried implementing the IEnumerable interface. This worked but was very slow, possibly due to boxing.
Is there a way to make the class itself enumerable without a performance hit?
Normal Code:
//Class
public class Foo {
//Stuff
public Item[,] InsideArray {get; private set;}
}
//Iteration. Shows up all over the place
foreach (Item x in classInstance.InsideArray)
{
//doStuff
}
Adjusted, much slower code:
//Class
public class Foo : IEnumerable {
//Stuff
private Item[,] InsideArray;
System.Collections.IEnumerator System.Collections.IEnumerable GetEnumerator()
{
return InsideArray.GetEnumerator();
}
}
//Iteration. Shows up all over the place
foreach (Item x in classInstance)
{
//doStuff
}
Note: Adding an implementation for the nongeneric iterator is possible and faster than my slow solution, but it is still a bit worse than just using the array directly. I was hoping there was a way to somehow tell C#, "hey, when I ask you to iterate over this object iterate over it's array, just as fast," but apparently that is not quite possible...at least from the answers suggested thus far.
A bespoke iterator might make it quicker (edited to return as known type):
Basic: 2468ms - -2049509440
Bespoke: 1087ms - -2049509440
(you would use the ArrayIterator directly as Foo's GetEnumerator - essentially copying the code from ArrayEnumerator.GetEnumerator; my point is to show that a typed iterator is faster than the interface)
With code:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
class Foo
{
public struct ArrayIterator<T> : IEnumerator<T>
{
private int x, y;
private readonly int width, height;
private T[,] data;
public ArrayIterator(T[,] data)
{
this.data = data;
this.width = data.GetLength(0);
this.height = data.GetLength(1);
x = y = 0;
}
public void Dispose() { data = null; }
public bool MoveNext()
{
if (++x >= width)
{
x = 0;
y++;
}
return y < height;
}
public void Reset() { x = y = 0; }
public T Current { get { return data[x, y]; } }
object IEnumerator.Current { get { return data[x, y]; } }
}
public sealed class ArrayEnumerator<T> : IEnumerable<T>
{
private readonly T[,] arr;
public ArrayEnumerator(T[,] arr) { this.arr = arr; }
public ArrayIterator<T> GetEnumerator()
{
return new ArrayIterator<T>(arr);
}
System.Collections.Generic.IEnumerator<T> System.Collections.Generic.IEnumerable<T>.GetEnumerator()
{
return GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public int[,] data;
public IEnumerable<int> Basic()
{
foreach (int i in data) yield return i;
}
public ArrayEnumerator<int> Bespoke()
{
return new ArrayEnumerator<int>(data);
}
public Foo()
{
data = new int[500, 500];
for (int x = 0; x < 500; x++)
for (int y = 0; y < 500; y++)
{
data[x, y] = x + y;
}
}
static void Main()
{
Test(1); // for JIT
Test(500); // for real
Console.ReadKey(); // pause
}
static void Test(int count)
{
Foo foo = new Foo();
int chk;
Stopwatch watch = Stopwatch.StartNew();
chk = 0;
for (int i = 0; i < count; i++)
{
foreach (int j in foo.Basic())
{
chk += j;
}
}
watch.Stop();
Console.WriteLine("Basic: " + watch.ElapsedMilliseconds + "ms - " + chk);
watch = Stopwatch.StartNew();
chk = 0;
for (int i = 0; i < count; i++)
{
foreach (int j in foo.Bespoke())
{
chk += j;
}
}
watch.Stop();
Console.WriteLine("Bespoke: " + watch.ElapsedMilliseconds + "ms - " + chk);
}
}
Cast your array to IEnumerable<item> before calling GetEnumerator() and you'll get the generic IEnumerator. For example:
string[] names = { "Jon", "Marc" };
IEnumerator<string> enumerable = ((IEnumerable<string>)names).GetEnumerator();
It may well still be a bit slower than enumerating the array directly with foreach (which the C# compiler does in a different way) but at least you won't have anything else in the way.
EDIT:
Okay, you said your other attempt used an indexer. You could try this approach, although I don't think it'll be any faster:
public IEnumerable<Item> Items
{
get
{
foreach (Item x in items)
{
yield return x;
}
}
}
An alternative would be to try to avoid using a two-dimensional array to start with. Is that an absolute requirement? How often are you iterating over a single array after creating it? It may be worth taking a slight hit at creation time to make iteration cheaper.
EDIT: Another suggestion, which is slightly off the wall... instead of passing the iterator back to the caller, why not get the caller to say what to do with each item, using a delegate?
public void ForEachItem(Action action)
{
foreach (Item item in items)
{
action(item);
}
}
Downsides:
You incur the penalty of a delegate call on each access.
It's hard to break out of the loop (other than by throwing an exception). There are different ways of approaching this, but let's cross that bridge when we come to it.
Developers who aren't familiar with delegates may get a bit confused.
How about adding an indexer to the class:
public MyInsideArrayType this[int index]
{
get{return this.insideArray[index];
}
And if you REALLY need foreach capabilities:
public IEnumerable<MyInsideArrayType> GetEnumerator()
{
for(int i = 0; i<this.insideArray.Count;i++)
{
yield return this[i];
}
}
All forms of iteration are cheap. If anyone in this day-and-age managed to somehow write and publish an expensive iterator they would be (rightly) burned at the stake.
Premature optimization is evil.
Cheers. Keith.

Categories

Resources