# Resource usage reduction in brick multiplexing

Each brick is regresented with a graph of translators in a brick process.
Each translator in the graph has its own set of threads and mem pools
and other system resources allocations. Most of the times all these
resources are not put to full use. Reducing the resource consumption
of each brick is a problem in itself that needs to be addressed. The other
aspect to it is, sharing of resources across brick graph, this becomes
critical in brick multiplexing scenario. In this document we will be discussing
only about the threads.

If a brick mux process hosts 50 bricks there are atleast 600+ threads created
in that process. Some of these are global threads that are shared by all the
brick graphs, and others are per translator threads. The global threads like
synctask threads, timer threads, sigwaiter, poller etc. are configurable and
do not needs to be reduced. The per translator threads keeps growing as the
number of bricks in the process increases. Each brick spawns atleast 10+
threads:
- io-threads
- posix threads:
     1. Janitor
     2. Fsyncer
     3. Helper
     4. aio-thread
- changelog and bitrot threads(even when the features are not enabled)

## io-threads

io-threads should be made global to the process, having 16+ threads for
each brick does not make sense. But io-thread translator is loaded in
the graph, and the position of io-thread translator decides from when
the fops will be parallelised across threads. We cannot entirely move
the io-threads to libglusterfs and say the multiplexing happens from
the primary translator or so. Hence, the io-thread orchestrator code
is moved to libglusterfs, which ensures there is only one set of
io-threads that is shared among the io-threads translator in each brick.
This poses performance issues due to lock-contention in the io-threds
layer. This also shall be addressed by having multiple locks instead of
one global lock for io-threads.

## Posix threads
Most of the posix threads execute tasks in a timely manner, hence it can be
replaced with a timer whose handler register a task to synctask framework, once
the task is complete, the timer is registered again. With this we can eliminate
the need of one thread for each task. The problem with using synctasks is
the performance impact it will have due to make/swapcontext. For task that
does not involve network wait, we need not do makecontext, instead the task
function with arg can be stored and executed when a synctask thread is free.
We need to implement an api in synctask to execute atomic tasks(no network wait)
without the overhead of make/swapcontext. This will solve the performance
impact associated with using synctask framework.

And the other challenge, is to cancel all the tasks pending from a translator.
This is important to cleanly detach brick. For this, we need to implement an
api in synctask that can cancel all the tasks from a given translator.

For future, this will be replced to use global thread-pool(once implemented).

## Changelog and bitrot threads

In the initial implementation, the threads are not created if the feature is
not enabled. We need to share threads across changelog instances if we plan
to enable these features in brick mux scenario.

