Jump to content
Unity Insider Forum
  • Announcements

    • Lars

      Allgemeine Forenregeln   03/13/2017

      Forenregeln Nimm dir bitte einen Moment um die nachfolgenden Regeln durchzulesen. Wenn du diese Regeln akzeptierst und die Registration fortsetzen willst, klick einfach auf den "Mit der Registrierung fortfahren"-Button. Um diese Registration abzubrechen, klick bitte einfach auf den "Zurück" Button deines Browsers. Wir garantieren nicht für die Richtigkeit, Vollständigkeit und Brauchbarkeit der Nachrichten und sind auch nicht dafür verantwortlich. Die Beiträge drücken die Meinung des Autors des Beitrags aus, nicht zwangsläufig das, wofür die Forensoftware steht. Jeder Nutzer, der denkt, dass ein veröffentlichter Beitrag unzulässig bzw. störend ist, ist aufgefordert uns unverzüglich per E-Mail zu kontaktieren. Wir haben das Recht störende Beiträge zu löschen und bemühen uns, das in einem realistischem Zeitraum zu erledigen (sofern wir beschlossen haben, dass die Löschung notwendig ist). Du akzeptierst, durchgehend während der Nutzung dieses Services, dass du dieses Forum nicht dazu missbrauchen wirst, Inhalte zu veröffentlichen, welche bewusst falsch und/oder verleumderisch, ungenau, beleidigend, vulgär, hasserfüllt, belästigend, obszön, sexuell belästigend, bedrohlich, die Privatsphäre einer Person verletzend oder in irgend einer Art und Weise das Gesetz verletzen. Des Weiteren akzeptierst du, dass du keine urheberrechtlich geschützte Inhalte ohne Erlaubnis des Besitzers in diesem Forum veröffentlichst. Mit dem Klick auf den "Mit der Registrierung fortfahren"-Button, akzeptierst du zudem unsere Datenschutzerklärung und stimmst der Speicherung deiner IP-Adresse und personenbezogenen Daten zu, die dafür benötigt werden, um dich im Falle einer rechtswidrigen Tat zurückverfolgen zu können bzw. permanent oder temporär aus dem Forum ausschließen zu können. Es besteht keine Pflicht zur Abgabe der Einwilligung, dies erfolgt alles auf freiwilliger Basis.   Zusatzinformationen Der Forenbetreiber hat das Recht, Nutzer ohne Angabe von Gründen permanent aus dem Forum auszuschließen. Des Weiteren hat er das Recht, Beiträge, Dateianhänge, Umfrage, Blogeinträge, Galleriebilder oder Signaturen ohne Angabe von Gründen zu entfernen. Mit der Registrierung verzichtest du auf alle Rechte an den von dir erstellten Inhalten, bzw. treten diese an das Unity-Insider.de und Unity-Community.de ab. Dies bedeutet im Klartext, dass das Unity-Insider.de und Unity-Community.de frei über deine Texte verfügen kann, sofern diese nicht wiederum die Rechte anderer verletzen. Es besteht weiterhin kein Anspruch von registrierten Nutzern bzw. ehemaligen registrierten Nutzern darauf, dass erstellte Inhalte und/oder die Mitgliedschaft (User) wieder gelöscht werden (Erhaltung der Konsistenz dieses Forums).   Einwilligungserklärung Wenn du mit der Speicherung deiner personenbezogenen Daten sowie den vorstehenden Regeln und Bestimmungen einverstanden bist, kannst du mit einem Klick auf den Mit der Registrierung fortfahren-Button unten fortfahren. Ansonsten drücke bitte Zurück. Stand: 07.03.2011

runner78

Members
  • Content count

    46
  • Joined

  • Last visited

  • Days Won

    3

runner78 last won the day on November 26 2017

runner78 had the most liked content!

Community Reputation

14 Gut

About runner78

  • Rank
    Advanced Member

Recent Profile Visitors

