Just4Fun Performance-Steigerung

Blackhawk50000

Erfahrenes Mitglied
Hallo liebe Gemeinde,

Ich bin nun schon seit Jahren, genauer gesagt, seit dem Windows Vista auf den Markt gewürgt wurde, auf der Suche nach einer Möglichkeit, die Textausgabe der Console an Performance zu emulieren.
Warum versuche ich das? Nun, Seit Vista ist der ConsolenVollbildModus nicht mehr vorhanden. Aber die Geschwindigkeit der Textausgabe war und ist legendär.

Testet es selbst: Erstellt ein einfaches Consolenprojekt und fügt ganz einfach diese Zeilen ein:

for (int i = 0; ; i++ )
{
Console.Write(" TEST " + i);
}

Ihr werden sehen, mit welch rasender Geschwindigkeit der Text über das Bild fegt.

Und ich suche wie nun schon gesagt seit Ewigkeiten nach einer Möglichkeit am bessten GENAU DAS, und GENAU SO im vollbildmodus unter Windows 7 in Vollbild darstellen zu lassen...

Hat hier irgendjemand eine Idee?

Wäre echt lieb. Danke
 
Ich musste das gleich mal ausprobieren. In meinem Test ist die selbstgebaute Console halb so schnell wie die .Net-Console.
Falls du es wirklich drauf anlegst, dann ließe sich die Geschwindigkeit bestimmt steigern, wenn du DirectX zum Zeichnen verwendest (anstatt GDI+ wie ich hier).
Hier der Code (neue Konsolenanwendung erstellen und Verweise auf System.Drawing und System.Windows.Forms hinzufügen):
Datei "Program.cs":
C#:
using System;
using System.Windows.Forms;

namespace WhateverProgram
{
    static class Program
    {
        public const int LoopMaximum = 20000;

        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            System.Diagnostics.Stopwatch Stoppuhr = System.Diagnostics.Stopwatch.StartNew();
            for (int i = 0; i < LoopMaximum; i++)
            {
                Console.WriteLine("Loop "+i.ToString());
            }
            Stoppuhr.Stop();
            Console.WriteLine("Console: Verstrichene Ticks: " + Stoppuhr.ElapsedTicks.ToString());
            Console.WriteLine("Console: Verstrichene Millisekunden: " + Stoppuhr.ElapsedMilliseconds.ToString());
            Console.WriteLine("Now starting Window");
            Application.Run(new Form1());
        }
    }
}
Und Datei "Form1.cs":
C#:
using System;
using System.Drawing;
using System.Windows.Forms;

namespace WhateverProgram
{
    public partial class Form1 : Form
    {
        private int NextAppendTextIndex;
        private String[] buffer;
        private Brush Pinsel;
        private System.Threading.Thread CreateTextThread;
        private delegate void AppendTextDelegate(String Text);
        private AppendTextDelegate AppendTextDelegateInstance;

