myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
   » Plugin für Firefox
   » Plugin für IE
   » Gadget für Windows
» Regeln
» Wie poste ich richtig?
» Datenschutzerklärung
» wbb-FAQ

Mitglieder
» Liste / Suche
» Stadt / Anleitung dazu
» Wer ist wo online?

Angebote
» ASP.NET Webspace
» Bücher
» Zeitschriften
   » dot.net magazin
» Accessoires

Ressourcen
» .NET-Glossar
» guide to C#
» openbook: Visual C#
» openbook: OO
» .NET BlogBook
» MSDN Webcasts
» Search.Net

Team
» Kontakt
» Übersicht
» Wir über uns
» Bankverbindung
» Impressum

» Unsere MiniCity
MiniCity
» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Gemeinschaft » .NET-Komponenten und C#-Snippets » Zeiger auf generics+ Struktur<->bytes 4x schneller
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | An Freund senden | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Zeiger auf generics+ Struktur<->bytes 4x schneller

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Floste
myCSharp.de-Mitglied

images/avatars/avatar-2376.jpg


Dabei seit: 13.06.2007
Beiträge: 1.130
Entwicklungsumgebung: VS 2008
Herkunft: Norddeutschland


Floste ist offline

Zeiger auf generics+ Struktur<->bytes 4x schneller

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Beschreibung:

Normalerweise kann man keine zeiger auf Variablen generischer Typen erstellen. Der folgende Code macht aber genau das. Man muss aber aufpassen, dass man nur mit Zeigern weiterarbeitet, während das Objekt als ref-Parameter an eine belibige Methode übergeben wurde, denn das entspricht von den Opcodes exakt einem fixed-statement oder das Objekt direkt auf dem Stack liegt.

Man kann mit der Methode gut strukturen in bytearrays kopieren (und umgekehrt). Das geht sogar 4x soschnell wie mit den marschal-methoden.

C#-Code:
using System;
using System.Reflection;
using System.Reflection.Emit;

using BF = System.Reflection.BindingFlags;
using System.Runtime.InteropServices;

namespace Krimskrams
{
    public static class UnsafeHelper
    {
        /// <see cref="UnsafeHelper<T>.GetPtr"/>
        public static unsafe void* GetPtr<T>(ref T arg) where T : struct
        {
            return UnsafeHelper<T>.GetPtr(ref arg);
        }


        public static unsafe void MoveMemory<T1, T2>(ref T1 dest, ref T2 src, int size)
            where T1 : struct
            where T2 : struct
        {
            MoveMemory(UnsafeHelper<T1>.GetPtr(ref dest), UnsafeHelper<T2>.GetPtr(ref src), size);
        }

        public static unsafe void MoveMemory<T>(ref T dest, void* src, int size) where T : struct
        {
            MoveMemory(UnsafeHelper<T>.GetPtr(ref dest), src, size);
        }

        public static unsafe void MoveMemory<T>(int numDestObjs,ref T dest, void* src) where T : struct
        {
            MoveMemory(UnsafeHelper<T>.GetPtr(ref dest), src, numDestObjs * UnsafeHelper<T>.Size);
        }

        public static unsafe void MoveMemory<T>(void* dest, ref T src, int size) where T : struct
        {
            MoveMemory(dest, UnsafeHelper<T>.GetPtr(ref src), size);
        }

        public static unsafe void MoveMemory<T>(void* dest,int numSrcObjs, ref T src) where T : struct
        {
            MoveMemory(dest, UnsafeHelper<T>.GetPtr(ref src), numSrcObjs * UnsafeHelper<T>.Size);
        }

        [DllImport("Kernel32.dll", EntryPoint="RtlMoveMemory", SetLastError=false)]
        public static unsafe extern void MoveMemory(void* dest, void* src, int size);

        /// <remarks>Schneller bei mehrmaligem Aufruf! Anders als bei Marshal.SizeOf wird char mit 2 bytes übersetzt!</remarks>
        /// <see cref="UnsafeHelper<T>.Size"/>
        public static int SizeOf<T>()
        {
            return UnsafeHelper<T>.Size;
        }

