## 4 Evaluation
### Experimental Results
in improved resource utilization and makespans, as depicted in the exemplary case of K-means benchmark (Figure 5) and Figure 3.  
In the case of applications where the overall execution time increased compared to the Fair approach (e.g., Terasort and Join in Hadoop as seen from Figure 3a), the workload is typically divided into several execution steps so that, between those steps, other running containers may have acquired idle computing resources. This can be an interesting trade-offs of making the monitoring and adjusting cycles short (in our case, 3 s, as discussed in Section 3.2). If there are idle cycles longer than our predefined monitoring period between multiple steps of a Big Data job, allocated computing resources can be redistributed to other containers even though that Big Data job has not been completely finished yet. Nevertheless,  
Figure 4: Memory usages of benchmarks in the Fair approach to show an exemplary case of inefficient resource usage patterns. Figure 5: Memory usages in the K-means benchmark in the Adaptive approach to show an exemplary case of efficient resource usage patterns. based on the effective vertical elasticity management of Docker containers, our proposed scheme can achieve aggregated performance improvements by 50.1% and 13.7% in Hadoop and Spark, respectively (as seen from \"Total\" in Figure 2(a),b) for representative Big Data workloads. Tables 4 and 5 show the summarized experimental results for single-container executions and concurrent container executions, respectively. Docker not only can limit the maximum CPU usage of a container based on CPU time but also supports the method of limiting the use of only specific CPUs by setting a fixed set of CPU thread numbers (called \"CPU Affinity\") [30]. In the case of conventional CPU time-based approach, since the CPUs being used can continuously change, the overhead of context switching may occur. Therefore, in order to investigate the effects of CPU pinning (i.e., setting the CPU affinity) on Big Data workloads, we performed other experiments, as seen in Figure 6. We compared our basic adaptive resource allocation scheme (**Adaptive**) with the modified CPU allocation method from time sharing to affinity (**Adaptive-affinity**). Overall, the effects of applying CPU affinity to the resource allocation of containers seem not so significant considering that we are running Big Data workloads, which are not typically compute-intensive. For example, the aggregated makespan of Adaptive affinity is improved only by 1.9% compared to the basic Adaptive approach in the Hadoop platform (as seen from Figure 5(a)). Interestingly, the aggregated makespan of Adaptive affinity becomes worse by 5.7% compared to the original approach in the Spark platform, as seen \begin{table}
\begin{tabular}{c c c c c} \hline \hline
**Benchmark** & **Hadoop (Baseline)** & **Hadoop (Adaptive)** & **Spark (Baseline)** & **Spark (Adaptive)** \\ \hline Terasort & 1275.2 & 1471.2 & 1725.6 & 1848.8 \\ K-means & 1806.2 & 1860.4 & 1151.6 & 1333 \\ PageRank & 1285.8 & 1334 & 1741.8 & 2607.6 \\ Join & 552.4 & 595.8 & 270.8 & 398.8 \\ \hline \hline \end{tabular}
\end{table} 
Table 4: Summary of single-container executions (sec). Figure 6: Effects of CPU Affinity, which limits the use of only specific CPUs by setting a fixed set of CPU thread numbers for Big Data workloads. \begin{table}
\begin{tabular}{c c c c c} \hline \hline
**Benchmark** & **Hadoop (Fair)** & **Hadoop (Adaptive)** & **Spark (Fair)** & **Spark (Adaptive)** \\ \hline Terasort & 3992 & 5007.6 & 6146.4 & 5140.8 \\ K-means & 10,621.2 & 4620.4 & 5605.4 & 4953.2 \\ PageRank & 5432.8 & 5301 & 6860.4 & 5918.4 \\ Join & 2002.8 & 2187.8 & 1864.6 & 1868.6 \\
**Total** & **10,621.2** & **5301** & **6860.4** & **5918.4** \\ \hline \hline \end{tabular}
\end{table} 
Table 5: Summary of concurrent container executions (sec). from Figure 6b.