        public Form1()
        {
            InitializeComponent();
            // Flackern durch GDI+-Ausgabe verhindern
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
            AppendTextDelegateInstance = new AppendTextDelegate(this.AppendText);
            Pinsel = new SolidBrush(this.ForeColor);
            UpdateZeilenanzahl();
            for (int i = 0; i < buffer.Length + 2; i++)
            {
                this.AppendText("Starttext " + i.ToString());
            }
            CreateTextThread = new System.Threading.Thread(new System.Threading.ThreadStart(this.AppendSomeTextLoop));
        }

        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            CreateTextThread.Start();
        }

        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            CreateTextThread.Abort();
            base.OnFormClosed(e);
        }


        private void AppendSomeTextLoop()
        {
            try
            {
                System.Diagnostics.Stopwatch Stoppuhr = System.Diagnostics.Stopwatch.StartNew();
                for (int i = 0; i < Program.LoopMaximum; i++)
                {
                    this.AppendText("Loop " + i.ToString());
                }
                Stoppuhr.Stop();
                String temp = "Verstrichene Ticks: " + Stoppuhr.ElapsedTicks;
                this.AppendText(temp);
                Console.WriteLine("WinForms: " + temp);
                temp = "Verstrichene Millisekunden: " + Stoppuhr.ElapsedMilliseconds;
                this.AppendText(temp);
                Console.WriteLine("WinForms: " + temp);
            }
            catch (Exception)
            {
                // nichts tun. Thread wurde wahrscheinlich abgebrochen
            }
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            UpdateZeilenanzahl();
        }

        private void UpdateZeilenanzahl()
        {
            int Zeilenanzahl = (this.ClientSize.Height / this.Font.Height);
            buffer = new String[Zeilenanzahl];  // Der alte Buffer sollte natürlich eigentlich nicht gelöscht werden. Aber als Beispiel reicht das hier.
            NextAppendTextIndex = 0;
            for (int i = 0; i < Zeilenanzahl; i++)
            {
                this.AppendText("Text nach Resize " + i.ToString());
            }
        }

        private void AppendText(String Text)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(AppendTextDelegateInstance, Text);
            }
            else
            {
                buffer[NextAppendTextIndex] = Text;
                NextAppendTextIndex++;
                if (NextAppendTextIndex >= buffer.Length) NextAppendTextIndex = 0;
                this.Invalidate(false);
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            int length = buffer.Length;
            Graphics g = e.Graphics;
            for (int i = 0; i < length; i++)
            {
                int TextIndex = (NextAppendTextIndex + i) % length;
                g.DrawString(buffer[TextIndex], this.Font, Pinsel, 0f, (float)i * this.FontHeight);
            }
        }
    }
}
Da ich den Code nicht kommentiert habe... falls es Fragen gibt, einfach melden ;)
 
Wow.... eigentlich garnicht so übel...ich habs jetzt mal zum laufen gebracht und irgendwie kommts mir schnell vor..
Der vergleich den du eingebaut hast ist genial. Dabei habe ich gemerkt, das es sehr sehr unterschiedlich ist wie schnell das ganze zeug ist. Mal ist es fast gleich schnell ,mal ist es halb so schnell und mal ist es 10 mal langsamer.

geht es auch, das im windows fenster (nicht console) der text nicht in ner neuen zeile geschrieben wird, sondern hinten dran?

ich meine schon mal entfernt dran gedacht zu haben DirectX zu benutzen weil in spielen hat viel mehr viel schneller angezeigt werden muss... (zum beispiel)

allerdings entzieht sich mir da komplett das wissen wie man da überhaupt ran geht.

da das hier ja ein Just4Fun beitrag ist, kannst du mir ja mal, wenn du dich damit auskennst, ein "As Short As Possible" (ASAP) Tutorial geben wie man mit DirectX einen einfachen (cool wäre grüner) Text im Vollbildmodus auf den Bildschirm bringt.
 
Zuletzt bearbeitet:
Okay, habe mal beispiel zwei getestet und angepasst.. Keine Chance. nicht mal im ansatz so schnell.

jetzt schau ich mir mal das erste beispiel mit XNA an... mal sehen wie schnell das ist. wobei ich mir ehr sorgen mache, ob ichs verstehe =)
 
da das hier ja ein Just4Fun beitrag ist, kannst du mir ja mal, wenn du dich damit auskennst, ein "As Short As Possible" (ASAP) Tutorial geben wie man mit DirectX einen einfachen (cool wäre grüner) Text im Vollbildmodus auf den Bildschirm bringt.
Leider kenne ich mich weder mit XNA noch mit DirectX aus. Das habe ich noch nie verwendet :p
 
Hallo,

ich bin mir nicht sicher, dass jede Zeile der command shell einzeln ausgegeben wird. Ich denke eher, dass diese eine Refreshrate pro Sekunde hat.
Ich hab mal Shakies Beispiel um einen Timer der das Invalidate() macht erweitert. Läuft jetzt ähnlich schnell wie die CMD.