        /// <remarks>Langsamer bei mehrmaligem Aufruf. Anders als bei Marshal.SizeOf wird char mit 2 bytes übersetzt!</remarks>
        public static int SizeOf(Type type)
        {
            object[] attrs=type.GetCustomAttributes(typeof(StructLayoutAttribute), false);
            if (attrs.Length > 0)
            {
                StructLayoutAttribute attr = (StructLayoutAttribute)attrs[0];
                if (attr.Size > 0) return attr.Size;
            }

            if (type.IsPrimitive)
            {
                if (type == typeof(IntPtr))
                    return IntPtr.Size;

                if (type == typeof(double) ||
                    type == typeof(long) ||
                    type == typeof(ulong))
                    return 8;

                if (type == typeof(float) ||
                    type == typeof(int) ||
                    type == typeof(uint))
                    return 4;

                if (type == typeof(char) ||
                    type == typeof(short) ||
                    type == typeof(ushort))
                    return 2;

                if (type == typeof(bool) ||
                    type == typeof(sbyte) ||
                    type == typeof(byte))
                    return 1;
            }
            else if (type.IsPointer)
            {
                return IntPtr.Size;
            }
            else if (type.IsValueType)
            {
                int sum = 0;
                foreach (FieldInfo info in type.GetFields(BF.Instance | BF.Public | BF.NonPublic))
                {
                    sum += SizeOf(info.FieldType);
                }
                return sum;
            }
            throw new NotSupportedException(type.FullName);
        }
    }

    public static class UnsafeHelper<T>
    {
        public unsafe delegate void* getPtrFunc(ref T value);
        public unsafe readonly static getPtrFunc GetPtr = BuildFunction();
        public static readonly int Size = UnsafeHelper.SizeOf(typeof(T));
        private static DynamicMethod method;

        private unsafe static getPtrFunc BuildFunction()
        {
            method = new DynamicMethod("getPtr<" + typeof(T).FullName.Replace(".", "<>") + ">",
                typeof(void*), new Type[1] { typeof(T).MakeByRefType() }, typeof(UnsafeHelper).Module);

            ILGenerator generator = method.GetILGenerator();
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Conv_U);
            generator.Emit(OpCodes.Ret);
            return (getPtrFunc)method.CreateDelegate(typeof(getPtrFunc));
        }
    }
}

Schlagwörter: pointer generic generics

[EDIT] Unsinnige Methode entfernt
[EDIT2]
Überarbeitet:
Man kann jetzt ganze Arrays umkopieren. (einfach MoveMemory(anzahlArrayElemente,ref meinArray[0],meinZeiger); )

3. @Peter: Ich habe versucht einen bequemen und sehr schnellen "binarywriter" für nicht verwalteten speicher zu schreiben. (für Grafikdaten)

Dieser Beitrag wurde 4 mal editiert, zum letzten Mal von Floste am 29.01.2010 11:52.

26.01.2010 21:20 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Peter Bucher Peter Bucher ist männlich
myCSharp.de-Poweruser/ Experte

images/avatars/avatar-2785.jpg


Dabei seit: 17.03.2005
Beiträge: 5.869
Entwicklungsumgebung: VS08
Herkunft: Zentralschweiz


Peter Bucher ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Salute Floste

Und wo braucht man das? :-)


Gruss Peter
27.01.2010 22:03 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
FZelle
myCSharp.de-Poweruser/ Experte

Dabei seit: 23.04.2004
Beiträge: 8.986


FZelle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Wenn man viel Hackt und/oder mit Binärdaten von Anderen basteln will/muss.
28.01.2010 09:46 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 4 Jahre.
Der letzte Beitrag ist älter als 4 Jahre.
Antwort erstellen


© Copyright 2003-2014 myCSharp.de-Team. Alle Rechte vorbehalten. 23.10.2014 01:51