Friday, June 12, 2020

Digest for comp.programming.threads@googlegroups.com - 12 updates in 12 topics

aminer68@gmail.com: Jun 11 07:13PM -0700

Hello,
 
 
Look at more fun with the following video of a techlead:
 
Programmer Lives Matter
 
https://www.youtube.com/watch?v=ouKgUdqZMds&t=543s
 
 
Thank you,
Amine Moulay Ramdane.
aminer68@gmail.com: Jun 11 06:41PM -0700

Hello,
 
 
Benefits of Asynchronous Programming
 
There are two things which are very important for any application – Usability and Performance. Usability because say a user clicks on a button to save some data. This requires multiple smaller tasks like reading and populating data in internal object, establishing connection with SQL and saving it there etc. As SQL runs on another machine in network and runs under different process, it could be time consuming and may take bit longer. So, if the application runs on a single thread then the screen will be in hanged state till all the tasks completes which is a very bad user experience. That's why nowadays many applications and new frameworks completely rely on asynchronous model.
 
Performance of an application is also very important. It has been seen that while executing a request, around 70-80% of the time gets wasted while waiting for the dependent tasks. So, it can be maximum utilized by asynchronous programming where once the task is passed to another process (say SQL), current thread saves the state and available to take another task. When the SQL task completes any thread which is free, can take it up further.
 
And as you have noticed i have implemented a portable and efficient implementation of a future in Delphi and FreePascal, i think you can
also use it for Asynchronous Programming, look at GetIsReady() method etc. inside the source code to see how to use it for Asynchronous Programming.
 
You can download my portable and efficient implementation of a future in Delphi and FreePascal version 1.06 from:
 
https://sites.google.com/site/scalable68/a-portable-and-efficient-implementation-of-a-future-in-delphi-and-freepascal
 
 
Thank you,
Amine Moulay Ramdane.
aminer68@gmail.com: Jun 11 06:25PM -0700

Hello,
 
 
What about garbage collection?
 
Read what said this serious specialist called Chris Lattner:
 
"One thing that I don't think is debatable is that the heap compaction
behavior of a GC (which is what provides the heap fragmentation win) is
incredibly hostile for cache (because it cycles the entire memory space
of the process) and performance predictability."
 
"Not relying on GC enables Swift to be used in domains that don't want
it - think boot loaders, kernels, real time systems like audio
processing, etc."
 
"GC also has several *huge* disadvantages that are usually glossed over:
while it is true that modern GC's can provide high performance, they can
only do that when they are granted *much* more memory than the process
is actually using. Generally, unless you give the GC 3-4x more memory
than is needed, you'll get thrashing and incredibly poor performance.
Additionally, since the sweep pass touches almost all RAM in the
process, they tend to be very power inefficient (leading to reduced
battery life)."
 
Read more here:
 
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160208/009422.html
 
Here is Chris Lattner's Homepage:
 
http://nondot.org/sabre/
 
And here is Chris Lattner's resume:
 
http://nondot.org/sabre/Resume.html#Tesla
 
 
This why i have invented the following scalable algorithm and its
implementation that makes Delphi and FreePascal more powerful:
 
My invention that is my scalable reference counting with efficient support for weak references version 1.38 is here..
 
Here i am again, i have just updated my scalable reference counting with efficient support for weak references to version 1.37, I have just added a TAMInterfacedPersistent that is a scalable reference counted version, and now i think i have just made it complete and powerful.
 
Because I have just read the following web page:
 
https://www.codeproject.com/Articles/1252175/Fixing-Delphis-Interface-Limitations
 
But i don't agree with the writting of the guy of the above web page, because i think you have to understand the "spirit" of Delphi, here is why:
 
A component is supposed to be owned and destroyed by something else, "typically" a form (and "typically" means in english: in "most" cases, and this is the most important thing to understand). In that scenario, reference count is not used.
 
If you pass a component as an interface reference, it would be very unfortunate if it was destroyed when the method returns.
 
Therefore, reference counting in TComponent has been removed.
 
Also because i have just added TAMInterfacedPersistent to my invention.
 
To use scalable reference counting with Delphi and FreePascal, just replace TInterfacedObject with my TAMInterfacedObject that is the scalable reference counted version, and just replace TInterfacedPersistent with my TAMInterfacedPersistent that is the scalable reference counted version, and you will find both my TAMInterfacedObject and my TAMInterfacedPersistent inside the AMInterfacedObject.pas file, and to know how to use weak references please take a look at the demo that i have included called example.dpr and look inside my zip file at the tutorial about weak references, and to know how to use delegation take a look at the demo that i have included called test_delegation.pas, and take a look inside my zip file at the tutorial about delegation that learns you how to use delegation.
 