C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace ConsoleApplication1
{
    public partial class Form1 : System.Windows.Forms.Form
    {
        private int NextAppendTextIndex;
        private String[] buffer;
        private Brush Pinsel;
        private System.Threading.Thread CreateTextThread;
        private delegate void AppendTextDelegate(String Text);
        private AppendTextDelegate AppendTextDelegateInstance;
        Timer t = new Timer();
        System.Diagnostics.Stopwatch fps = new System.Diagnostics.Stopwatch(); 


        public Form1()
        {
           // InitializeComponent();

            this.Bounds = new Rectangle(this.Bounds.X, this.Bounds.Y, 400, 900);

            // Flackern durch GDI+-Ausgabe verhindern
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
            AppendTextDelegateInstance = new AppendTextDelegate(this.AppendText);
            Pinsel = new SolidBrush(this.ForeColor);
            UpdateZeilenanzahl();
            for (int i = 0; i < buffer.Length + 2; i++)
            {
                this.AppendText("Starttext " + i.ToString());
            }
            CreateTextThread = new System.Threading.Thread(new System.Threading.ThreadStart(this.AppendSomeTextLoop));
            t.Tick += new EventHandler(t_Tick);
            t.Interval = 10;
            fps.Start();
            t.Start();
        }

        

        void t_Tick(object sender, EventArgs e)
        {
            this.Invalidate();
            long ms = fps.ElapsedMilliseconds;
            fps.Restart();
            this.Text = String.Format( "fps: {0}",(1000 / ms).ToString());
        }

        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            CreateTextThread.Start();
        }

        protected override void OnFormClosed(FormClosedEventArgs e)
        {
            CreateTextThread.Abort();
            base.OnFormClosed(e);
        }


        private void AppendSomeTextLoop()
        {
            try
            {
                System.Diagnostics.Stopwatch Stoppuhr = System.Diagnostics.Stopwatch.StartNew();
                for (int i = 0; i < Program.LoopMaximum; i++)
                {
                    this.AppendText("Loop " + i.ToString());
                }
                Stoppuhr.Stop();
                String temp = "Verstrichene Ticks: " + Stoppuhr.ElapsedTicks;
                this.AppendText(temp);
                Console.WriteLine("WinForms: " + temp);
                temp = "Verstrichene Millisekunden: " + Stoppuhr.ElapsedMilliseconds;
                this.AppendText(temp);
                Console.WriteLine("WinForms: " + temp);
            }
            catch (Exception)
            {
                // nichts tun. Thread wurde wahrscheinlich abgebrochen
            }
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            UpdateZeilenanzahl();
        }

        private void UpdateZeilenanzahl()
        {
            int Zeilenanzahl = (this.ClientSize.Height / this.Font.Height);
            buffer = new String[Zeilenanzahl];  // Der alte Buffer sollte natürlich eigentlich nicht gelöscht werden. Aber als Beispiel reicht das hier.
            NextAppendTextIndex = 0;
            for (int i = 0; i < Zeilenanzahl; i++)
            {
                this.AppendText("Text nach Resize " + i.ToString());
            }
        }

        private void AppendText(String Text)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(AppendTextDelegateInstance, Text);
            }
            else
            {
                buffer[NextAppendTextIndex] = Text;
                NextAppendTextIndex++;
                if (NextAppendTextIndex >= buffer.Length) NextAppendTextIndex = 0;
              //  this.Invalidate(false);
            }
        }


        int length;
        Graphics g;
        int textIndex  ;

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            length = buffer.Length;
            g = e.Graphics;
            textIndex = 0;
            for (int i = 0; i < length; i++)
            {
                textIndex = (NextAppendTextIndex + i) % length;
                g.DrawString(buffer[textIndex], this.Font, Pinsel, 0f, (float)i * this.FontHeight);
            }
        }
    }
}
 
Zuletzt bearbeitet:
Yup, kann ich bestätigen! Mit Refresh-Timer laufen beide Varianten gleich schnell. Gute Idee!
 

Neue Beiträge

Zurück