Procesos y manejo (tuberías) -- # campo con performance camp codereview Relacionados El problema

Processes and Handling (Piping)


4
vote

problema

Español

Básicamente tengo 3 procesos que me encierro.

El primer proceso está codificando el video. En realidad, son 2 procesos, pero están conectados, por lo que no necesito preocuparme por cómo maneja el otro.

El segundo y tercero están conectados por mí, sin embargo. Uno lee y las otras escribas, por lo que tengo que alimentar manualmente el stdin / out.

y aquí soy un poco escéptico. Si lo hago, la forma "normal", que básicamente está teniendo un hilo de devolución de llamada que obtiene los datos, y luego lo escribe inmediatamente. El rendimiento se bloqueará a un hilo.

con eso me refiero a que ambos procesos compartirán el hilo, por lo que ambos se funcionarán en un 50%.

Para resolver esto, estoy permitiendo que la devolución de llamada se ejecute y simplemente alimente los datos a un 9988776665544330 , que luego lee el otro proceso (que se está realizando en otro hilo). Sin embargo, no estoy seguro de que esta es una forma verdaderamente eficiente de hacer cosas, pero funciona.

El último es simplemente un proceso que lleva 2 archivos y los pone en un contenedor.

3 de estos procesos se ejecutan en la misma variable cmdProcesses . La excepción es la que es una causa separada de la tubería.

