Forum Discussion

Mousefluff's avatar
Mousefluff
Iron Contributor
Aug 22, 2024

Simple Guide On Effective Use Of Parallel Programming For C# In A Managed Code Environment:

Parallel programming in C# uses a variation of Managed Threading, that relies on PLINQ, Expression Trees, The Barrier Class, Thread Class, BackgroundWorker Class, SpinWait Struct, SpinLock Struct, and Thread-Tracking Mode for SpinLock. The reason is that it's faster to use the environment to determine how many cores / threads are available, as to not starve the device of resources, which at that point, you have to use the BackgroundWorker Class to manage each task you've created. Often in this scenario, you can end up with a deadlock condition, because you have more than one task trying to access a shared resource. It's much easier and faster to split up each task, ONLY using byte arrays, assigning each task individual byte arrays to sort / parse, encrypted or not, with the Stream class, or a sub variation of that Class, and then when each task finishes, they all finish at different times, but the shared resource is divided up into portions, so that they will only be able to fill one area of that array. The reason why Barrier is used in this situation, is it forces each one to wait until all the tasks are finished, or until they all ARRIVE at the same place, which solves one timing issue, yet it might create another where there's a bit of a timing mismatch if your estimates are wrong, you overshoot or undershoot I mean. At the very end, you can use a separate process to just COPY from each individual array, without a deadlock scenario occurring. The only issue, is you have to estimate how many threads are available ahead of time, and you can't use every single thread, yet you're going to have to divide a single resource between all those threads. Beforehand, you have to verify if it's a waste of time to use more than one thread. The reason why I say this, is that a lot of people use reference types, not knowing they are immutable, and they take a huge / massive performance hit because of this. Often you have to convert strings into byte arrays, or use a pre-initialized character array at the start of the program, which contains the Unicode values that you want to recast individually as strings, and then use a byte array as an INDEX or a placeholder, of a Unicode character array. If you’re not encrypting the byte arrays, or using them for text parsing, which byte arrays tend to be best in high throughput scenarios, than integer arrays will suffice. The index can be scrambled based on how you want to represent that one string, though it's smarter to only cast a new reference type when you want to display text on the screen. If you spend too much time manually parsing using built-in libraries, it's REALLY SLOW. A byte array is better to use than an integer array in this sort of situation. You might have to create separate indexes with a byte array representing a set of binary flags, to determine whether each one is a letter, number, symbol, etc, or how you want to classify each one based on the code chart that you're using. You would be better off in that situation to just use right shift / left shift / XOR, etc, to set the flags. Then you have something which is also very fast, and almost equivalent to a Barrel Shifter, given C# does not allow you to use pointers, as it's managed code / a managed environment. All the Boolean Logical Operators with Compound Assignment rely on pre-initialized Cast Expressions of Integer Literals, Bitwise and Shift Operators, combined with Lambda Expressions, and Operator Overloading. The purpose of the Shift Operators is to mask / pad the bits of one byte value with zeroes, so that your Cast Expression Of An Integer Literal, which serves at the mask, always gives you a fixed / deterministic result, when used in conjunction with Boolean Logical Operators, especially if the value is smaller than 8-bits / a single byte, or you're dealing with a larger array has to represent a flag "register" with a size of ( 2 ^ 8 ) 256 bits, which is basically a Double-Word:

"Microsoft Learn - Boolean logical operators - AND, OR, NOT, XOR - Compound assignment" -> "https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/boolean-logical-operators#compound-assignment"
"Microsoft Learn - Bitwise and shift operators (C# reference)" -> "https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators"
"Microsoft Learn - Operator overloading - predefined unary, arithmetic, equality and comparison operators" -> "https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/operator-overloading"
"Microsoft Learn - Lambda expressions and anonymous functions" -> "https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/lambda-expressions"
"Microsoft Learn - Integral numeric types (C# reference) - Integer literals" -> "https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types#integer-literals"
"Microsoft Learn - Type-testing operators and cast expressions - is, as, typeof and casts - Cast expression" -> "https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/type-testing-and-cast#cast-expression"

"Microsoft Learn - Deserialization risks in use of BinaryFormatter and related types" -> "https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide"
"Microsoft Learn - BinaryReader Class" -> "https://learn.microsoft.com/en-us/dotnet/api/system.io.binaryreader?view=netframework-4.0"
"Microsoft Learn - Stream Class" -> "https://learn.microsoft.com/en-us/dotnet/api/system.io.stream?view=netframework-4.0"
"Microsoft Learn - StreamWriter Class" -> "https://learn.microsoft.com/en-us/dotnet/api/system.io.streamwriter?view=netframework-4.0"
"Microsoft Learn - StreamReader Class" -> "https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader?view=netframework-4.0"
"Microsoft Learn - File and Stream I/O" -> "https://learn.microsoft.com/en-us/dotnet/standard/io/"
"Microsoft Learn - Pipe Functions" -> "https://learn.microsoft.com/en-us/windows/win32/ipc/pipe-functions"
"Microsoft Learn - System.IO.Pipes Namespace" -> "https://learn.microsoft.com/en-us/dotnet/api/system.io.pipes?view=netframework-4.0"
"Microsoft Learn - Custom Partitioners for PLINQ and TPL" -> "https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/custom-partitioners-for-plinq-and-tpl"
"Microsoft Learn - Expression Trees" -> "https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/expression-trees/"
"Microsoft Learn - Build expression trees" -> "https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/expression-trees/expression-trees-building"
"Microsoft Learn - Translate expression trees" -> "https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/expression-trees/expression-trees-translating"
"Microsoft Learn - Execute expression trees" -> "https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/expression-trees/expression-trees-execution"
"Microsoft Learn - System.Windows.Threading Namespace" -> "https://learn.microsoft.com/en-us/dotnet/api/system.windows.threading?view=netframework-4.0"
"Microsoft Learn - System.Threading Namespace" -> "https://learn.microsoft.com/en-us/dotnet/api/system.threading?view=netframework-4.0"
"Microsoft Learn - System.Threading.Channels Namespace" -> "https://learn.microsoft.com/en-us/dotnet/api/system.threading.channels?view=netcore-3.0"
"Microsoft Learn - System.Threading.Tasks Namespace" -> "https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks?view=netframework-4.0"
"Microsoft Learn - Timer Class (System.Timers)" -> "https://learn.microsoft.com/en-us/dotnet/api/system.timers?view=netframework-4.0"
"Microsoft Learn - Timer Class (System.Threading)" -> "https://learn.microsoft.com/en-us/dotnet/api/system.threading.timer?view=netframework-4.0"
"Microsoft Learn - DispatcherTimer Class (System.Windows.Threading)" -> "https://learn.microsoft.com/en-us/dotnet/api/system.windows.threading.dispatchertimer?view=netframework-4.0"
"Microsoft Learn - Dispatcher Class (System.Windows.Threading)" -> "https://learn.microsoft.com/en-us/dotnet/api/system.windows.threading.dispatcher?view=netframework-4.0"
"Microsoft Learn - Threads and threading" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/threads-and-threading"
"Microsoft Learn - Using threads and threading" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/using-threads-and-threading"
"Microsoft Learn - Introduction to PLINQ" -> "https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/introduction-to-plinq"
"Microsoft Learn - Task Parallel Library (TPL)" -> "https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-parallel-library-tpl"
"Microsoft Learn - Lambda Expressions in PLINQ and TPL" -> "https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/lambda-expressions-in-plinq-and-tpl"
"Microsoft Learn - Multithreading in Windows Forms Controls" -> "https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/multithreading-in-windows-forms-controls"
"Microsoft Learn - Managed threading best practices" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/managed-threading-best-practices"
"Microsoft Learn - Parallel programming in .NET: A guide to the documentation" -> "https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/"
"Microsoft Learn - Thread Class" -> "https://learn.microsoft.com/en-us/dotnet/api/system.threading.thread"
"Microsoft Learn - BackgroundWorker Class" -> "https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker"
"Microsoft Learn - Synchronizing data for multithreading" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/synchronizing-data-for-multithreading"
"Microsoft Learn - Overview of synchronization primitives" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives"
"Microsoft Learn - Environment.ProcessorCount Property" -> "https://learn.microsoft.com/en-us/dotnet/api/system.environment.processorcount"
"Microsoft Learn - Managed threading best practices - Number of Processors" -> "https://learn.microsoft.com/en-us/previous-versions/dotnet/netframework-1.1/1c9txz50(v=vs.71)#number-of-processors"
"Microsoft Learn - lock statement - ensure exclusive access to a shared resource" -> "https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/lock"
"Microsoft Learn - Reliability Best Practices" -> "https://learn.microsoft.com/en-us/dotnet/framework/performance/reliability-best-practices"
"Microsoft Learn - BackgroundWorker Component Overview" -> "https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/backgroundworker-component-overview"
"Microsoft Learn - How to: Run an Operation in the Background" -> "https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-run-an-operation-in-the-background"
"Microsoft Learn - Thread-safe collections" -> "https://learn.microsoft.com/en-us/dotnet/standard/collections/thread-safe/"
"Microsoft Learn - Threading objects and features" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/threading-objects-and-features"
"Microsoft Learn - Barrier" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/barrier"
"Microsoft Learn - Barrier Class" -> "https://learn.microsoft.com/en-us/dotnet/api/system.threading.barrier?view=netframework-4.0"
"Microsoft Learn - SpinWait" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/spinwait"
"Microsoft Learn - SpinWait Struct" -> "https://learn.microsoft.com/en-us/dotnet/api/system.threading.spinwait?view=netframework-4.0"
"Microsoft Learn - SpinLock" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/spinlock"
"Microsoft Learn - SpinLock Struct" -> "https://learn.microsoft.com/en-us/dotnet/api/system.threading.spinlock?view=netframework-4.0"
"Microsoft Learn - How to: use SpinLock for low-level synchronization" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/how-to-use-spinlock-for-low-level-synchronization"
"Microsoft Learn - How to: Enable Thread-Tracking Mode in SpinLock" -> "https://learn.microsoft.com/en-us/dotnet/standard/threading/how-to-enable-thread-tracking-mode-in-spinlock"
"Microsoft Learn - Chaining tasks using continuation tasks" -> "https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/chaining-tasks-by-using-continuation-tasks"
"Microsoft Learn - Interlocked Class" -> "https://learn.microsoft.com/en-us/dotnet/api/system.threading.interlocked?view=netframework-4.0"
"Microsoft Learn - TaskFactory Class" -> "https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.taskfactory?view=netframework-4.0"