I think my Scalable reference counting with efficient support for weak references is stable and fast, and it works on both Windows and Linux, and my scalable reference counting scales on multicore and NUMA systems,
and you will not find it in C++ or Rust, and i don't think you will find it anywhere, and you have to know that this invention of mine solves
the problem of dangling pointers and it solves the problem of memory leaks and my scalable reference counting is "scalable".
 
And please read the readme file inside the zip file that i have just extended to make you understand more.
 
You can download my new scalable reference counting with efficient support for weak references version 1.38 from:
 
https://sites.google.com/site/scalable68/scalable-reference-counting-with-efficient-support-for-weak-references
 
 
Thank you,
Amine Moulay Ramdane.
aminer68@gmail.com: Jun 11 06:11PM -0700

Hello,
 
 
Why Energy Is A Big And Rapidly Growing Problem For Data Centers
 
It's either a breakthrough in our compute engines, or we need to get deadly serious about doubling the number of power plants on the planet.
 
Read more here:
 
https://www.forbes.com/sites/forbestechcouncil/2017/12/15/why-energy-is-a-big-and-rapidly-growing-problem-for-data-centers/#1d126295a307
 
 
Thank you,
Amine Moulay Ramdane.
aminer68@gmail.com: Jun 11 05:46PM -0700

Hello,
 
 
Lock Versus Lock-Free..
 
 
The class of problems that can be solved by lock-free approaches is limited.
 
Furthermore, lock-free approaches can require restructuring a problem.
As soon as multiple shared data-structures are modified simultaneously,the only practical approach is to use a lock.
 
All lock-free dynamic-size data-structures using such CAA (Compare-and-assign) require some form of garbage collector to lazily delete storage when it is no longer referenced. In languages with garbage collection, this capability comes for free (at the cost of garbage collection). For languages without garbage collection, the code is complex and error prone in comparison with locks, requiring epoch-based reclamation, read-copy-update (RCU), or hazard pointers.
 
While better performance is claimed for lock-free data-structures, there is no long-term evidence to support this claim. Many high-performance locking situations, e.g., operating system kernels and databases, continue to use locking in various forms, even though there are a broad class of lock-free data-structure readily available.
 
While lock-free data-structures cannot have deadlock, there is seldom deadlock using locks for the simple class of problems solvable using lock-free approaches. For example, protecting basic data-structure operations with locks is usually very straightforward. Normally deadlock occurs when accessing multiple resources simultaneously, which is not a class of problems dealt with by lock-free approaches. Furthermore, disciplined lock usage, such as ranking locks to avoid deadlock, works well in practice and is not onerous for the programmer.Finally, some static analysis tools are helpful for detecting deadlock scenarios.
 
Lock-free approaches have thread-kill tolerance, meaning no thread owns a lock, so any thread can terminate at an arbitrary point without leaving a lock in the closed state. However, within an application, thread kill is an unusual operation and thread failure means an unrecoverable error or major reset.
 
A lock-free approach always allows progress of other threads, whereas locks can cause delays if the lock owner is preempted. However,this issue is a foundational aspect of preemptive concurrency. And there are ways to mitigate this issue for locks using scheduler-activation techniques. However, lock-free is not immune to delays. If a page is evicted containing part of the lock-based or lockfree data, there is a delay. Hence, lock free is no better than lock based if the page
fault occurs on frequently accessed shared data. Given the increasing number of processors and large amount of memory on modern computers, neither of these delays should occur often.
 
Lock-free approaches are reentrant, and hence, can be used in signal handlers, which are implicitly concurrent. Locking approaches cannot deal with this issue. Lock-free approaches are claimed not to have priority inversion. However, inversion can occur because of the spinning required with atomic instructions, like CAA, as the hardware does not provide a bound for spinning threads. Hence, a low-priority thread can barge head of a high-priority thread because the low-priority thread just happens to win the race at the CAA instruction. Essentially,
priority inversion is a foundational aspect of preemptive concurrency and can only be mitigated.
 
The conclusion is that for unmanaged programming language (i.e., no garbage collection), using classical locks is simple, efficient, general, and causes issues only when the problem scales to multiple locks. For managed programming-languages, lock-free data-structures are easier to implement, but only handle a specific set of problems, and the programmer must accept other idiosyncrasies, like pauses in
execution for garbage collection.
 
 
 
Thank you,
Amine Moulay Ramdane.
aminer68@gmail.com: Jun 11 05:27PM -0700

Hello,
 
 
About programming languages and about Functional programming and about Haskell..
 
I have just talked about lock-based systems and about Transactional memory and about message passing vs shared memory, and now i will talk about programming languages and about Functional programming and about Haskell:
 
So read my following thoughts to understand:
 
https://community.idera.com/developer-tools/general-development/f/getit-and-third-party/71555/here-is-more-of-my-thoughts-on-programming-languages
 
 
Thank you,
Amine Moulay Ramdane.
aminer68@gmail.com: Jun 11 05:18PM -0700