Aquí es la forma en que se ejecuta la parte principal de este código:

  private void Encoding(string[] GetFile) {     using(AutoResetEvent OpusCheck = new AutoResetEvent(false))     using (QU = new BlockingCollection<byte[]>())     using (OpusEncoder = new Process())     for (int i = 0; i < GetFile.Length; i++)     {         try         {             ReadBuffer = new byte[4096];             string filename = Path.GetDirectoryName(GetFile[i]) + "\" + Path.GetFileNameWithoutExtension(GetFile[i]);              using (cmdCommands = new Process())             {                  cmdCommands.StartInfo.UseShellExecute = false;                 cmdCommands.StartInfo.CreateNoWindow = false;                 cmdCommands.StartInfo.FileName = SC.GetAVS4x264Path();                 cmdCommands.StartInfo.Arguments = string.Format(""{0}" --x264-binary "{1}" --colormatrix=bt709 {2} --output="{3}" -", filename + ".avs", SC.Getx264Path(), SC.Getx264Settings(true), filename + ".mkv");                 cmdCommands.Start();                 cmdCommands.WaitForExit();                  if (EncodingStopped)                     break;                  cmdCommands.StartInfo.UseShellExecute = false;                 cmdCommands.StartInfo.CreateNoWindow = true;                 cmdCommands.StartInfo.RedirectStandardOutput = true;                 cmdCommands.StartInfo.FileName = SC.GetAVS2PipeModPath();                 cmdCommands.StartInfo.Arguments = string.Format("{0} "{1}" -wav", SC.GetAVS2PipeModPath(), filename + ".avs");                 cmdCommands.Start();                  Thread OpusThread = new Thread(() => OpusEncode(filename, OpusCheck));                 OpusThread.Start();                  cmdCommands.StandardOutput.BaseStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, PipeWrite, null);                 cmdCommands.WaitForExit();                 OpusCheck.WaitOne();                 if (EncodingStopped)                     break;                  cmdCommands = new Process();                 cmdCommands.StartInfo.UseShellExecute = false;                 cmdCommands.StartInfo.RedirectStandardError = true;                 cmdCommands.StartInfo.FileName = SC.GetMKVMergePath();                 cmdCommands.StartInfo.Arguments = (" -o "" + filename + "-muxed.mkv" "" + filename + ".mkv" " + """ + filename + ".opus"");                 cmdCommands.Start();                 cmdCommands.WaitForExit();                    File.Delete(filename + ".mkv");                 File.Delete(filename + ".opus");             }         }         catch (Exception e)         {             MessageBox.Show(e.Message);          }     }      StopEncoding.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new System.Action(() => { StopEncoding.IsEnabled = false; Encode.IsEnabled = true; })); }   

la tubería (devolución de llamada)

      private void PipeWrite(IAsyncResult ar)     {         int read = cmdCommands.StandardOutput.BaseStream.EndRead(ar);         if (read != 0)         {             QU.Add((byte[])ReadBuffer.Clone());             cmdCommands.StandardOutput.BaseStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, PipeWrite, null);             cmdCommands.StandardOutput.BaseStream.Flush();         }         else         {             ReadBuffer = new byte[0];             QU.Add(ReadBuffer);             cmdCommands.StandardOutput.BaseStream.Close();         }     }   

El hilo de proceso separado

  private void OpusEncode(string filename,AutoResetEvent OpusCheck) {         OpusEncoder.StartInfo.UseShellExecute = false;         OpusEncoder.StartInfo.RedirectStandardInput = true;         OpusEncoder.StartInfo.FileName = SC.GetOpusEncPath();         OpusEncoder.StartInfo.Arguments = string.Format("{0} - "{1}"", SC.GetOpusSettings(true), filename + ".opus");         OpusEncoder.Start();         byte[] temp;         while (QU.TryTake(out temp, Timeout.Infinite))         {             if (temp.Length == 0)                 break;             OpusEncoder.StandardInput.BaseStream.Write(temp, 0, temp.Length);          }             OpusEncoder.StandardInput.Close();             OpusEncoder.WaitForExit();         OpusCheck.Set();                }   

Quiero saber si este enfoque es el camino a seguir, o si estoy manejando este mal. Y también si puede ser más eficiente, lo que probablemente vaya en la mano con que sea correcto / incorrecto.

Original en ingles

I basically have 3 processes which I loop through.

The first process is encoding Video. It's actually 2 processes but they are connected, so I don't need to worry about how it handles the other one.

The second and third are connected by me, however. One reads and the other writes, so I have to manually feed the stdin/out.

And here I am a bit skeptical. If I do it the "normal" way, which basically is having one callback thread which gets the data, and then writes it immediately. The performance will be locked to one thread.

With that I mean that both processes will share Thread, so both will pretty much run at 50%.

To solve this I am letting the Callback run and just feed the Data to a BlockingCollection, which the other process then reads from (that's being done on another Thread). I am not, however, sure this is truly an efficient way to do things, but it works.

The last is simply a process which takes 2 files and puts them into a container.

3 of these processes are run on the same variable cmdProcesses. The exception is the one that is a separate cause of the piping.

Here is how the main part of this code runs:

private void Encoding(string[] GetFile) {     using(AutoResetEvent OpusCheck = new AutoResetEvent(false))     using (QU = new BlockingCollection<byte[]>())     using (OpusEncoder = new Process())     for (int i = 0; i < GetFile.Length; i++)     {         try         {             ReadBuffer = new byte[4096];             string filename = Path.GetDirectoryName(GetFile[i]) + "\\" + Path.GetFileNameWithoutExtension(GetFile[i]);              using (cmdCommands = new Process())             {                  cmdCommands.StartInfo.UseShellExecute = false;                 cmdCommands.StartInfo.CreateNoWindow = false;                 cmdCommands.StartInfo.FileName = SC.GetAVS4x264Path();                 cmdCommands.StartInfo.Arguments = string.Format("\"{0}\" --x264-binary \"{1}\" --colormatrix=bt709 {2} --output=\"{3}\" -", filename + ".avs", SC.Getx264Path(), SC.Getx264Settings(true), filename + ".mkv");                 cmdCommands.Start();                 cmdCommands.WaitForExit();                  if (EncodingStopped)                     break;                  cmdCommands.StartInfo.UseShellExecute = false;                 cmdCommands.StartInfo.CreateNoWindow = true;                 cmdCommands.StartInfo.RedirectStandardOutput = true;                 cmdCommands.StartInfo.FileName = SC.GetAVS2PipeModPath();                 cmdCommands.StartInfo.Arguments = string.Format("{0} \"{1}\" -wav", SC.GetAVS2PipeModPath(), filename + ".avs");                 cmdCommands.Start();                  Thread OpusThread = new Thread(() => OpusEncode(filename, OpusCheck));                 OpusThread.Start();                  cmdCommands.StandardOutput.BaseStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, PipeWrite, null);                 cmdCommands.WaitForExit();                 OpusCheck.WaitOne();                 if (EncodingStopped)                     break;                  cmdCommands = new Process();                 cmdCommands.StartInfo.UseShellExecute = false;                 cmdCommands.StartInfo.RedirectStandardError = true;                 cmdCommands.StartInfo.FileName = SC.GetMKVMergePath();                 cmdCommands.StartInfo.Arguments = (" -o \"" + filename + "-muxed.mkv\" \"" + filename + ".mkv\" " + "\"" + filename + ".opus\"");                 cmdCommands.Start();                 cmdCommands.WaitForExit();                    File.Delete(filename + ".mkv");                 File.Delete(filename + ".opus");             }         }         catch (Exception e)         {             MessageBox.Show(e.Message);          }     }      StopEncoding.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new System.Action(() => { StopEncoding.IsEnabled = false; Encode.IsEnabled = true; })); } 

The Pipe (CallBack)

    private void PipeWrite(IAsyncResult ar)     {         int read = cmdCommands.StandardOutput.BaseStream.EndRead(ar);         if (read != 0)         {             QU.Add((byte[])ReadBuffer.Clone());             cmdCommands.StandardOutput.BaseStream.BeginRead(ReadBuffer, 0, ReadBuffer.Length, PipeWrite, null);             cmdCommands.StandardOutput.BaseStream.Flush();         }         else         {             ReadBuffer = new byte[0];             QU.Add(ReadBuffer);             cmdCommands.StandardOutput.BaseStream.Close();         }     } 

The separate Process Thread

private void OpusEncode(string filename,AutoResetEvent OpusCheck) {         OpusEncoder.StartInfo.UseShellExecute = false;         OpusEncoder.StartInfo.RedirectStandardInput = true;         OpusEncoder.StartInfo.FileName = SC.GetOpusEncPath();         OpusEncoder.StartInfo.Arguments = string.Format("{0} - \"{1}\"", SC.GetOpusSettings(true), filename + ".opus");         OpusEncoder.Start();         byte[] temp;         while (QU.TryTake(out temp, Timeout.Infinite))         {             if (temp.Length == 0)                 break;             OpusEncoder.StandardInput.BaseStream.Write(temp, 0, temp.Length);          }             OpusEncoder.StandardInput.Close();             OpusEncoder.WaitForExit();         OpusCheck.Set();                } 

I want to know if this approach is the way to go, or if I am handling this wrong. And also if it can be more efficient, which probably goes in hand with it being right/wrong.

     

Lista de respuestas

5
 
vote

nombramiento. Es dificil

Me enfocaré en eso, así que un programador mejor de lo que puedo enfocar cosas más importantes cuando revisan esto.

  • combnk8 no tiene sentido para el Sr. Mantenedor.
  • combnk9 es un poco repetitivo. let rec combnk k lst = if k = 0 then [[]] else let f = function | [] -> [] | x :: xs -> List.map (fun z -> x :: z) (combnk (k - 1) xs) in if is_empty lst then [] else List.concat (List.map f (tails lst)) 0 sería suficiente. let rec combnk k lst = if k = 0 then [[]] else let f = function | [] -> [] | x :: xs -> List.map (fun z -> x :: z) (combnk (k - 1) xs) in if is_empty lst then [] else List.concat (List.map f (tails lst)) 1 podría ser aún mejor.
  • Los métodos
  • deben tener nombres de verbo-sustantivos. let rec combnk k lst = if k = 0 then [[]] else let f = function | [] -> [] | x :: xs -> List.map (fun z -> x :: z) (combnk (k - 1) xs) in if is_empty lst then [] else List.concat (List.map f (tails lst)) 2 sería mejor como let rec combnk k lst = if k = 0 then [[]] else let f = function | [] -> [] | x :: xs -> List.map (fun z -> x :: z) (combnk (k - 1) xs) in if is_empty lst then [] else List.concat (List.map f (tails lst)) 3 o tal vez let rec combnk k lst = if k = 0 then [[]] else let f = function | [] -> [] | x :: xs -> List.map (fun z -> x :: z) (combnk (k - 1) xs) in if is_empty lst then [] else List.concat (List.map f (tails lst)) 4 .
  • let rec combnk k lst = if k = 0 then [[]] else let f = function | [] -> [] | x :: xs -> List.map (fun z -> x :: z) (combnk (k - 1) xs) in if is_empty lst then [] else List.concat (List.map f (tails lst)) 5 debe ser let rec combnk k lst = if k = 0 then [[]] else let f = function | [] -> [] | x :: xs -> List.map (fun z -> x :: z) (combnk (k - 1) xs) in if is_empty lst then [] else List.concat (List.map f (tails lst)) 6 .

Así que mentí, hay un par de otras cosas que puedo señalar.

  • En esta línea, let rec combnk k lst = if k = 0 then [[]] else let f = function | [] -> [] | x :: xs -> List.map (fun z -> x :: z) (combnk (k - 1) xs) in if is_empty lst then [] else List.concat (List.map f (tails lst)) 7 , 4096 es un Número mágico . Solo se ha usado una vez, por lo que definir una constante puede ser demasiado exagerada, pero un comentario rápido sobre por qué 4096 en lugar de cualquier otro tamaño sería agradable.
  • No creo que estés saliendo de todo este bloque de captura. Realmente debe tomarse el tiempo para pensar en qué tipo de errores probablemente sucedan y qué se debe hacer con ellos si lo hacen.

      let rec combnk k lst =   if k = 0 then     [[]]   else     let f = function       | []      -> []       | x :: xs -> List.map (fun z -> x :: z) (combnk (k - 1) xs)     in       if is_empty lst then         []       else         List.concat (List.map f (tails lst)) 8  
 

Naming. It's hard.

I'll focus on that so a better programmer than I may focus more important things when they review this.

  • QU is completely meaningless to Mr. Maintainer.
  • cmdCommands is a bit repetitive. commands would be sufficient. commandProcess might be even better.
  • Methods should have verb-noun names. PipeWrite would be better as WritePipe or maybe WriteToPipe.
  • ar should be asyncResult.

So I lied, there are a couple of other things I can point out.

  • In this line, ReadBuffer = new byte[4096];, 4096 is a magic number. It's only been used once, so defining a constant for it might be overkill, but a quick comment about why 4096 as opposed to any other size would be nice.
  • I don't think you're getting a whole lot out of this catch block. You should really take the time to think about what kind of errors are likely to happen and what should be done with them if they do.

    catch (Exception e) {     MessageBox.Show(e.Message);  } 
 
 
 
 

Relacionados problema

6  Palindrome más largo en una matriz  ( Longest palindrome in an array ) 
Soy nuevo en la programación, y creo que este código podría mejorarse. ¿Alguna sugerencia? 'done'0 ...

4  Simulación simple de red neural en C ++ (Ronda 2)  ( Simple neural network simulation in c round 2 ) 
Intro Ayer He publicado esta pregunta . Desde entonces, he actualizado mi código para incorporar estas sugerencias . También he eliminado la dependencia d...

8  Simple GCD Utility en Java  ( Simple gcd utility in java ) 
i anteriormente discutido El rendimiento se refiere a diferentes algoritmos GCD. Escribí una simple clase de Java que implementa el algoritmo binario GCD. E...

35  Demasiados bucles en la aplicación de dibujo  ( Too many loops in drawing app ) 
Tengo un método que tiene muchos bucles: #ifndef __RUNES_STRUCTURES_H #define __RUNES_STRUCTURES_H /* Runes structures. */ struct Game { char board[2...

2  IMACROS BOT para realizar refrescos  ( Imacros bot for performing refreshes ) 
Estoy tratando de simplificar este código. Parece que todo funciona como debería; Sin embargo, cuando en el bucle de actualización de Imacro, parece un poco i...

3  Generador de imágenes de Mandelbrot con iteración paralela  ( Mandelbrot image generator with parallel iteration ) 
Actualmente estoy tratando de optimizar esta clase que tengo para la generación fractal. La ecuación está destinada a ser conectable; He usado z => z*z + c ...

1  Compruebe si dos cadenas son permutación entre sí  ( Check if two strings are permutation of each other ) 
private String sort(String word) { char[] content = word.toCharArray(); Arrays.sort(content); return new String(content); } private boolea...

5  Encuentre el próximo número Prime - Control de flujo de los bucles anidados 'para `  ( Find the next prime number flow control of nested for loops ) 
Este código funciona perfectamente, pero me molesta. Tener un bucle etiquetado y anidado Bucle, con un Enumerable<T>.Empty()0 Declaración, y un 9988777665...

1  Integración de oscilador de fase perturbada  ( Perturbed phase oscillator integration ) 
Estoy integrando un sistema de osciladores de fase perturbados. Defino el sistema de ecuación y también la matriz jacobiana. Tengo que remodelar el vector dim...

5  Memoria / Performance of Merge Sort Code  ( Memory performance of merge sort code ) 
Escribí un código de tipo de combinación para un poco de bocadillo nocturno. Lo he puesto trabajando, pero solo estaba mirando a aprender si me faltaba algo e...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos