\section{Implémentation}

L'implémentation se distingue en deux parties mais avec une grosse base commune décrite dans \ref{sec:impl_general}.

\subsection{Générale}\label{sec:impl_general}

Nous utilisons une file qui ne contient que les threads non finis et non en attente.
Lorsque qu'un thread fini, il met celui qui l'attend dans la file.
On a une file de threads à utiliser pour ne pas libérer/allouer en permanence. Celui qui attend un thread le met dans la file lorsqu'il peut reprendre la main.
On préalloue 2000 threads au début pour être tranquille. Voir graphes de performances figure \ref{fig:create-many}

\begin{figure}[h!]
    \centering
    \begin{minipage}[b]{0.49\linewidth}
        \centering
        \subfloat[]{
            \includesvg[width=\linewidth]{img/graphs/21-create-many.svg}
        }
    \end{minipage}
    \begin{minipage}[b]{0.49\linewidth}
        \centering
        \subfloat[]{
            \includesvg[width=\linewidth]{img/graphs/22-create-many-recursive.svg}
        }
    \end{minipage}\par\medskip
    \begin{minipage}[b]{0.49\linewidth}
        \centering
        \subfloat[]{
            \includesvg[width=\linewidth]{img/graphs/23-create-many-once.svg}
        }
    \end{minipage}
    \caption{Performances sur la création de multiples threads}
    \label{fig:create-many}
\end{figure}

Les graphiques montrent une grande différence entre \code{pthread} et nos threads, cela s'explique par le fait que \code{pthread} s'exécute en multi-coeurs et il y a un gros coût de performance à faire cela. On s'attend à un sur-coût équivalent lors de notre future implémentation des threads noyaux.

\subsection{Fibonacci}

L'implémentation pour Fibonacci ne se distingue que sur un aspect important : la technique d'
ordonnancement. Si dans le cas général nous utilisons une file, pour Fibonacci nous passons à une pile. Cela permet de parcourir l'arbre des appels en profondeur et non en largeur. De fait, nous avons au maximum $h$ threads en même temps, où $h$ est la hauteur de l'arbre des appels, \emph{id est} $n$ pour l'exécution de {\ttfamily fibo(n)}.

En plus de cela, nous trichons \emph{légèrement} sur l'ordonnancement en rendant le premier appel à \code{thread\_yield} inutile. C'est-à-dire que l'ordonnanceur regarde si le thread en court d'exécution a déjà fait un appel à \code{thread\_yield}. Le cas échéant il basculera sur un nouveau thread, sinon celui courant garde la main.

\begin{figure}[h]
    \centering
    \includesvg{img/graphs/51-fibonacci.svg}
    \caption{Performances sur Fibonacci}
    \label{fig:fibo}
\end{figure}

Grâce à la comparaison sur la figure \ref{fig:fibo}, nous pouvons voir que notre bibliothèque est bien plus performante que \code{pthreads}. Cela s'explique par notre optimisation pour ce test uniquement là où la glibc est bien plus générale. De plus, cette-dernière utilise les threads noyaux, plus gourmands, qui explorent plusieurs branches en même temps.