Hello,
 
 
Message Passing vs Shared Memory
 
Read more here:
 
http://boron.physics.metu.edu.tr/ozdogan/GraduateParallelComputing.old/week8/node9.html
 
 
And now about The disadvantages of Actor model:

1- Not all languages easily enforce immutability

Erlang, the language that first popularized actors has immutability at
its core but Java and Scala (actually the JVM) does not enforce
immutability.


2- Still pretty complex

Actors are based on an asynchronous model of programming which is not so
straight forward and easy to model in all scenarios; it is particularly
difficult to handle errors and failure scenarios.


3- Does not prevent deadlock or starvation

Two actors can be in the state that wait message one from another; thus
you have a deadlock just like with locks, although much easier to debug.
With transactional memory however you are guaranteed deadlock free.


4- Not so efficient

Because of enforced immutability and because many actors have to switch
in using the same thread actors won't be as efficient as lock-based
concurrency.

 

Thank you,
Amine Moulay Ramdane.
aminer68@gmail.com: Jun 11 03:34PM -0700

Hello,
 
 
Why have i invented scalable RWLocks and scalable Locks ?
 
Because there is a disadvantage with Transactional memory and
here it is:
 
About Hardware Transactional Memory:
 
"As someone who has used TSX to optimize synchronization primitives, you can expect to see a ~15-20% performance increase, if (big if) your program is heavy on disjoint data access, i.e. a lock is needed for correctness, but conflicts are rare in practice. If you have a lot of threads frequently writing the same cache lines, you are probably going to see worse performance with TSX as opposed to traditional locking. It helps to think about TSX as transparently performing optimistic concurrency control, which is actually pretty much how it is implemented under the hood."
 
Read more here:
 
https://news.ycombinator.com/item?id=8169697
 
 
So as you are noticing, HTM (hardware transactional memory) and TM can not replace locks when doing IO and when we have a highly contended critical section.
 
 
Read the rest:
 
 
I have just read the following article that appeared in C/C++ Users Journal, 23(3), March 2005
 
The Trouble With Locks
 
http://gotw.ca/publications/mill36.htm
 
 
And here is my thoughts about how to avoid deadlocks and race conditions
in lock-based systems:
 
https://community.idera.com/developer-tools/general-development/f/getit-and-third-party/71464/about-turing-completeness-and-parallel-programming
 
Also i don't agree with him about composability of lock-based systems,
read the following to understand:
 
"About composability of lock-based systems now:
 
Design your systems to be composable. Among the more galling claims of the detractors of lock-based systems is the notion that they are somehow uncomposable:
 
"Locks and condition variables do not support modular programming," reads one typically brazen claim, "building large programs by gluing together smaller programs[:] locks make this impossible."9 The claim, of course, is incorrect. For evidence one need only point at the composition of lock-based systems such as databases and operating systems into larger systems that remain entirely unaware of lower-level locking.
 
There are two ways to make lock-based systems completely composable, and each has its own place. First (and most obviously), one can make locking entirely internal to the subsystem. For example, in concurrent operating systems, control never returns to user level with in-kernel locks held; the locks used to implement the system itself are entirely behind the system call interface that constitutes the interface to the system. More generally, this model can work whenever a crisp interface exists between software components: as long as control flow is never returned to the caller with locks held, the subsystem will remain composable.
 
Second (and perhaps counterintuitively), one can achieve concurrency and
composability by having no locks whatsoever. In this case, there must be
no global subsystem state—subsystem state must be captured in per-instance state, and it must be up to consumers of the subsystem to assure that they do not access their instance in parallel. By leaving locking up to the client of the subsystem, the subsystem itself can be used concurrently by different subsystems and in different contexts. A concrete example of this is the AVL tree implementation used extensively in the Solaris kernel. As with any balanced binary tree, the implementation is sufficiently complex to merit componentization, but by not having any global state, the implementation may be used concurrently by disjoint subsystems—the only constraint is that manipulation of a single AVL tree instance must be serialized."
 
Read more here:
 
https://queue.acm.org/detail.cfm?id=1454462
 
 
 
Thank you,
Amine Moulat Ramdane.
aminer68@gmail.com: Jun 11 03:07PM -0700

Hello,
 
 
Read again about Locks and composability, i have just added
my thoughts below about deadlocks and race conditions in
lock-based systems..
 
I have just read the following article that appeared in C/C++ Users Journal, 23(3), March 2005
 
The Trouble With Locks
 
http://gotw.ca/publications/mill36.htm
 
 
And here is my thoughts about how to avoid deadlocks and race conditions
in lock-based systems:
 
https://community.idera.com/developer-tools/general-development/f/getit-and-third-party/71464/about-turing-completeness-and-parallel-programming
 