490 profile views
  1. GC Performance verbessern.

    Structs sind generell nicht vom GC betroffen, sobald du aber eine eigene Klasse machst, dann hast du den GC am Hals. Ich bin schon seit einiger Zeit dabei einen Octree/Quadtree so gut es geht GC-frei umzusetzen, dabei sind alle Nodes structs. Diese speichere ich sie in einem dictionary mit einem Index. Durch einfache Mathematik kann ich dann aus einer Position den Index ermitteln und auch den ganzen Node-tree und kann anhand der Indices nachschauen, ob ein Node existiert. Da ist momentan das Dictionary der Hacken, hier experimentiere ich derzeit mit eigenen Listtypen. Mit unsafe code und dem c# 7 ref return könnte man sehr effiziente Liste erzeugen.
  2. Unity 2017 und .NET 4.6

    Ich glaube das könnte wirklich Hyperthreading liegen. Wenn man jetzt aber anfängt manuell die Thread auf bestimmte Kerne zu beschränken, kann es aber auch dazukommen, dass man einen Kern erwischt, der vielleicht von einem anderen Prozess stärker Ausgelastet wird.
  3. Unity 2017 und .NET 4.6

    Windows kann Threads auch von Kern zu Kern schieben. In der Regel regelt das Betriebsystem es so, das die Threads optimial auf die Kerne verteilt werden.
  4. Unity 2017 und .NET 4.6

    Nachtrag: Wenn man das Codebeispiel in einer einfachen .net Konsoleanwendung ausprobiert, listet er die Thread korrekt. Entweder ein Bug von Unity, oder Unity verhindert hier bewusst das manipulieren der Threads.
  5. Unity 2017 und .NET 4.6

    Im Ressourcenmonitor von Windows kannst du nachsehen, wie viele Threads Unity verwendet, der Editor benutzt bei mir zwischen 124 und 127 Threads im Editromodus, im Gamemodus ca. 128 (Unity 2017.3.0f1) Ich denke, es ist wohl besser die Hände davon zu lassen, am Ende macht man alles nur schlimmer.
  6. Unity 2017 und .NET 4.6

    Ich habe auch schon Methoden gesehen, wo jemand erst ganz am ende den yield return gesetzt hatte.
  7. Unity 2017 und .NET 4.6

    Doch, Coroutinen sind von der Framerate abhängig, alles zwischen 2 yield returns wird in einem Frame ausgeführt. Bei einer fixen Framerate wäre die Ausführungsdauer unabhängig der Prozessorgeschwindigkeit immer gleich. Auch wenn die Anweßung zwischen zwei yields nur 2 Millisecunden dauert, wird bei 60 FPS erst 15 Millisekunden später wieder vorgesetzt. In solchen Fällen sollte man die Logik in einen seperaten Thred arbeiten lassen, und da ist async/await mit Task die nach meinen bisherigen Erfahrung die Variante mit dem geringsten Overhead. Auf welchen Prozessorkern was läuft, das entscheidet in der Regel das Betriebsystem. Ein unterschied ist noch, die Statemachine wird als Valuetype realiesiert, der Enumerator als Referenztype. async/await ist nicht wirklich dafür ausgelegt, Logik asynchron innerhalb der Anwendung auf dem Mainthread auszuführen, so wie es die Coroutine macht.
  8. Unity 2017 und .NET 4.6

    Asynchron bedeutend nicht automatisch im Hintergrund. Coroutinen sind abhängig von der Framerate, auch wenn der Prozessor noch Ressourcen frei hat, z.B. bei fixen Frameraten, wird die Ausführung unnötig in die länge gezogen. Ich werde mal heute Abend mal etwas experimentieren, mal sehen wie sich Coroutinen und async/await so in Sachen Performance so verhalten, wenn man im Mainthread bleibt. Ich war hier einfach zu faul es auszuschreiben Ein so ganz festes Pattern scheint Unity hier aber nicht zu haben. du musst nicht 2 Klassen machen, du kannst ja auch eine ScriptBehaviour machen, die bestehende Daten benutzt, ohne eine eigene DataComponent an das Entity zu hängen. Die Daten-Componenten sind alles structs, die werden nicht mehr von Unitys "Object" ableiten. Eigentlich ist es noch zu früh für diese Diskussion, da man noch nicht selbst reinschnuppern kann.
  9. Unity 2017 und .NET 4.6

    Hauptziel von async/await war die UI Programmierung, um den UI-Thread nicht zu blockieren. Coroutinen an sich blockieren immer den Main Thread, nur eben aufgeteilt auf mehrere Frames. Das neue Entity System benutzt ein "Data oriented design" und wurde für eine gute Zusammenarbeit mit dem c# Jobsystem entwickelt, das Multithreading auf das äußerste ausreizen dürfte. Wie ich in einem Anderen Thread schon geschrieben hatte, das neue System erfordert an einigen Stellen umdenken. Wo mehr Ram verbraucht wird: ScriptBehaviors bekommen immer eine Kopie der Daten die an den Entitäten hängen, das mag auf den ersten Moment ineffizient wirken, laut Unity ist es aber tatsächlich effizienter bei der Ausführung. Die Daten werden im Ram in Reih und Glied nebeneinander aufgereiht, dann greift beim iterieren eine Prozessoroptimierung und man braucht weniger Prozessorzyklen pro Iteration. Wo weniger Ram verbaucht wir: Instanz Felder oder Properties, die irgendwelche Daten halten die unabhängig von der Entität/GameObject sind. Sich ein wirkliches Bild von dem System machen kann man aber erst ab der 2018.1, es wurde ja auch gesagt, das man das System noch etwas Benutzerfreundlich machen will, besonders im Bezug auf das Jobsystem. Die erste Beta sollte schon im Laufe des Dezembers erscheinen, Das Entity System ist dann noch Experimentell, da könnte sich immer noch einiges an der Handhabung ändern.
  10. Unity 2017 und .NET 4.6

    Nachtrag zum "Hype": Task insbesondere mit async/await waren damals, als es neu war in der c# Welt schon ein Hype und heute in neuen Projekten im Grunde Standard. Unity ist da nur etwas spät dran, sowohl was .NET betrifft als auch dem Hype Ich Hype bei Unity Lieber das neue Job, Entity Componenten System wie auch die Nativen Listen und arrays.
  11. Unity 2017 und .NET 4.6

    In deinem Fall sind es aber sogar 3 Heap Objekte, einmal, der Iterator (IEnumerator und yield return laufen auch auf dem Heap), die Instanz der Automatisch generierte Klasse und noch das Array selbst. Die Variable bleibt solange im Heap, solange es mindestens eine Referenz darauf gibt, und da in unserem Beispiel die Variable an DoSomethingWith() weitergegeben wird, kann sich in dem Kontext über die Lebenszeit der Variable kein Aussage Treffen. Ich habe mal dein Beispiel etwa abgeändert: private int[] results = new int[1000]; IEnumerator StartLocal() { yield return new CoroutineThread(() => { for (var i = 0; i < this.results.Length; i++) { this.results[i] = Random.Range(0, 1000); Thread.Sleep(10); } }); } void DoSomethingWith() { // mach was mit this.results this.results = null; } Aus der Lambda wird im Hintergehend eine normale Methode, aber immer noch 2 mal Heap. Mit der "kleinen" Version deines CoroutineThread aus https://forum.unity-community.de/topic/11895-coroutinethread/ kämen noch 2 weitere Heap Objekte dazu, Thread und ThreadStart die du da jedes mal erstellst. Über Task und deine ThreadPool Version kann ich dazu nichts sagen.
  12. Unity 2017 und .NET 4.6

    Nach dem Umstellen in den PlayerSettings sollte nach dem Neustart von Unity die Projekt Datei automatisch auf 4.6 umgestellt sein. Eventuelle noch mal auf 3.5 und dann auf 4.6 Stellen. In deinem Beispiel benutzt du eine Closure, also schwirrt die Variable tatsächlich irgendwo im Heap rum (Indirekt) Der Compiler erzeugt bei einer Closure im Hintergrund eine Klasse, wo er die Variable abspeichert. Lokale Variablen werden bekanntlich beim Verlassen des Gültigkeitsbereichs gelöscht, Damit sie aber in einer Closure zur Verfügung stehen müssen die ja irgendwo gespeichert bleiben. Hier schön erklärt inklusive was sich mit C# 7 in dieser Hinsicht besser wird. https://www.youtube.com/watch?v=-3274JsdtOQ (ab ca. 28:00) Das ist allerdings ein generelles Problem. Hier das Beispiel mit Task ohne Closure: var results = await Task.Run(() => { var innerResults = new int[1000]; for (var i = 0; i < innerResults.Length; i++) { innerResults[i] = Random.Range(0, 1000); Thread.Sleep(10); } return innerResults; }); DoSomethingWith(results);
  13. Unity 2017 und .NET 4.6

    Ich bin ehrlich gesagt kein Freund der Coroutine, die einem Asynchronität vorgaukeln, wo keine ist. Die einzige Sinnhafte Anwendung von Coroutinen, die mir spontan einfällt ist so wie du sie Verwendest hast, um auf das beenden eine echten Asynchronen Aufgabe zu warten. Dafür gibt es aber ab .net 4.5 async/await. Dafür hättest du auch Thread direkt Verwenden können. void Start() { new Thread(new ThreadStart(() => Thread.Sleep(1000))).Start(); } Wie gehst du eigentlich vor, wenn du ein Ergebnis erwartest?
  14. Unity 2017 und .NET 4.6

    Du unterschlägst hier den Aufruf der Methode, also 2 Zeilen in zwei Methoden. Dieses Beispiel hattest du in einem anderen Thema gepostet: private void Start() { StartCoroutine(DoSomething()); } private IEnumerator DoSomething() { yield return new CoroutineThread(() => Thread.Sleep(1000)); print("The thread has finished sleeping."); } Mit Task: private void Start() { Task.Run(() => Thread.Sleep(1000)); } oder: private async void Start() { await Task.Run(() => Thread.Sleep(1000)); print("The thread has finished sleeping."); } oder wenn man unbedingt 2 Methoden haben will: private void Start() { DoSomething(); } private async Task DoSomething() { await Task.Run(() => Thread.Sleep(1000)); print("The thread has finished sleeping."); } Alles mit .net Boardmitteln, ich brauche keine zusätzlichen eigene Klassen mehr. Deine TheadPool Variante habe ich jetzt nicht gefunden.
  15. Unity 2017 und .NET 4.6

    Nicht nur einfacher, auch Effizienter wenn man nur Task verwendet. Beispiel JobQueue, auf meinem PC dauert die Ausführung durchschnittlich 2200 Millisekunden: public class CalcLimit2 : JobItem { public string CustomName; public int count = 5; public float Result; protected override void DoWork() { float v = 0; for (int i = 0; i < this.count; i++) { v += Mathf.Pow(0.5f, i); if ((i % 100) == 0 && this.IsAborted) return; } this.Result = v; } public override void OnFinished() { //UnityEngine.Debug.Log("Job: " + CustomName + " has finished with the result: " + Result); } } public class JobQuereEx : MonoBehaviour { private JobQueue<CalcLimit2> queue; Stopwatch watch; bool onWork = false; private void Start() { int maxThread; int o; ThreadPool.GetMaxThreads(out maxThread, out o); JobQueueExample(maxThread); } void Update() { this.queue.Update(); if (this.onWork && this.queue.CountActiveJobs() == 0) { this.watch.Stop(); UnityEngine.Debug.Log($"JobQueue Elapsed Milliseconds : {this.watch.ElapsedMilliseconds}"); this.onWork = false; } } void OnDisable() { this.queue.ShutdownQueue(); } private void JobQueueExample(int maxThread) { UnityEngine.Debug.Log($"Start JobQueue with {maxThread} Threads"); this.watch = Stopwatch.StartNew(); this.queue = new JobQueue<CalcLimit2>(maxThread); for (int i = 0; i < maxThread; i++) { this.queue.AddJob(new CalcLimit2 { count = 50000, CustomName = "over 9001" }); } this.onWork = true; } } Gleiche Logik mit Task, auf meinem PC durchschnittlich 850 Millisekunden: public class TaskTest : MonoBehaviour { private void Start() { int maxThread; int o; ThreadPool.GetMaxThreads(out maxThread, out o); TaskExample(maxThread); } private void TaskExample(int maxThread) { var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; UnityEngine.Debug.Log($"Start {maxThread} tasks"); var watch = Stopwatch.StartNew(); Task[] tasks = new Task[maxThread]; for (int i = 0; i < tasks.Length; i++) { tasks[i] = Task.Run(() => CalcLimit2(50000, token), token); } Task.WaitAll(tasks); watch.Stop(); UnityEngine.Debug.Log($"Task Elapsed Milliseconds : {watch.ElapsedMilliseconds}"); } private float CalcLimit2(int count, CancellationToken token) { float v = 0; for (int i = 0; i < count; i++) { v += Mathf.Pow(0.5f, i); if ((i % 100) == 0 && token.IsCancellationRequested) return default(float); } return v; } }
×