2 Replies

  • Mousefluff's avatar
    Mousefluff
    Iron Contributor

    Example script that utilizes concepts from the above post, and runs on a single core in a managed code environment, which emphasizes type safety:

     

    Use Notepad to create this file on your desktop or another folder: https://sourceforge.net/projects/openscriptlab/files/Batch_PowerShell/Generic_Cryptographically_Secure_Password_Generator.bat/download

     

    NOTE: This is an example batch file, that uses PowerShell 5.1 with C# style syntax and .NET APIs, without using pointers, or direct / indirect addressing, yet still having low level access to each byte value, to create a virtual flag register, by utilizing the equivalent of a unary cast operator, right shift, left shift, and logical exclusive or, as a byte mask. By itself, this one of the most most efficient ways to sort reference types, only using unsigned integers ( byte values, ) and either a hash table or a byte array, used as an index to cross translate when it comes time to display the text on the screen, with the reference types stored in another array, along with the index being in the form of a byte array, that points to said array of reference types, which in contrast, are represented as a series of Unicode character values ( UTF-16. ) This is similar to how you're supposed to handle reference types, without recasting a reference type over and over again, which is very inefficient, or only recasting WHEN you need to display it on the screen. The syntax differs slightly from the C# version, given it's also an interpreted language that runs on the equivalent of a virtual machine. If you were to use this in C# it would be very fast, and you would not have to worry as much about type safety in a manged code environment. The whole purpose of this is achieve the same outcome without pointers, in a managed code environment, and not lose the performance gains associated with using C Language.

Resources