Sistemas Operacionais
Atividade Bônus 2
07/04/2019
NOME: Batata Frita
Matrícula: 01110000 01101111 01110100 01100001 01110100 01101111
Foi proposto nesta atividade, fazer dois programas quaisquer na linguagem C:
O objetivo é compará-los e verificar quais dos dois possui a maior eficiência.
Para executar este experimento, foi utilizado o seguinte hardware: Notebook Dell Latitude 3480 (8GB de memória RAM, processador Intel Core i5-7200 x86_64 2.5GHz)
Versão do Kernel: 4.15.0-47-generic
Distribuição Linux: Ubuntu 18.04
Versão do gcc: 7.3.0
Junto às instruções deste experimento, está o código em C para utilizarmos no teste.
Para que não seja necessário dois arquivos (um para syscalls, outro para funções da libc) e sim, apenas um arquivo binário, modifiquei o código fonte para ficar da seguinte maneira:
./bonus2.c
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
/*
* First argument: mode (libc or syscall)
* Second argument: buffer size
*/
int main(int argc, char *argv[]) {
char buffer[2000000];
int i;
if( !strcmp(argv[1], "syscall") ) {
i = read(0, &buffer, strtol(argv[2], (char **)NULL, 10));
while(i > 0) {
write(1, &buffer, strtol(argv[2], (char **)NULL, 10));
i = read(0, &buffer, strtol(argv[2], (char **)NULL, 10));
}
}
else if( !strcmp(argv[1], "libc") ) {
i = fread(&buffer, strtol(argv[2], (char **)NULL, 10), 1, stdin);
while(i > 0) {
fwrite(&buffer, strtol(argv[2], (char **)NULL, 10), 1, stdout);
i = fread(&buffer, strtol(argv[2], (char **)NULL, 10), 1, stdin);
}
}
else {
printf("%s: Unknown option.\n", argv[0]);
}
return 0;
}
Para obter o executável, é necessário compilar utilizando o gcc
:
gcc -o bonus2 arquivo.c
Observação: utilizei, também, o clang
. Apesar de ser mais rápido, não achei que fosse necessário utilizá-lo como compilador principal para o experimento.
Essa modificação permite que em único binário, seja executado o teste tanto com syscalls quanto com funções da libc, com o tamanho do buffer desejado. O código deve ser executado desejado seguinde forma:
./bonus2 libc 16
./bonus2 syscall 32
De acordo com as instruções, os tamanhos dos buffer que serão usados são: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, ..., 1048546
Para não ter que executar o binario várias vezes, criei o seguinte script:
./iterator.sh
#!/bin/bash
size=1
printf "%s\n" "glibc:"
for i in $(seq 0 20); do
# clear cache
sync; echo 3 > /proc/sys/vm/drop_caches
printf "buffer size: %s - " "$size"
output=$({ time ./bonus2 libc "$size" < datafile > /dev/null; } 2>&1)
value_output=$?
# print only if the above execution was successfull
if [[ $value_output -eq 1 ]]; then
echo "$output" | grep real | awk '{ print $2 }'
fi
let size=size*2
done
size=1
printf "%s\n" "Syscalls:"
for i in $(seq 0 20); do
# clear cache
sync; echo 3 > /proc/sys/vm/drop_caches
printf "buffer size: %s - " "${size}"
output=$({ time ./bonus2 syscall "${size}" < datafile > /dev/null; } 2>&1)
value_output=$?
# print only if the above execution was successfull
if [[ $value_output -eq 1 ]]; then
echo "$output" | grep real | awk '{ print $2 }'
fi
let size=size*2
done
Com a execução do script acima, obteve-se o seguinte resultado:
glibc:
buffer size: 1 - 0m0,970s
buffer size: 2 - 0m0,951s
buffer size: 4 - 0m0,410s
buffer size: 8 - 0m0,476s
buffer size: 16 - 0m0,450s
buffer size: 32 - 0m0,475s
buffer size: 64 - 0m1,017s
buffer size: 128 - 0m0,776s
buffer size: 256 - 0m0,472s
buffer size: 512 - 0m0,461s
buffer size: 1024 - 0m0,852s
buffer size: 2048 - 0m0,618s
buffer size: 4096 - 0m0,450s
buffer size: 8192 - 0m0,460s
buffer size: 16384 - 0m0,404s
buffer size: 32768 - 0m0,449s
buffer size: 65536 - 0m0,458s
buffer size: 131072 - 0m0,572s
buffer size: 262144 - 0m0,459s
buffer size: 524288 - 0m0,559s
buffer size: 1048576 - 0m0,618s
Syscalls:
buffer size: 1 - 0m8,326s
buffer size: 2 - 0m4,351s
buffer size: 4 - 0m2,439s
buffer size: 8 - 0m1,404s
buffer size: 16 - 0m0,854s
buffer size: 32 - 0m0,594s
buffer size: 64 - 0m1,590s
buffer size: 128 - 0m0,473s
buffer size: 256 - 0m0,449s
buffer size: 512 - 0m0,869s
buffer size: 1024 - 0m0,966s
buffer size: 2048 - 0m0,672s
buffer size: 4096 - 0m0,477s
buffer size: 8192 - 0m0,541s
buffer size: 16384 - 0m0,475s
buffer size: 32768 - 0m0,673s
buffer size: 65536 - 0m0,849s
buffer size: 131072 - 0m0,397s
buffer size: 262144 - 0m0,452s
buffer size: 524288 - 0m0,484s
buffer size: 1048576 - 0m0,610s
Transformado-os em um gráfico, fica da seguinte forma:
De acordo com os resultados, a conclusão foi que utilizar funções da libc é mais eficiente e mais rápida que funções do sistema (syscalls), por isso devemos utilizá-la ao invés de funções do sistema.