Also i don't agree with him about composability of lock-based systems,
read the following to understand:
 
"About composability of lock-based systems now:
 
Design your systems to be composable. Among the more galling claims of the detractors of lock-based systems is the notion that they are somehow uncomposable:
 
"Locks and condition variables do not support modular programming," reads one typically brazen claim, "building large programs by gluing together smaller programs[:] locks make this impossible."9 The claim, of course, is incorrect. For evidence one need only point at the composition of lock-based systems such as databases and operating systems into larger systems that remain entirely unaware of lower-level locking.
 
There are two ways to make lock-based systems completely composable, and each has its own place. First (and most obviously), one can make locking entirely internal to the subsystem. For example, in concurrent operating systems, control never returns to user level with in-kernel locks held; the locks used to implement the system itself are entirely behind the system call interface that constitutes the interface to the system. More generally, this model can work whenever a crisp interface exists between software components: as long as control flow is never returned to the caller with locks held, the subsystem will remain composable.
 
Second (and perhaps counterintuitively), one can achieve concurrency and
composability by having no locks whatsoever. In this case, there must be
no global subsystem state—subsystem state must be captured in per-instance state, and it must be up to consumers of the subsystem to assure that they do not access their instance in parallel. By leaving locking up to the client of the subsystem, the subsystem itself can be used concurrently by different subsystems and in different contexts. A concrete example of this is the AVL tree implementation used extensively in the Solaris kernel. As with any balanced binary tree, the implementation is sufficiently complex to merit componentization, but by not having any global state, the implementation may be used concurrently by disjoint subsystems—the only constraint is that manipulation of a single AVL tree instance must be serialized."
 
Read more here:
 
https://queue.acm.org/detail.cfm?id=1454462
 
 
 
Thank you,
Amine Moulat Ramdane.
aminer68@gmail.com: Jun 11 02:45PM -0700

Hello,
 
 
About Locks and composability..
 
I have just read the following article that appeared in C/C++ Users Journal, 23(3), March 2005
 
The Trouble With Locks
 
http://gotw.ca/publications/mill36.htm
 
 
But i don't agree with him about composability of lock-based systems,
read the following to understand:
 
"About composability of lock-based systems now:
 
Design your systems to be composable. Among the more galling claims of the detractors of lock-based systems is the notion that they are somehow uncomposable:
 
"Locks and condition variables do not support modular programming," reads one typically brazen claim, "building large programs by gluing together smaller programs[:] locks make this impossible."9 The claim, of course, is incorrect. For evidence one need only point at the composition of lock-based systems such as databases and operating systems into larger systems that remain entirely unaware of lower-level locking.
 
There are two ways to make lock-based systems completely composable, and each has its own place. First (and most obviously), one can make locking entirely internal to the subsystem. For example, in concurrent operating systems, control never returns to user level with in-kernel locks held; the locks used to implement the system itself are entirely behind the system call interface that constitutes the interface to the system. More generally, this model can work whenever a crisp interface exists between software components: as long as control flow is never returned to the caller with locks held, the subsystem will remain composable.
 
Second (and perhaps counterintuitively), one can achieve concurrency and
composability by having no locks whatsoever. In this case, there must be
no global subsystem state—subsystem state must be captured in per-instance state, and it must be up to consumers of the subsystem to assure that they do not access their instance in parallel. By leaving locking up to the client of the subsystem, the subsystem itself can be used concurrently by different subsystems and in different contexts. A concrete example of this is the AVL tree implementation used extensively in the Solaris kernel. As with any balanced binary tree, the implementation is sufficiently complex to merit componentization, but by not having any global state, the implementation may be used concurrently by disjoint subsystems—the only constraint is that manipulation of a single AVL tree instance must be serialized."
 
Read more here:
 
https://queue.acm.org/detail.cfm?id=1454462
 
 
 
Thank you,
Amine Moulat Ramdane.
aminer68@gmail.com: Jun 11 12:56PM -0700

Hello,
 
 
About the Linux sys_membarrier() expedited and the windows FlushProcessWriteBuffers()..
 
Read my following thoughts to understand:
 
https://community.idera.com/developer-tools/general-development/f/getit-and-third-party/70804/about-the-linux-sys_membarrier-expedited-and-the-windows-flushprocesswritebuffers
 
 
Thank you,
Amine Moulay Ramdane.
aminer68@gmail.com: Jun 11 11:23AM -0700

Hello,
 
 
China Is Not A Technology Superpower. Stop Treating It Like One
 
Read more here:
 
https://supchina.com/2019/10/01/china-is-not-a-technology-superpower-stop-treating-it-like-one/
 
 
Thank you,
Amine Moulay Ramdane.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.programming.threads+unsubscribe@googlegroups.com.

No comments: