Cita de: Andres128 en 29 Julio 2017, 05:27 AMejecutar una aplicación que tiene una lista de cuentas de usuario un total de 100 o más, ahora necesito que se ejecuten simultáneamente las 100 y realice sus peticiones y tareas necesarias
Eso no es una buena idea.
Crear tal cantidad como 100 threads provocará una gran demanda de interrupción en la ejecución de cada thread activo por core en la CPU (thread swaping) en el programador de threads del sistema operativo. Dependiendo de lo intensivas que sean esas "peticiones y tareas necesarias" que has mencionado, esto que acabo de mencionar puede ser algo insignificante, o por lo contrario un problema de gravedad a tomarse en cuenta con su debida seriedad.
Por lo general no te conviene en absoluto crear 100 threads, sino más bien crear unos pocos threads (4, 8, 16) y dividir el trabajo entre ellos. De esta manera, 1 thread trabajará sobre más de un elemento distinto (lista de cuenta de usuario), optimizando el trabajo y realizando un uso más eficiente y escalable de los recursos del sistema.
Cita de: Andres128 en 29 Julio 2017, 05:27 AM1. Los hilos o thread que consumen RAM o procesador o las dos ???
Cita de: engel lex en 29 Julio 2017, 05:47 AM1- consumen ambos, los recursos son exigidos para cada hilo individualmente
Hay que tener en cuenta que en los lenguajes de alto nivel (abstractos) como VB.NET y C# ( o más bien dicho .NET Framework ) se optimiza el uso de los threads, pues lo que un programador suele llamar thread o hilo, es en realidad un wrapper de alto nivel que abstrae cierta funcionalidad de un thread del sistema. A raíz de esto hay toda una extensa serie de implementaciones abstractas en la librería de clases de .NET Framework para cubrir, administrar y perfeccionar muchos aspectos relacionados con el uso/rendimiento de los threads, empezando por la implementación de un gestionador de threads (un Thread Pool y un Task Scheduler). El compilador de .NET genera ciertas optimizaciones automáticas en las instrucciones designadas al uso de threads, y los runtimes junto al programador de threads del S.O. se encargan de procesarlas y hacer el resto.
Respecto al consumo, los threads de una aplicación .NET comparten el mismo espacio de memoria de la aplicación (como es evidente, pues un thread no es un proceso independiente de la aplicación, sino un subset del proceso padre, como un subset de subprocesos), y siempre que puedan éstos compartirán y consumirán los recursos de otros threads del proceso por así decirlo de forma comprensible. Es decir, que no estrictamente siempre se deberá asignar un espacio extra/adicional para administrar los recursos de un nuevo thread (aparte del tamaño de la pila o call stack que eso sí siempre es independiente en cada thread), el GarbageCollector de .NET determinará lo que se puede aprovechar/compartir/reciclar con otro thread, y lo que se debe destruir pro completo. En general, llegar a comprender de forma fidedigna como .NET administra los recursos de memoria asignados en una aplicación es bastante (muy) complejo y confuso, o al menos a mi me resulta así ...en comparación con otros.
Cita de: Andres128 en 29 Julio 2017, 05:27 AM2. Que debo tener en cuenta para seleccionar el VPS que tenga más RAM o un mejor procesador.
Cita de: engel lex en 29 Julio 2017, 05:47 AM2- depende del programa, puede consumir más ram o procesador según el caso
Cita de: Andres128 en 29 Julio 2017, 05:27 AM3. Cuanto creen que necesite de RAM o de procesador para que funcione bien.
Cita de: engel lex en 29 Julio 2017, 05:47 AM3- depende del programa, nadie sabe cuanto consume ni en que sistema corre... de entrada te digo que minimo 1gb de ram para levantar el sistema operativo apropiadamente
Equilibrio, así de simple. Ante la duda, siempre se debe buscar un sistema equilibrado para intentar minimizar las consecuencias de un posible impacto negativo en un factor (CPU) o en el otro (RAM).
Evidentemente en este tipo de escenario multihilo, cuantos más cores y núcleos por core es mejor, y a más RAM será todavía mucho mejor.
También se debe tener en cuenta que tipo de actividad realizarán tus threads y tu aplicación en general (ej. cargar montones de imagenes de alta resolución en un buffer de memoria, o realizar operaciones masivas I/O de escritura o lectura en disco con 1000 archivos de forma simultanea) y como de intensiva será dicha actividad. Eso no podemos saberlo nosotros, tú eres el desarrollador de tu código y por el momento no nos has mostrado NADA del código como para poder orientarte... aunque de todas formas y para ser sincero yo sobre servidores privados de máquinas virtuales apenas sé nada xD.
Cita de: Andres128 en 29 Julio 2017, 05:27 AM4. Se puede dañar un PC si se ejecutar muchísimos hilos unos 500 al tiempo?? que podría pasar???
Cita de: engel lex en 29 Julio 2017, 05:47 AM4- no, no se daña... es como afirmar que una pc se daña al abrir muchos programas al mismo tiempo... si son muchos hilos el sistema operativo los organizará en la tabla de prioridades y se procesarán poco a poco... eso si, poco a poco puede ser 0.01 segundo por proceso por nucleo, así que siendo por ejemplo 8 nucleos, serían unos 0.6 segudos para procesar y cerrar todas las peticiones... si no tienes suficiente potencia el sistema operativo se puedes quedar pegado... en ese caso el vps lo detectará y reiniciará
eso como aclaratoria que depende mucho del sistema
Poco más puedo aportar a la respuesta del copañero @Engel Lex. Como ya te han dicho: no se "daña", y los efectos observables serían exactamente los mismos que si te pones a iniciar 100 procesos distintos al mismo tiempo: una sobrecarga de recursos que tendrá como consecuencia una ralentización del sistema operativo.
Pero cabría destacar que .NET Framework se encarga de buscar el equilibrio perfecto de una aplicación multihilo, determinando de forma automática la cantidad mímina y máxima de threads que pueden estar iniciados en paralelo al mismo tiempo por dicha aplicación. Esto se decide en base a muchos factores, así que un colapso de recursos en el S.O. es más bien improbable al ser teoricamente imposible de suceder por si solo (a menos que modificases de forma arbitraria los límites de threads mínimos y máximos por defecto en la aplicación).
Cita de: Andres128 en 29 Julio 2017, 05:27 AM(use esta librería para ejecutarlas https://github.com/amibar/SmartThreadPool
En mi opinión haces mal al usar una reimplementación de algo que no sea la implementación original de Microsoft, a eso se le llama REINVENTAR LA RUEDA !!. Otra cosa bien distinta sería utilizar una librería que extienda la implementación original para añadirle funcionalidades adicionales, que sinceramente no sé si será el caso, pero por lo poco que he leido en esa página de CodeProject... no parece ser el caso.
Si te fijas bien, verás que ese proyecto lleva en desarrollo desde el año 2003, esto viene a ser el mismo año en el que se utilizaba .NET Framework 1.0, es en ese año cuando nació ese proyecto de CodeProject, y puede que por aquél entonces si que valiese la pena utilizar una implementación de terceros del thread pool de .NET Framework, ya que simplemente era la versión 1.0 del producto y había muchas cosas que pulir, pero hoy en dia francamente ese tipo de librerías las veo algo de lo más innecesario y sin mucha utilidad real (pues quien la use solo la usará por simple desconocimiento de como llevar a cabo la misma tarea de forma "nativa" o guiada mediante el instrumental que provee .NET Framework ), además solo conseguirías obtener justo lo opuesto a ese rendimiento óptimo que estás buscando...
En .NET Framework, la cantidad máxima de threads administrados que puedes mantener activos (por defecto) se determina en base a muchos factores, podemos abreviar todos estos factores como un conjunto de recursos (RAM) y disponibilidad de cores en CPU. El máximo límite de threads que puedes iniciar de forma simultanea se ve incrementado en cada versión de .NET Framework. Te puedo decir que el límite es de 1023 threads administrados en .NET Framework 4.0, y 2047 en .NET Framework 4.6, ojo, eso solamente en aplicaciones de 32 Bits, ya que este número se ve multiplicado por 16 para una aplicación de 64-Bits, siendo así un límite máximo de 32.767 threads en el thread pool de .NET Framework 4.6 x64. Luego existe un límite de threads de operaciones I/O, cuyo valor no varia y siempre son 1.000 (pero también lo puedes modificar). De todas formas estamos hablando de números/límites muy altos que probablemente nunca podrán ser revasados por una aplicación "normal", y de intentarlo posría provocar un desbordmiento (overflow) de la pila o stack de la aplicación.
Otro motivo por el cual me resulta innecesaria esa reimplementación...que te la "venden" como si fuese la única posibilidad de poder asignar un límite mínimo de threads activos de forma simultanea, es que la librería de clases de .NET Framework proporciona miembros para modificar tanto el límite mínimo como el máximo de threads en tu aplicación (aunque por otro lado esto no limita la cantidad mínima ni máxima de threads dedicados en la aplicación): System.Threading.ThreadPool.SetMinThreads() y System.Threading.ThreadPool.SetMaxThreads(), y además provee varias alternativas de hacer "lo mismo", por orden de abstracción de un thread del sistema: la clase Thread, BackgroundWorker, y Task, cada una de ellas enfocada a distintos escenarios (thread dedicado, thread que necesite interactuar con los controles de la UI, thread 'fire and forget', etc).
¿Todavía sigues creyendo que necesitas recurrir a una librería de terceros para poder ejecutar 100 threads de forma simultanea en una aplicación .NET?, no, en absoluto, y como ya digo... solamente conseguirías desaprovechar los beneficios de la implementación de Microsoft, no obtendrías ese rendimiento óptimo que buscas.
En mi opinión, para lo que pretendes hacer creo que te serviría de mucho usar la clase ThreadPool de .NET. Mientras que la creación y ejecución de un thread administrado (clase: System.Threading.Thread) puede resultar una operación expensiva para el S.O., la clase ThreadPool rehusa los threads y amortigua esos costes adicionales de creación y ejecución. Además, dicha clase ayuda a simpliicar el procedimiento de creación, ejecución y detención/aborto de los threads.
Aquí te muestro un ejemplo de como utilizar el Thread Pool de .NET para mantener 100 threads activos (como mínimo) de forma simultanea:
VB.NET
Código (vbnet) [Seleccionar]
Imports System
Imports System.Diagnostics
Imports System.Threading
Public Module Module1
<MTAThread>
Public Sub Main()
Dim minThreadCount As Integer = 100
Dim maxThreadCount As Integer
Dim minIOThreadCount As Integer
Dim maxIOThreadCount As Integer
ThreadPool.GetMinThreads(Nothing, minIOThreadCount)
ThreadPool.GetMaxThreads(maxThreadCount, maxIOThreadCount)
If (maxThreadCount <= minThreadCount) Then
maxThreadCount = (minThreadCount + 1)
End If
ThreadPool.SetMinThreads(minThreadCount, minIOThreadCount)
ThreadPool.SetMaxThreads(maxThreadCount, maxIOThreadCount)
Debug.WriteLine("Minimum Thread Count: {0}", minThreadCount)
Debug.WriteLine("Maximum Thread Count: {0}", maxThreadCount)
For i As Integer = 0 To Byte.MaxValue ' Loop trough 0 to 255
Dim wcb As New WaitCallback(AddressOf MyThreadWork)
ThreadPool.QueueUserWorkItem(wcb, Nothing)
Next i
Thread.Sleep(TimeSpan.FromSeconds(1))
Dim activeThreadCount As Integer = Process.GetCurrentProcess().Threads.Count
Debug.WriteLine("Amount of active threads: {0}", activeThreadCount)
Console.ReadKey()
Environment.Exit(0)
End Sub
' <MethodImpl(MethodImplOptions.Synchronized)>
Private Sub MyThreadWork(ByVal stateInfo As Object)
Thread.Sleep(Timeout.Infinite)
End Sub
End Module
C#
Código (csharp) [Seleccionar]
using System;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApp1 {
class Program {
[MTAThread()]
static void Main(string[] args) {
int minThreadCount = 100;
int maxThreadCount = 0;
int minIOThreadCount = 0;
int maxIOThreadCount = 0;
ThreadPool.GetMinThreads(out int nul, out minIOThreadCount);
ThreadPool.GetMaxThreads(out maxThreadCount, out maxIOThreadCount);
if (maxThreadCount <= minThreadCount) {
maxThreadCount = (minThreadCount + 1);
}
ThreadPool.SetMinThreads(minThreadCount, minIOThreadCount);
ThreadPool.SetMaxThreads(maxThreadCount, maxIOThreadCount);
Debug.WriteLine("Minimum Thread Count: {0}", minThreadCount);
Debug.WriteLine("Maximum Thread Count: {0}", maxThreadCount);
for (int i = 0; i <= byte.MaxValue; i++) { // Loop trough 0 to 255
WaitCallback wcb = new WaitCallback(MyThreadWork);
ThreadPool.QueueUserWorkItem(wcb, null);
}
Thread.Sleep(TimeSpan.FromSeconds(1));
int activeThreadCount = Process.GetCurrentProcess().Threads.Count;
Debug.WriteLine("Amount of active threads: {0}", activeThreadCount);
Console.ReadKey();
Environment.Exit(0);
}
// [MethodImpl(MethodImplOptions.Synchronized)]
static void MyThreadWork(object stateInfo) {
Thread.Sleep(Timeout.Infinite);
}
}
}
También puedes hacer uso del paralelismo para iniciar una determinada cantidad de tareas en paralelo (léase: threads) de forma simultanea (en base a los límites actuales establecidos en el thread pool de .NET):
VB.NET:
Código (vbnet) [Seleccionar]
Imports System
Imports System.Diagnostics
Imports System.Threading
Imports System.Threading.Tasks
Public Module Module1
<MTAThread>
Public Sub Main()
Dim minThreadCount As Integer = 100
Dim maxThreadCount As Integer
Dim minIOThreadCount As Integer
Dim maxIOThreadCount As Integer
ThreadPool.GetMinThreads(Nothing, minIOThreadCount)
ThreadPool.GetMaxThreads(maxThreadCount, maxIOThreadCount)
If (maxThreadCount <= minThreadCount) Then
maxThreadCount = (minThreadCount + 1)
End If
ThreadPool.SetMinThreads(minThreadCount, minIOThreadCount)
ThreadPool.SetMaxThreads(maxThreadCount, maxIOThreadCount)
Dim options As New ParallelOptions() With {
.CancellationToken = CancellationToken.None,
.TaskScheduler = TaskScheduler.Current,
.MaxDegreeOfParallelism = minThreadCount
}
Dim action As New Action(Of Integer, ParallelLoopState)(AddressOf MyThreadWork)
Parallel.For(0, Byte.MaxValue, options, action) ' Loop trough 0 to 255
Console.ReadKey()
Environment.Exit(0)
End Sub
' <MethodImpl(MethodImplOptions.Synchronized)>
Private Sub MyThreadWork(ByVal i As Integer, state As ParallelLoopState)
Static flag As Boolean = False
Dim activeThreadCount As Integer = Process.GetCurrentProcess().Threads.Count
If (activeThreadCount >= 100) AndAlso Not (flag) Then
flag = Not flag
Debug.WriteLine("Amount of active threads: {0}", activeThreadCount)
End If
Thread.Sleep(Timeout.Infinite)
End Sub
End Module
C#
Código (csharp) [Seleccionar]
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1 {
class Program {
[MTAThread()]
static void Main(string[] args) {
int minThreadCount = 100;
int maxThreadCount = 0;
int minIOThreadCount = 0;
int maxIOThreadCount = 0;
ThreadPool.GetMinThreads(out int nul, out minIOThreadCount);
ThreadPool.GetMaxThreads(out maxThreadCount, out maxIOThreadCount);
if (maxThreadCount <= minThreadCount) {
maxThreadCount = (minThreadCount + 1);
}
ThreadPool.SetMinThreads(minThreadCount, minIOThreadCount);
ThreadPool.SetMaxThreads(maxThreadCount, maxIOThreadCount);
Debug.WriteLine("Minimum Thread Count: {0}", minThreadCount);
Debug.WriteLine("Maximum Thread Count: {0}", maxThreadCount);
ParallelOptions options = new ParallelOptions {
CancellationToken = CancellationToken.None,
TaskScheduler = TaskScheduler.Current,
MaxDegreeOfParallelism = minThreadCount
};
Action<int, ParallelLoopState> action = new Action<int, ParallelLoopState>(MyThreadWork);
Parallel.For(0, byte.MaxValue, options, action); // Loop trough 0 to 255
Console.ReadKey();
Environment.Exit(0);
}
static bool flag = false;
// [MethodImpl(MethodImplOptions.Synchronized)]
static void MyThreadWork(int i, ParallelLoopState state) {
int activeThreadCount = Process.GetCurrentProcess().Threads.Count;
if ((activeThreadCount >= 100) && !(flag)) {
flag = !flag;
Debug.WriteLine("Amount of active threads: {0}", activeThreadCount);
}
Thread.Sleep(Timeout.Infinite);
}
}
}
Cita de: Andres128 en 29 Julio 2017, 07:01 AMEstaba pensando en usar Wine para que me salga barato el VPS, realizare varias pruebas para ver como se comporta
Hace muuuchos años que no manejo de forma seria Linux ni Wine; las cosas habrán cambiado mucho desde aquél entonces, se supone que ahora Wine permite instalar .NET Framework y hasta la versión 4.6 nada menos, pero lo cierto es que si tu intención es instalar Wine para poder ejecutar esa aplicación desarrollada en VB.NET... entonces NO NECESITAS USAR WINE. Además de por si la idea de usar un pseudo-emulador para solucionar el problema no debería ser tu primera opción.
...¿Y entonces cómo hacerlo?, pues bien, para empezar te hago saber que tienes a tu disposición una implementación de terceros de .NET Framework multiplataforma llamada Mono, que es capaz de correr aplicaciones desarrolladas para la plataforma .NET Framework en Linux. No es estrictamente necesario desarrollar la aplicación con la IDE Mono Develop (pero si recomendable para no cometer errores de compatibilidad), puedes desarrollar la aplicación de forma normal con Visual Studio, ya que las librerías de los runtimes de Mono solo se necesitan para iniciar la aplicación.
Y mucho mejor que Mono tienes una opción más óptima a tu disposición: desde hace unos pocos años Microsoft provee una implementación reducida y multiplataforma de .NET Framework llamada .NET Core, que al igual que Mono nos permite crear aplicaciones para Linux, con todos los beneficios y optimizaciones que ello implica por la garantia Made In Microsoft .
En fin, espero que algo de todo lo que expliqué te haya podido servir de ayuda.
Saludos!