Reducción de consumo energético en aplicaciones científicas ...
Transcript of Reducción de consumo energético en aplicaciones científicas ...
Universidad Nacional del Centro de la Provincia De Buenos Aires
Facultad de Ciencias Exactas - Departamento de Computación y Sistemas
Doctorado en Ciencias de la Computación
Reducción de consumo energético en aplicaciones científicas paradispositivos móviles a través de refactorización de código fuente
Ing. Ana Victoria RodríguezDirector: Dr. Alejandro Zunino
Co-Director: Dr. Cristian Mateos
Tesis presentada como requisito parcial
para optar por el título de
Doctor en Ciencias de la Computación
Noviembre 2017
Resumen
La llegada de ambientes de cómputo que representan nuevos paradigmas de compu-
tación como los grid móviles y los clouds móviles, junto con el creciente número de dis-
positivos móviles con capacidades cada vez más potentes hace este tipo de dispositivos
atractivos para los usuarios que ejecutan aplicaciones científicas y de HPC. Sin embar-
go, los dispositivos móviles aún tienen capacidades limitadas en comparación con otros
dispositivos como PCs y sobre todo servidores, generando obstáculos para desarrollar
software que aproveche las mismas. Aún más importante a la hora de realizar desarrollos
móviles es tener en cuenta que los dispositivos móviles dependen de las baterías para su
suministro de energía, por lo que los usuarios descartan las aplicaciones que afectan sig-
nificativamente la duración de las mismas. Como resultado, aparece un nuevo requisito
no funcional al momento de desarrollar aplicaciones para dispositivos móviles: consumo
energético.
Comúnmente, los desarrolladores no saben cuánta energía consumen los diferentes com-
ponentes de hardware y el software. Entonces, a pesar de que estén capacitados para
desarrollar software, necesitan pautas y conocimientos específicos para desarrollar apli-
caciones eficientes energéticamente. Para atacar este problema, esta tesis de doctorado es-
tudia cómo reducir el consumo de energía en dispositivos móviles a través de refactoriza-
ción de código fuente. Específicamente, investigamos este problema en el contexto de los
núcleos computacionales intensivos recurrentes en aplicaciones científicas pero sin dejar
de lado la posibilidad de extender los resultados a otras áreas. Particularmente, este es-
tudio conlleva a contribuciones no sólo en el desarrollo de software móvil, sino también
en el área de Green Computing.
Para lograr el objetivo de este trabajo primero debemos delimitar el estudio a un sistema
operativo (SO) específico y un lenguaje específico ya que el comportamiento energético
varía de acuerdo al SO, el lenguaje y el hardware, entre otras variables. Entonces, lue-
go de evaluar diferentes sistemas operativos y lenguajes, decidimos utilizar dispositivos
móviles Android –el sistema operativo móvil más popular a nivel mundial– y desarro-
llar el estudio en Java, el lenguaje de alto nivel de Android. En un segundo paso, pre-
sentamos los trade-off entre el esfuerzo de análisis y refactorización necesario frente a
la ganancia (en términos de energía) para cada refactorización, junto con el impacto en
el diseño de la aplicación generado por aplicar estos refactorings. Además, se analizan
los inconvenientes inherentes al uso de dispositivos móviles para la ejecución de códigos
computacionalmente intensivos, limitando la investigación a teléfonos inteligentes y ta-
bletas. La elección de Java, además, propicia el análisis del desempeño de los refactorings
en desarrollo de aplicaciones científicas que corren en servidores, donde el uso de Java es
altamente difundido.
En resumen, la evaluación del enfoque apunta a medir el consumo energético de di-
ferentes versiones de varios grupos de micro-benchmarks que representan operaciones
primitivas comunes en aplicaciones científicas. Basándonos en el análisis de estas evalua-
ciones de micro-benchmarks derivamos guías de buenas prácticas para que los desarro-
lladores puedan aplicar las abstracciones de programación más eficientes desde el punto
de vista energético en sus aplicaciones. Además, generamos guías prácticas para refac-
torizar aplicaciones existentes, propiciando así una reducción en su consumo energético.
Finalmente, evaluamos y analizamos el impacto de tales refactorizaciones en aplicaciones
móviles con uso intensivo de CPU. En todos nuestros experimentos utilizamos variedad
de dispositivos móviles para obtener más generalidad al obtener los resultados ya que
el consumo energético de una operación puede variar de acuerdo al hardware de cada
dispositivo. Además, presentamos los resultados de los trabajos realizados sobre servi-
dores con la finalidad de comparar el impacto obtenido en los diferentes ambientes de
ejecución.
Keywords: Dispositivos móviles, Consumo energético, Refactoring, Android, Java, Micro-
benchmark.
Agradecimientos
Me gustaría extender mi agradecimiento a todas las personas e instituciones que me han
permitido terminar este trabajo. En primer lugar, me gustaría agradecer a mis directores,
Alejandro Zunino y Cristian Mateos, por su constante apoyo y orientación durante mi
trabajo. Sin su constante aliento y consejos, este trabajo nunca hubiera sido posible.
También me gustaría extender mi agradecimiento al ISISTAN y a su personal por pro-
porcionar un ambiente de trabajo cómodo.
Mi gratitud también se extiende a Marisa Musa por su invaluable conocimiento de inglés.
Agradezco al Consejo Nacional de Investigaciones Científicas y Técnicas (CONICET) por
su apoyo financiero a través de diferentes becas.
Finalmente, me gustaría agradecer a mi familia por su apoyo. En particular, quiero agra-
decer a mis padres, Ana María y Jorge Antonio, y mis hermanos, Ana Paula, Jorge Tomás,
Juan Manuel y Alex Jorge.
Ana Victoria
Índice general
1. Introducción 1
1.1. Motivación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2. Tesis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.3. Organización . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2. Background 11
2.1. Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.2. Aplicaciones Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3. HPC en Smartphones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
2.4. Mobile Grids . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.5. Green Computing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.6. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3. Trabajos Relacionados 25
3.1. Offloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.1.1. Enfoques orientados a la performance . . . . . . . . . . . . . . . . . 29
3.1.2. Enfoques orientados a energía . . . . . . . . . . . . . . . . . . . . . 30
3.1.3. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
3.2. Schedulers distribuidos para dispositivos móviles basados en energía . . . 35
3.3. Modelos de desarrollo de software y metodologias basados en energía . . 39
3.3.1. Dispositivos móviles . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.3.2. Servidores y computadoras personales . . . . . . . . . . . . . . . . 54
3.4. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4. Micro-benchmarks y aplicaciones 59
4.1. Micro-benchmarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
4.1.1. Copia de arreglos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4.1.2. Creación de objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.1.3. Acceso a atributos de un objeto . . . . . . . . . . . . . . . . . . . . . 63
4.1.4. Manejos de Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.1.5. Manejo de excepciones . . . . . . . . . . . . . . . . . . . . . . . . . . 64
4.1.6. Uso de tipos de datos primitivos . . . . . . . . . . . . . . . . . . . . 65
4.1.7. Recorrido de matrices . . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.1.8. Operaciones aritméticas . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.2. Aplicaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
4.2.1. Fast Fourier Transform (FFT) . . . . . . . . . . . . . . . . . . . . . . 70
4.2.2. Matrix multiplication (MMULT) . . . . . . . . . . . . . . . . . . . . 71
4.2.3. Knapsack (KP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
4.2.4. N-Queens Problem . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
4.2.5. Sequence Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
4.2.6. Gradient Descent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.2.7. Bayes Network Classifier . . . . . . . . . . . . . . . . . . . . . . . . 76
4.2.8. Aplicaciones de usuario final (FiveStones y Sorter) . . . . . . . . . 77
4.3. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
5. Experimentos 81
5.1. Caliper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
5.2. Aplicación Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
5.2.1. Metodología . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
5.3. Aplicación para Servidores . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
5.4. Aplicaciones de usuario final . . . . . . . . . . . . . . . . . . . . . . . . . . 90
5.5. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
6. Resultados 93
6.1. Resultados de Micro-benchmark (Móviles) . . . . . . . . . . . . . . . . . . 94
6.1.1. Copia de arreglos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
6.1.2. Creación de objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
6.1.3. Acceso a un atributo de objetos . . . . . . . . . . . . . . . . . . . . . 98
6.1.4. Manejo de Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
6.1.5. Manejo de excepciones . . . . . . . . . . . . . . . . . . . . . . . . . . 99
6.1.6. Uso de tipos de datos primitivos . . . . . . . . . . . . . . . . . . . . 100
6.1.7. Recorrido de matrices . . . . . . . . . . . . . . . . . . . . . . . . . . 102
6.1.8. Operaciones aritméticas . . . . . . . . . . . . . . . . . . . . . . . . . 104
6.1.9. Resumen micro-benchmarks en dispositivos móviles . . . . . . . . 105
6.2. ¿Cómo refactorizar aplicaciones? . . . . . . . . . . . . . . . . . . . . . . . . 106
6.3. Resultados de las aplicaciones de prueba en dispositivos móviles . . . . . 110
6.3.1. Fast Fourier Transform (FFT) . . . . . . . . . . . . . . . . . . . . . . 110
6.3.2. Matrix multiplication (MMULT) . . . . . . . . . . . . . . . . . . . . 116
6.3.3. Knapsack Problem (KP) . . . . . . . . . . . . . . . . . . . . . . . . . 117
6.3.4. Aplicaciones Multi-core . . . . . . . . . . . . . . . . . . . . . . . . . 118
6.3.5. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
6.4. Resultados de Micro-benchmarks (Servidores) . . . . . . . . . . . . . . . . 121
6.5. Resultados de aplicaciones en servidores . . . . . . . . . . . . . . . . . . . 123
6.5.1. Fast Fourier Transformation (FFT) . . . . . . . . . . . . . . . . . . . 125
6.5.2. Matrix Multiplication (MMULT) . . . . . . . . . . . . . . . . . . . . 126
6.5.3. Knapsack (KP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
6.5.4. N-Queens problem (NQ) . . . . . . . . . . . . . . . . . . . . . . . . 126
6.5.5. Sequence alignment (SA) . . . . . . . . . . . . . . . . . . . . . . . . 126
6.5.6. Gradient Descent (GA) . . . . . . . . . . . . . . . . . . . . . . . . . 127
6.5.7. Bayes Network Classifier (Bayes) . . . . . . . . . . . . . . . . . . . . 128
6.5.8. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
6.6. Aplicaciones de usuario final en dispositivos móviles . . . . . . . . . . . . 131
6.7. Eficiencia energética vs. diseño OO . . . . . . . . . . . . . . . . . . . . . . . 133
6.8. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
7. Conclusiones y Trabajos Futuros 137
7.1. Conclusiones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
7.1.1. Q1 ¿Pueden ser refactorizaciones simples útiles para ahorrar ener-
gía en aplicaciones científicas con uso intensivo de recursos compu-
tacionales? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
7.1.2. Q2 ¿Cuál es el impacto que estas refactorizaciones generan en apli-
caciones científicas reales? . . . . . . . . . . . . . . . . . . . . . . . . 139
7.1.3. Q3 ¿Cuál es el impacto de estas refactorizaciones en el diseño orien-
tado a objetos y la calidad de la aplicación? . . . . . . . . . . . . . . 140
7.1.4. Q4 ¿Cómo impactan estas refactorizaciones en el consumo energé-
tico en aplicaciones científicas en servidores? . . . . . . . . . . . . . 140
7.1.5. Q5 ¿Qué tan adecuadas son estas refactorizaciones para aplicacio-
nes de usuario final? . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
7.1.6. Resumen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
7.2. Trabajos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
7.3. Publicaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143
7.3.1. Revista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
7.3.2. Capítulos de libro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
7.3.3. Conferencias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
Bibliografía 147
Índice de figuras
1.1. Evolución de los smartphones . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1. Arquitectura de Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2. Versiones de Android . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.3. Ciclo de vida de una Activity . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.4. Ciclo de vida de un Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.1. Cliente vs VM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.1. Secuencias de ADN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
4.2. FiveStones UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.3. Sorter UI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
5.1. Micro-benchmark . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.2. Aplicación Android: Diagrama de clases y Scrrenshot . . . . . . . . . . . . 85
5.3. Diagrama de clases del software utilizado para medir el consumo de aplca-
ciones científicas en servidores . . . . . . . . . . . . . . . . . . . . . . . . . 89
5.4. Power Meter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
5.5. Power Monitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
6.1. Resultados de los grupos de micro-benchmarks . . . . . . . . . . . . . . . 96
6.2. Arreglos en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
6.3. Comparación de resultados de micro-benchmark . . . . . . . . . . . . . . . 106
6.4. FFT (Dispositivos Móviles) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
6.5. MMULT (Dispositivos Móviles) . . . . . . . . . . . . . . . . . . . . . . . . . 117
6.6. Knapsack (Dispositivos Móviles) . . . . . . . . . . . . . . . . . . . . . . . . 118
6.7. Multi-core evaluation (Dispositivo Movil) . . . . . . . . . . . . . . . . . . . 119
6.8. Consumo para single-thread (izquierda) y multi-thread (derecha). los val-
ores tienen una escala de log10 . . . . . . . . . . . . . . . . . . . . . . . . . 125
Índice de tablas
3.1. Resumen de Offloaders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.2. Evaluación (ms) Sangchul and Wook [2010] . . . . . . . . . . . . . . . . . . 42
3.3. Resumen de guías . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
4.1. Grupos de micro-benchmark . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.2. Resumen de aplicaciones de Ibis/Satin. El signo “+” representa una indi-
cación cuantitativa de la extensión de código que tiene ese grupo de micro-
benchmarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.3. Aplicaciones de casos de estudio. El signo “+” representa una indicación
cuantitativa de la extensión de código que tiene ese grupo de micro-benchmarks 80
4.4. Aplicaciones de casos de estudio (Machine Learning). El signo “+” repre-
senta una indicación cuantitativa de la extensión de código que tiene ese
grupo de micro-benchmarkse . . . . . . . . . . . . . . . . . . . . . . . . . . 80
6.1. Resultado de Micro-benchmarks (Móviles) . . . . . . . . . . . . . . . . . . 95
6.2. Refactoring application effort . . . . . . . . . . . . . . . . . . . . . . . . . . 108
6.3. Resultados de aplicaciones (I5500 smartphone) . . . . . . . . . . . . . . . . 111
6.4. Resultados de aplicaciones (ViewPad 10s tablet) . . . . . . . . . . . . . . . 112
6.5. Resultados de aplicaciones (Acer A100 tablet) . . . . . . . . . . . . . . . . . 113
6.6. Resultados de aplicaciones multicore (Acer A100 tablet) . . . . . . . . . . . 114
6.7. Test de significancia estadística: Variación en número de ejecuciones . . . 120
6.8. Resultados de Micro-benchmarks (Server) . . . . . . . . . . . . . . . . . . . 122
6.9. Resultados de aplicaciones de prueba en servidores . . . . . . . . . . . . . 124
6.10. Significancia estadística de test en aplicaciones reales en servidores . . . . 129
6.11. Resultados de aplicaciones de usuario final en dispositivos móviles . . . . 132
7.1. Eficiencia energética vs. diseño OO . . . . . . . . . . . . . . . . . . . . . . . 140
Índice de algoritmos
3.1. Declaración estática . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.2. Acceso privado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
6.1. Dex-code copia de arreglos manual . . . . . . . . . . . . . . . . . . . . . . . 97
6.2. Dex-code System.arraycopy . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
6.3. Dex-code creación de objetos . . . . . . . . . . . . . . . . . . . . . . . . . . 98
6.4. Dex-code reuso de objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
6.5. Dex-code invocación de métodos . . . . . . . . . . . . . . . . . . . . . . . . 99
6.6. Dex-code acceso directo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
6.7. Dex-code String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
6.8. Dex-code StringBuilder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
6.9. Dex-code excepción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
6.10. Dex-code sin excepción . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
6.11. Dex-code uso de clases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
6.12. Dex-code tipos de datos primitivos . . . . . . . . . . . . . . . . . . . . . . . 103
6.13. Dex-code recorrido por columnas . . . . . . . . . . . . . . . . . . . . . . . . 104
6.14. Dex-code recorrido por filas . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
6.15. Dex-code operación aritmética . . . . . . . . . . . . . . . . . . . . . . . . . 105
Acrónimos
API Application Programming Interface
AOT Ahead-of-time
ART Android Runtime
DFT Discrete Fourier Transform
GC Garbage Collector
HAL Hardware Abtraction Layer
HPC High Performance Computing
ICT Information and Communication Technology
IDE Integrated Development Environment
JIT Just-In-Time
JRE Java Runtime Environment
JVM Java Virtual Machine
NDK Native Development Kit
OO Orientado a Objetos
SO Sistema Operativo
URI Uniform Resource Identifier
Capıtulo 1
Introducción
A lo largo de este capítulo desarrollaremos la motivación del problema que este trabajo
pretende abordar: el consumo de energía de las aplicaciones móviles científicas. Toma-
mos en cuenta no solo los problemas específicos, sino también sus orígenes y desarrollo,
ambos necesarios para comprender su evolución. Además, se presenta una breve intro-
ducción a las decisiones tomadas a lo largo del trabajo y a la metodología experimen-
tal. Junto con esta introducción inferimos las contribuciones de este trabajo en diferentes
áreas científicas. Finalmente, el Capítulo concluye describiendo la estructura general del
documento.
1.1. Motivación
En comparación con las computadoras personales o servidores, los dispositivos móviles
tienen recursos más limitados. En este contexto, un punto importante es el de minimizar
el consumo de energía ya que los dispositivos móviles dependen de sus baterías para el
suministro energético. Por otra parte, los dispositivos como smartphones y tablets repre-
sentan un mercado atractivo para el desarrollo de aplicaciones, principalmente porque
estos dispositivos son la forma más popular de tecnología en el mundo Rodriguez et al.
[2011b]. Algunas razones de su popularidad son sus interesantes interesantes como Wi-
Fi, un teclado físico o virtual para ingresar información, la capacidad de descargar datos
de Internet (incluidas aplicaciones y libros), y el tamaño y el peso que permite llevarlos
en una mano y manipularlo con la otra mano. Consecuentemente, estos dispositivos ya
no son simples agendas o teléfonos celulares, sino que ahora son "computadoras peque-
ñas" que los usuarios pueden explotar sus capacidades para realizar tareas de oficina,
entretenerse y navegar por Internet, entre otras funcionalidades.
Para apreciar las capacidades computacionales de los dispositivos móviles modernos, es
necesario mirar al pasado. En 1986, el Cray X-MP, que tenía 16-128 megabytes de RAM
1
y uno, dos o cuatro procesadores corriendo a 117 MHz cada uno, era uno de las super-
computadoras más potentes del momento. Esta computadora necesitaba un suministro
de energía dedicado para satisfacer las necesidades energéticas Foster and Kesselman
[2003]. Hoy en día los smartphones actuales tienen un procesador, con 2 a 10 núcleos fun-
cionando hasta 2 GHz cada uno, y también hasta varios gigabytes de RAM, satisfaciendo
las necesidades energéticas a través de una batería. Otra diferencia entre los antiguas
supercomputadoras y los dispositivos móviles es que mientras las supercomputadoras
estaban interconectadas con otras computadoras a través de enlaces de red cableados,
los dispositivos móviles pueden conectarse a través de una gama de tecnologías de re-
des inalámbricas (por ejemplo, 3G, 4G, WiFi o Bluetooth) con una velocidad superior a 1
Mbps Rodriguez et al. [2011b].
Finalmente, esta tesis doctoral se basa principalmente en dos tipos de dispositivos mó-
viles: smartphones y tablets. Por un lado, un smartphone es un teléfono celular con una
computadora integrada que le permite tener características que originalmente no están
asociadas con los teléfonos móviles (un explorador web y la capacidad de ejecutar aplica-
ciones de software, por ejemplo). Por otro lado, una tablet es una computadora móvil de
una pieza con pantallas más grandes que un smartphone y ofrece entretenimiento por-
tátil y navegación por la web. Además, los dispositivos seleccionados ofrecen caracterís-
ticas de hardware interesantes como GPS, sensor de proximidad, barómetro, giroscopio,
magnetómetro y acelerómetros que no están presentes en otro tipo de dispositivos.
Entonces, es importante mencionar la evolución acelerada de estos dispositivos móviles
particulares, Figura 1.1. Podemos observar el progreso constante en los teléfonos inteli-
gentes comparando el Samsung Galaxy S que se lanzó al mercado el 9 de septiembre de
2010 y el último lanzamiento de Samsung, el Samsung Galaxy S8, lanzado al mercado
el 28 de abril de 2017. El Samsung Galaxy S utiliza el procesador Samsung S5PC110 que
combina una CPU ARM Cortex-A8 de 45 nm a 1 GHz con 512 MB de RAM, tiene un al-
macenamiento interno de 2 GB, un tiempo de conversación de hasta 6 horas y un tiempo
de espera de hasta 12 días y es compatible con Bluetooth 3.0, Wi-Fi 802.11b/g/n y datos
3 G con una tasa de transferencia hasta 7.2 Mbit/s. Por otra parte, el Galaxy S8 tiene un
procesador Octa-Core (2.3 Ghz Quad-Core + 1.7 Ghz Quad-Core), 4 GB de RAM y 64 GB
de almacenamiento interno. Tiene una batería Li-Ion 3000 mAh con un tiempo de espera
de hasta 24 días y un tiempo de conversación de hasta 20 horas. Este dispositivo agrega
nuevos sensores como lector de huellas dactilares, lector de iris, sensor de ritmo cardíaco
y sensor geomagnético.
Por otro lado, la idea de una tablet nació en la década de 1960 cuando investigadores
tuvieron la idea de un dispositivo portátil estilo tablet llamado Dynabook que serviría
principalmente para dar a los niños un acceso fácil a cualquier medio digital. Dynabook
actuaría como papel y lápiz, caballete de artista, máquina de escribir e instrumento musi-
2
Figura 1.1: Evolución de los smartphones
cal. Sin embargo, Dynabook nunca pasó la etapa conceptual debido a las limitaciones tec-
nológicas del momento. Finalmente, en 1989 nació la primera tablet, llamada GRiDPad.
GRiDPad tenía un procesador 80C86 a 10 MHz, sistema operativo MS-DOS, un adapta-
dor de gráficos a color monocromático (CGA), resolución de pantalla de 640x400 píxeles,
256 KB o 512 KB de tarjetas RAM, 1 MB o 2 MB de memoria interna del sistema, uno
puerto serie, dos ranuras ATA-FLASH y un conector de bus de expansión. El 24 de marzo
de 2017 Samsung lanzó la Galaxy Tab S3 que viene con un procesador Qualcomm Snap-
dragon 820, 4 GB de RAM, 32 GB de almacenamiento interno, una batería de 6000 mAh,
pantalla táctil super AMOLED capacitiva, 16 millones de colores, resolución de pantalla
de 1536x2048 píxeles, cámara con una resolución de 13 MP, sensor de huellas dactilares,
acelerómetro, giroscopio y brújula.
Asimismo, a lo largo de los años los usuarios comenzaron a exigir más de sus dispositi-
vos móviles. El entretenimiento, las redes sociales y las aplicaciones de oficina fueron la
principal fuente de estas demandas. Como resultado, los desarrolladores y las empresas
comenzaron a desarrollar diferentes aplicaciones móviles teniendo en cuenta sus caracte-
rísticas especiales. Además, el aumento de la potencia computacional de estos dispositi-
vos permite que estos ejecuten aplicaciones informáticas de alto rendimiento, un aspecto
interesante para los investigadores. En otras palabras, estos dispositivos representan un
poder computacional disponible sin precedentes a nivel mundial que se puede utilizar
para colaborar con la ciencia a través de la ejecución de código intensivo. Otra ventaja
interesante de los smartphones y las tablets es que, en comparación con un dispositivo
móvil de alta gama, como un portátil o una netbook, un teléfono inteligente es capaz de
ejecutar más operaciones computacionales por unidad de batería Rodriguez et al. [2011a].
Sin embargo, como mencionamos anteriormente, el consumo de energía en los dispositi-
vos móviles continúa siendo uno de los problemas más importantes en la investigación
3
en informática móvil. Los ejemplos de evolución de estos dispositivos presentados ante-
riormente muestran que, si bien la capacidad de cómputo ha aumentado rápidamente,
la capacidad de la batería ha aumentado lentamente Paradiso and Starner [2005], Flipsen
et al. [2012], lo cual es un problema de gran impacto cuando hablamos de la ejecución de
código intensivo.
Por lo tanto, esta tesis tiene como objetivo evaluar las capacidades energéticas de los dis-
positivos móviles utilizando diferentes micro-benchmarks comúnmente encontrados en
aplicaciones científicas, y mostrar el impacto en el consumo energético de refactorizacio-
nes de códigos fuente sencillas. Nuestro trabajo se centra en kernels científicos ya que,
actualmente, los dispositivos móviles no son solo dispositivos de conexión/acceso a re-
cursos informáticos externos, sino que también se están convirtiendo en nodos centrales
de infraestructuras computacionales distribuidas en proyectos científicos Murray et al.
[2010], Rodriguez et al. [2011b]. Actualmente, existe un interés creciente en integrar estos
dispositivos en infraestructuras computacionales comúnmente utilizadas en simulacio-
nes como Grids y Clusters Rodriguez et al. [2010, 2011b], Rodríguez et al. [2012a]. Por
ejemplo, Huynh et al. [2011] propone un modelo de computación híbrida en el que los
dispositivos móviles ejecutan secciones semi-intensivas de aplicaciones de simulación de
fluidos y Hirsch et al. [2017] propone un enfoque de scheduling de dos fases para eje-
cutar trabajos con uso intensivo de CPU en dispositivos móviles que combina criterios
novedosos basados en energía con técnicas de robo de trabajos.
1.2. Tesis
Introducir dispositivos móviles como nodos activos en entornos distribuidos Rodriguez
et al. [2014, 2011b] es un tema en el que un nuevo requisito no funcional aparece en pri-
mer plano: el consumo energético. En esta línea, la evaluación y el análisis de buenas
prácticas de programación es un área de investigación novedosa. Entonces, el objetivo
principal de esta tesis es evaluar las capacidades de los dispositivos móviles para eje-
cutar aplicaciones científicas intensivas y, a partir de esta evaluación, derivar pautas de
programación adecuadas para optimizar el consumo de energía centrándose en ciertos
componentes de hardware específicos como CPU y memoria. Este estudio se basa en la
hipótesis de que si los desarrolladores aplican pautas simples al desarrollar aplicaciones
móviles o refactorizar sus aplicaciones existentes, estas aplicaciones serán aplicaciones
reducirán su consumo energético. Como resultado, propondremos un catálogo de refac-
torings que se puede usar en un proceso de refactorización para mejorar el consumo de
energía de las aplicaciones móviles existentes.
Por otra parte, esta propuesta puede tener un impacto importante en otros entornos, co-
mo servidores o aplicaciones móviles de usuario. Consecuentemente la importancia de
este estudio radica en la hipótesis de que las refactorizaciones o prácticas simples pueden
4
resultar en un impacto positivo significativo en el consumo de energía de las aplicacio-
nes Rodriguez et al. [2016a], Rodríguez et al. [2012a], independientemente de la platafor-
ma donde se ejecutan los códigos refactorizados. Resumiendo, este trabajo responderá
tres preguntas principales y dos preguntas adicionales que se desprenden de las prime-
ras:
Q1: ¿Pueden ser refactorizaciones simples útiles para ahorrar energía en aplicaciones
científicas con uso intensivo de recursos computacionales?
Q2: ¿Cuál es el impacto que estas refactorizaciones generan en aplicaciones científicasreales?
Q3: ¿Cuál es el impacto de estas refactorizaciones en el diseño orientado a objetos y lacalidad de la aplicación?
Q4: ¿Cómo impactan estas refactorizaciones en el consumo energético en aplicacionescientíficas en servidores?
Q5: ¿Qué tan adecuadas son estas refactorizaciones para aplicaciones de usuario final?
Metodológicamente, esta tesis doctoral analizará el consumo de energía de diferentes ver-
siones de micro-benchmarks que representan operaciones comunes en aplicaciones cien-
tíficas OO. Existen numerosos trabajos como Cheng-Min et al. [2011], Li and Li [2010a],
Gottschalk et al. [2012, 2013, 2014] que abordan el problema de optimizar el consumo
de energía en aplicaciones móviles; sin embargo, una novedad importante del trabajo
propuesto es la evaluación completa de las pautas que se identifican. En otras palabras,
no solo evaluaremos los resultados individuales para cada grupo de micro-benchmarks
sino que también evaluaremos el impacto de aplicarlos a aplicaciones reales, tanto desde
el punto de vista del consumo de energía como del diseño de la aplicación. Hemos men-
cionado el diseño de la aplicación porque varias prácticas de energía no son compatibles
con las buenas prácticas de diseño OO conocidas, y, como consecuencia, los desarrolla-
dores deben conocer los trade-off de aplicar las prácticas para el ahorro energético.
De manera similar, en el área de Green Computing, hay numerosos trabajos que apun-
tan a reducir el consumo de energía centrándose la mayoría en el nivel de hardware o
plataforma, siendo pocas las investigaciones enfocadas en reducir el consumo energé-
tico a nivel de aplicación. Además de la escasa cantidad de documentos en el área, la
mayoría de ellos presentan algunas limitaciones como las que se observan en el entorno
móvil, especialmente podemos encontrar la falta de evaluación en aplicaciones reales,
objetivos demasiado específicos y la necesidad de una gran capacidad de cálculo para su
aplicabilidad. Como resultado nosotros buscamos desarrollar una investigación comple-
ta teniendo en cuenta las limitaciones de las investigaciones anteriores.
Luego de definir el objetivo principal del trabajo, tenemos que definir algunos aspectos
de nuestro trabajo:
5
¿Qué sistema operativo es el más adecuado para ejecutar nuestros experimentos
según el caso?
¿Qué lenguaje de programación proporcionará un mayor impacto?
¿Cuáles son los principales micro-puntos de referencia en aplicaciones científicas?
Para responder estas preguntas hicimos una investigación exhaustiva antes de comenzar
el diseño de los escenarios de prueba.
En primer lugar, esta investigación se centra en dispositivos Android porque millones
de smartphones, tablets y otros dispositivos móviles utilizan la plataforma Android, y
la plataforma incluye una capa intermedia entre las aplicaciones y el sistema operativo,
organizado en una pila de software extensible/modificable. Además, los smartphones
Android fueron los primeros en la lista de más vendidos en los Estados Unidos en los
últimos años, habiendo crecido exponencialmente. Su parte del mercado en todo el mun-
do fue de 86,8% durante el año 2016, mucho más alto que el de Apple iOS, el segundo
sistema operativo más popular1. Otra razón para usar dispositivos con Android es que
este sistema operativo no restringe a los desarrolladores a ciertas características, es decir,
los desarrolladores pueden administrar diferentes características usando las API y biblio-
tecas, haciendo el desarrollo de aplicaciones más flexibles. Además, los desarrolladores
pueden acceder al código fuente y listas de bugs, lo que no es posible en otros sistemas
operativos de código cerrado como iOS.
Teniendo en cuenta esta decisión, trasladamos esta decisión a los experimentos en servi-
dores optando por ejecutar nuestros experimentos en servidores basados en Linux, espe-
cíficamente en Ubuntu 16.04. Según TOP500 organization2, que informa las estadísticas
de los 500 mejores supercomputadoras del mundo, en noviembre de 2012 469 de estos se
basaron en GNU/Linux, 20 Unix, 7 híbridos, 1 BSD y 3 Windows.
Después de seleccionar el sistema operativo, analizamos Java y Android nativo como los
lenguajes de programación con el objetivo de centrar nuestro trabajo en uno de ellos. Du-
rante la etapa de análisis se tuvieron en cuenta diferentes aspectos como su utilidad para
ejecutar código de alto rendimiento y su popularidad. Finalmente, decidimos usar Java
debido a su popularidad y sus interesantes características; por ejemplo, Java ha sido re-
conocido como un lenguaje útil para desarrollar y ejecutar código de recursos intensivos
por los investigadores Mateos et al. [2011b], Barisone et al. [2001], Taboada et al. [2011].
La gran popularidad de Java para desarrollar aplicaciones HPC es una de las principales
razones para extender este trabajo a los servidores Taboada et al. [2011], ya que facilita la
ejecución de exactamente los mismos micro-benchmarks y aplicaciones.
1http://www.idc.com/prodserv/smartphone-os-market-share.jsp2https://www.top500.org
6
En el siguiente paso, identificamos 8 diferentes operaciones comunes para evaluar: Co-pia de matrices, Creación de Objetos, Acceso a Atributos, Manejo de Strings, Manejo deExcepciones, Uso de Tipos de Dato Primitivos, Recorrido de Matrices y Operaciones Arit-méticas Rodriguez et al. [2016a]. Para cada grupo de micro-benchmarks, programamosal menos dos versiones diferentes que ejecutamos varias veces en diferentes dispositivosAndroid con el fin de obtener generalidad en nuestros resultados. El siguiente párraforesume las razones principales por las cuales estos grupos fueron seleccionados.
En primer lugar, teniendo en cuenta que se han desarrollado diferentes bibliotecas para
uso científico en diversos lenguajes OO como C++ y Java Hofschuster and Krämer [2004],
Papadimitriou et al. [2011], comparamos la mejora del consumo de energía utilizando di-
chas bibliotecas para copiar una matriz en contra de implementar la misma funcionalidad
manualmente.
Además, elegimos la creación de objetos porque los objetos son el foco de la programa-
ción OO, así como su creación es una de las razones para la disminución del rendimiento
de la aplicación. Esta disminución del rendimiento se debe a las costosas tareas de ad-
ministración de memoria que esto implica, por ejemplo, el Garbage Collector en Java o
la eliminación de objetos explícitos en C++ que recuperan la memoria de los objetos no
utilizados. Como resultado, una cantidad excesiva de objetos puede disminuir el rendi-
miento de la aplicación. Por lo tanto, reutilizar un objeto previamente creado podría ser
una buena práctica para ahorrar energía en una aplicación.
El siguiente grupo, Acceso a atributos, se eligió por motivos similares: en la programa-
ción OO, un método es una subrutina asociada a una clase, siendo la llamada a un método
una operación común en aplicaciones OO. Esto nos llevó a analizar el consumo de ener-
gía del acceso a atributos de una clase a través de métodos, utilizados para preservar el
encapsulamiento de objetos, contra la ejecución de la misma funcionalidad sin la llamada
al método.
Con respecto a la manipulación de Strings, la concatenación de Strings es la operación
más frecuente Christensen et al. [2003]. De hecho, existen varios trabajos que investigan
problemas relacionados con la concatenación eficiente de Strings. Por ejemplo, Hermelin
et al. [2008] analiza el problema de cubrir un conjunto de Strings S con un conjunto C de
subcadenas en S (C cubre S si cada cadena en S se puede escribir como una concatenación
de las subcadenas en C). Como resultado, nuestro trabajo evalúa el consumo de energía
de diferentes operaciones para concatenar Strings.
Por lo tanto, las excepciones representan un mecanismo para el manejo de errores de for-
ma correcta y se usan comúnmente en los lenguajes que las soportan. Sin embargo, las
excepciones producen consumos generales que disminuyen el rendimiento de la aplica-
ción. En consecuencia, trabajos como Lee and Jeon [2010] analizan los mecanismos para
eliminar los overheads generales provocados por el manejo de excepciones y nos motivan
a medir el impacto de uso de excepciones en el consumo de energía. En otras palabras,
7
medimos el consumo de energía de diferentes métodos para gestionar un error, como
lanzar una excepción y manejar el error manualmente.
Cuando las aplicaciones usan wrappers para representar datos numéricos se utiliza más
memoria que si utilizaran los tipos de datos primitivos. Esto es porque los tipos de datos
primitivos usan la cantidad mínima de bits necesarios para representar su valor mientras
que los wrappers proveen operaciones particulares además de una estructura interna.
Luego, discutiremos las ventajas en términos de uso de energía del uso de tipos de datos
primitivos contra el uso de wrappers.
Por otra parte, las matrices son una estructura común en el software científico que tienen
numerosos usos matemáticos y computacionales importantes. Por ejemplo, las transfor-
maciones tridimensionales basadas en matrices Barisone et al. [2001] y las multiplicacio-
nes matriciales son núcleos importantes en algoritmos de álgebra lineal. entonces, eva-
luamos el consumo de energía de atravesar una matriz por filas y columnas.
El último grupo se refiere a la precisión al manipular datos numéricos. En cuanto a opera-
ciones aritméticas, históricamente varios estudios Vaidya [1990], Baron et al. [2006], Gur-
ram and Agarwal [2007] han centrado sus esfuerzos en optimizarlas. Dado que la suma
es la operación aritmética más común que los procesadores realizan3, nosotros decidimos
medir el consumo de energía al sumar datos de tipo float, int, double y long.
Después de analizar los resultados de micro-benchmarks (Q1), estudiaremos las guías
para programar estas operaciones comunes en dispositivos móviles de forma eficiente
en términos de energía, analizando también su impacto en aplicaciones científicas reales
(Q2). Sin embargo, como mencionamos anteriormente, seguir estas pautas puede violar
los principios conocidos del paradigma OO y, por lo tanto, una nueva pregunta de in-
vestigación será (Q3): ¿es posible explotar refactorizaciones de código obtenidas minimi-
zando el impacto en la calidad del código según lo estipulado por los criterios de calidad
tradicionales? Luego, analizaremos los resultados de micro-benchmark y la hipótesis so-
bre la calidad del software en diferentes aplicaciones científicas reales. Como extensiones
evidentes y simples, evaluaremos estos experimentos en servidores (Q4), generalizando
los resultados de nuestro trabajo en consumo de energía; y evaluaremos estas refactori-
zaciones propuestas en aplicaciones móviles reales para usuarios (Q5).
Finalmente, la principal contribución de esta tesis serán la guía de buenas prácticas y una
lista de refactorizaciones para desarrollar aplicaciones científicas adecuadas para ser eje-
cutadas en dispositivos móviles consumiendo la menor cantidad de energía posible. Esto
posiciona la contribución no solo en la programación móvil sino también en la informáti-
ca distribuida móvil, donde las aplicaciones distribuidas envían tareas a los dispositivos
en función de su capacidad energética, integrando dispositivos móviles adecuados en
3http://www.mathworks.com/help/fixedpoint/ug/rules-for-arithmetic-operations.html
8
entornos distribuidos como nodos activos. Aplicar nuestras pautas significa ejecutar ta-
reas que son eficientes energéticamente en los dispositivos que dependen de su batería
como fuente de energía. Además, esta investigación doctoral tiene un impacto en Green
Computing, un área cuyo objetivo principal es reducir el consumo de energía, reducir el
uso de materiales peligrosos al fabricar componentes de hardware y promover el recicla-
miento o biodegradación de dichos materiales.
1.3. Organización
Este Capítulo concluye presentando la organización general del trabajo. El Capítulo 2
describe el contexto del trabajo, teniendo en cuenta tanto las tecnologías utilizadas como
las áreas con las cuales el objetivo de este trabajo está directamente relacionado. Especi-
ficamente, el Capítulo 2 introduce en detalle las nociones de desarrollo de software para
dispositivos móviles, acompañadas por las principales características de estos dispositi-
vos y el papel que desempeñan hoy en día específicamente en el desarrollo de aplicacio-
nes científicas.
Además, el Capítulo 3 presenta y discute trabajos afines a nuestra hipótesis y nuestras
contribuciones. Estos trabajos cubren tanto el área de desarrollo de aplicaciones móvi-
les como la integración de dispositivos móviles a estructuras computacionales con fines
científicos. Además se presentan trabajos de ahorro energético en servidores.
Posteriormente, el Capítulo 4 presenta los diferentes grupos de micro-benchmarks queserán utilizados para trabajar con aplicaciones científicas. En este capítulo presentamosuna explicación detallada de cada decisión que se tomó durante el desarrollo de estetrabajo. Estas decisiones no solo se refieren a la elección de los dispositivos, el sistemaoperativo y el desarrollo del lenguaje, sino también a qué grupos de micro-benchmarksy aplicaciones se evalúan y por qué.
Luego, el Capítulo 5 discute la metodología utilizada para los experimentos junto con los
problemas que se tuvieron que enfrentar, particularmente cómo obtener mediciones de
energía precisas. Como consecuencia, presentamos diferentes opciones para sortear estos
problemas junto con la decisión final y su justificación.
Los resultados de los experimentos junto con sus características se presentan en el Capí-tulo 6, donde se agregan el análisis detallado junto con las conclusiones sobre los mismos.El objetivo de este Capítulo es evaluar el impacto en términos de ahorro de energía delas buenas prácticas propuestas y, por lo tanto, validar empíricamente nuestra hipótesisprincipal de investigación.
Finalmente, el Capítulo 7 profundiza las conclusiones que se desarrollaron a partir deltrabajo completo. Además, este último capítulo presenta una breve discusión sobre lostrabajos futuros que se llevarán a cabo continuando con la línea de investigación.
9
10
Capıtulo 2
Background
Este capítulo explica los conceptos principales sobre la construcción de este trabajo. Porlo tanto, hacemos una breve descripción de Android, el sistema operativo elegido parallevar a cabo nuestro análisis y experimentos. Junto con esta descripción, se presenta unresumen del desarrollo de aplicaciones de Android en la Sección 2.2. Finalmente, despuésde la introducción general, los temas importantes asociados a este trabajo se discuten endetalle: el uso de dispositivos móviles para la ejecución de código intensivo, la integra-ción de ellos en las infraestructuras computacionales distribuidas, y la contribución deeste trabajo en el área de Green Computing .
En particular, como el trabajo evalúa aplicaciones científicas ejecutadas en dispositivos
móviles, la Sección 2.3 muestra que es posible ejecutar aplicaciones que requieren una
gran capacidad de cómputo en Smartphones. Como los dispositivos móviles son ade-
cuados para ejecutar tareas intensivas, se pueden integrar en entornos distribuidos como
Grids los cuales se presentan en la Sección 2.4. Este tipo de entorno se presenta porque
nuestra investigación puede contribuir a esa área a través de la generación de pautas
para integrar correctamente dispositivos móviles. Por último, la Sección 2.4 introduce
el concepto de Green Computing. El área de Green Computing busca reducir el impacto
ambiental de las computadoras y los recursos relacionados. Entonces, reducir el consumo
de energía en cualquier dispositivo contribuye directamente con Green Computing.
2.1. Android
Android es un sistema operativo de código abierto diseñado para dispositivos móvilesdesarrollado por Google y basado en un kernel de Linux. Tiene un middleware extensi-ble y aplicaciones de usuario clave. Además, proporciona una tienda de aplicaciones enla que hay más de 2.000.000 de aplicaciones, de las cuales más de dos tercios son gra-tuitas. Esto permite a los usuarios finales personalizar sus dispositivos. Otra forma depersonalizar dispositivos es desarrollar aplicaciones personalizadas utilizando Java, ellenguaje de alto nivel utilizado en Android. Para ejecutar tales aplicaciones, Android usa
11
Figura 2.1: Arquitectura de Android
una máquina virtual especial optimizada para este tipo de dispositivos. Finalmente, An-droid presenta una arquitectura en capas -Figura 2.1- donde cada capa usa los serviciosofrecidos por las anteriores, y ofrece sus propios servicios a las capas superiores.
Los siguientes párrafos presentan una breve descripción de cada una de las capas de laarquitectura de Android:
Linux Kernel: la base de la plataforma de Android es el kernel de Linux. Por ejem-
plo, Android Runtime (ART) se basa en el kernel de Linux para funcionalidades
como el manejo de la memoria y el subprocesamiento. El uso de un kernel de Linux
le permite a Android aprovechar las características claves de seguridad y permi-
te a los fabricantes de dispositivos desarrollar controladores de hardware para un
kernel conocido.
12
Hardware Abstraction Layer (HAL): HAL proporciona interfaces estándar que ex-ponen las capacidades de hardware del dispositivo. La HAL consta de múltiplesmódulos de biblioteca, cada uno de los cuales implementa una interfaz para un ti-po específico de componente de hardware, como la cámara o el bluetooth. Cuandouna API realiza una llamada para acceder a un hardware de un dispositivo espe-cífico el sistema Android carga el módulo de biblioteca para ese componente dehardware particular.
Android Runtime (ART): Para dispositivos con Android versión 5.0 (API nivel 21) osuperior, cada aplicación se ejecuta en su propio proceso y con su propia instanciade ART. ART está diseñado para ejecutar múltiples máquinas virtuales en dispo-sitivos de poca memoria mediante la ejecución de archivos DEX, un formato debytecode diseñado especialmente para Android optimizado para minimizar el usode memoria. Algunas de las principales características de ART incluyen lo siguien-te:
• Compilación Ahead-of-time (AOT) and just-in-time (JIT)
• Optimización de garbage collection (GC)
• Mejor soporte de depuración, incluido un generador de perfiles de muestreodedicado, diagnostico detallado de excepciones e informes de fallas, y la capa-cidad de establecer watchpoints
Antes de Android versión 5.0 (API nivel 21), Dalvik era el la máquina virtual de An-droid. Si la aplicación funciona bien con ART, entonces debería funcionar tambiénen Dalvik, pero puede que no sea cierto lo contrario. Android también incluye unconjunto de bibliotecas de tiempo de ejecución del núcleo que proporcionan la ma-yoría de las funcionalidades del lenguaje de programación Java, incluidas algunascaracterísticas del lenguaje Java 8.
Native C/C++ Libraries: Muchos componentes y servicios centrales del sistemade Android, como ART y HAL, se crean a partir de código nativo que requierebibliotecas nativas escritas en C y C++. La plataforma Android proporciona Javaframework APIs para exponer la funcionalidad de algunas de estas bibliotecas na-tivas a las aplicaciones. Por ejemplo, los desarrolladores pueden acceder a OpenGLES a través del framework de Android Java OpenGL API para agregar soporte pa-ra dibujar y manipular gráficos 2D y 3D en las aplicaciones. Además, cuando losdesarrolladores están implementando una aplicación que requiere código C o C++,pueden usar el Kit de desarrollo nativo de Android (NDK) para acceder a algunasde estas bibliotecas de plataforma nativa desde su código.
Java API Framework: Todo el conjunto de funciones del SO Android está dispo-nible para los desarrolladores a través de API escritas en Java. Estas API formanlos bloques que los desarrolladores necesitan para crear aplicaciones Android quesimplifiquen la reutilización de componentes y servicios centrales y modulares delsistema. Tales bloques incluyen:
13
• Los desarrolladores pueden utilizar un sistema de visualización extensiblespara desarrollar interfaces de usuario en sus aplicaciones, incluyendo listas,tablas, cuadros de texto, botones e incluso un navegador web.
• Un administrador de recursos, que proporciona acceso a recursos tales comográficos y archivos de diseño.
• Un administrador de notificaciones que permite que todas las aplicacionesmuestren alertas personalizadas en la barra de estado.
• Un administrador de actividades que gestiona el ciclo de vida de las aplicacio-nes y proporciona una pila de navegación entre actividades común.
• Content Providers que permiten a las aplicaciones acceder a datos de otrasaplicaciones, como acceder a la información de la aplicación Contactos, o com-partir sus propios datos.
Los desarrolladores tienen acceso completo a las mismas APIs que utilizan las apli-caciones del sistema Android.
System Apps: Android viene con un conjunto de aplicaciones para correo electróni-co, mensajes SMS, agenda, navegación por Internet, contactos, etc. Las aplicacionesincluidas con la plataforma no tienen un estado especial comparado con las aplica-ciones que el usuario elige instalar. Por lo tanto, una aplicación de terceros puedeconvertirse en el navegador web predeterminado del usuario, SMS Messenger oincluso en el teclado predeterminado (se aplican algunas excepciones, como la apli-cación de Configuración del sistema).
Las aplicaciones del sistema funcionan como aplicaciones para los usuarios y co-
mo proveedoras de capacidades clave a las que los desarrolladores pueden acceder
desde su propia aplicación. Por ejemplo, si una aplicación desea entregar un mensa-
je SMS, los desarrolladores no necesitan construir esa funcionalidad ellos mismos,
sino que pueden invocar cualquier aplicación de SMS que ya esté instalada para
entregar un mensaje.
Además de estas características técnicas, es importante destacar que la popularidad deAndroid ha crecido exponencialmente1 desde su lanzamiento debido a que hace a losdispositivos más adaptables a las necesidades de los usuarios y, en consecuencia, los ha-ce más útiles. Además, debido a que Android es open source, los desarrolladores puedencrear una experiencia móvil con personalización única de dispositivos. Además de es-to, Android ofrece herramientas para crear aplicaciones. Las herramientas de desarrollopara Android proporcionan un IDE completo para Java con funciones avanzadas parael desarrollo de aplicaciones móviles. Con el IDE, los usuarios pueden desarrollar apli-caciones para cualquier dispositivo Android o crear dispositivos virtuales que emulencualquier configuración de hardware compatible para probar sus aplicaciones.
Finalmente, la API de Android tiene diferentes versiones disponibles que han sido desa-rrolladas de acuerdo a las necesidades emergentes. Por lo tanto, los cambios realizados
1http://www.idc.com/prodserv/smartphone-os-market-share.jsp
14
entre versiones generalmente son nuevas funcionalidades o reemplazos de funcionali-dades anteriores. Estas versiones actualizadas están diseñadas para ser compatibles conversiones anteriores, dejando las funcionalidades antiguas en desuso pero no elimina-das. Solo en un pequeño porcentaje de casos, algunas funcionalidades de la API fueroneliminadas. Cada versión de Android admite exactamente un nivel de API, que admiteimplícitamente todos los niveles previos de APIs. Las aplicaciones describen en el An-droidManifest los niveles mínimo y máximo de API en las que se pueden ejecutar, asícomo el nivel de la API preferida para la que están diseñadas.
Figura 2.2: Versiones de Android
2.2. Aplicaciones Android
Desde la API 21, cada aplicación de Android se ejecuta en su propio proceso de Linux.Este proceso se crea cuando parte del código de la aplicación necesita ejecutarse, y seguiráejecutándose hasta que ya no sea necesario o el sistema necesite memoria para que lautilicen otras aplicaciones.
Los desarrolladores de aplicaciones deben comprender las diferencias entre los compo-nentes de una aplicación (en particular, Activity, Service, y BroadcastReceiver) y su impactoen la vida del proceso de la aplicación. El hecho de no utilizar estos componentes correc-tamente puede provocar que el sistema mate los procesos de las aplicaciones mientrasrealizan una tarea importante.
Para comprender cómo funcionan las aplicaciones de Android, explicaremos brevemen-
te algunos conceptos clave del modelo asociado con ellos y sus componentes: Activity,
Service y Task; Intents, IntentFilters, BroadCastRecivers y PendingIntents; ContentProviders y
ContentResolvers; y AndroidManifest.
Activity: Las Activity son la parte visible de las aplicaciones. Esto significa que unActivity es la interfaz con la que el usuario interactúa. Además, es importante men-cionar que un Activity no es necesariamente un proceso, incluso las Activity y losService pueden compartir procesos. Además, una aplicación puede contener múl-tiples Activity. En este caso, cada Activity debe diseñarse teniendo en cuenta unaacción del usuario específica. Por ejemplo, una aplicación de agenda de contactospuede tener una Activity que muestre la información detallada de un contacto. Sinembargo, no es necesario que todas las Activity se definan en la misma aplicación:
15
una Activityd puede iniciar Activity que existen en otras aplicaciones del dispositi-vo mediante el uso de Intents.Por último, las Activity se pueden encontrar en diferentes estados durante su ejecu-ción. Estos estados junto con sus transiciones se presentan en la Figura 2.3.Para navegar por las transiciones entre los estados del ciclo de vida de la Activity, laclase Activity proporciona un conjunto central de seis llamadas a métodos: onCrea-te(), onStart(), onResume(), onPause(), onStop() y onDestroy(). El sistema invoca cadauna de estas llamadas cuando una Activity ingresa a un nuevo estado. Primero,cuando la Activity comienza, está en el estado starts. Durante esto se llama al méto-do OnCreate(). En este se deben definir las diferentes vistas y la información nece-saria para llevar a cabo la creación de la Activity. Luego, el siguiente método que seejecuta es OnStart(), que se encarga de poner la Activity visible para el usuario. Unavez que la Activity está visible, comienza a interactuar con el usuario ejecutando elmétodo OnResume(), llegando al estado starts. Finalmente, una vez que la Activityse está ejecutando se puede pausar cuando se debe ejecutar otra actividad. En esecaso la primera Activity ejecuta el método OnPause(), que debe cumplir sus respon-sabilidades rápidamente antes de que se produzca el cambio de Activity. Durantela ejecución de este método es necesario guardar la información del estado actualde la Activity pausada y detener las animaciones, entre otras funciones. Después depausar una Activity, el usuario puede reiniciarla volviendo a llamar implícitamenteal método OnResume() o el SO puede detener la Activity porque no ha estado visibledurante un largo período de tiempo. En el segundo caso, se ejecuta el método OnS-top(). Después de detener la actividad, a) se puede volver a hacer visible medianteel método OnRestart(), que a su vez llama al método OnStart() nuevamente, o b) sepuede destruir definitivamente mediante el método OnDestroy().
Service: Los Service son componentes de la aplicación que no tienen interfaz deusuario. Estos Service, a diferencia de las Activity, se pueden ejecutar en segundoplano. Como en el caso de las Activity, los Service tienen diferentes estados y transi-ciones, como se muestra en la Figura 2.4. Además, los estados de un Service varíande acuerdo con el método a través del cual fueron creados: startService() o bindSer-vice(). A continuación, se incluye un resumen de los estados en los que se puedeencontrar un Service. El primer caso de análisis es aquel en el que se ejecuta unservicio mediante una llamada al método startService(). Cuando se realiza esta lla-mada, el SO recupera el Service y, en el caso de que el servicio no se haya creadopreviamente, llama al método onCreate(). El siguiente paso es la llamada al méto-do onStartCommand(Intención,int,int). El Service continuará ejecutándose desde estemomento hasta que se llame al método Context.stopService() o stopSelf().Por otro lado, los desarrolladores pueden crear y obtener una conexión a un Ser-vice utilizando el método Context.bindService(). Si el Service no se creó previamente,este método lo crea llamando al método onCreate(), pero sin llamar al método onS-tart(). Luego, el cliente recibe un objeto IBinder que define una dependencia entrela aplicación y el Service. Esto permite al cliente hacer llamadas al Service a travésdel método onBind(Intent). Este Service continuará ejecutándose mientras la cone-xión continúe o se invoque el método onUnbind(). Finalmente, el Service se destruyemediante el método onDestroy().Finalmente, resaltamos que tanto Activity como Service no son sinónimos de proce-sos. De hecho, varios Service y Activity pueden compartir el mismo proceso..
16
Figura 2.3: Ciclo de vida de una Activity
17
Figura 2.4: Ciclo de vida de un Service
18
Task: Una tarea es una colección de actividades con las que los usuarios interactúancuando realizan un determinado trabajo. Las Activity se organizan en una pila en elorden en que se abre cada Activity. Por ejemplo, una aplicación de correo electró-nico puede tener una Activity para mostrar una lista de mensajes nuevos. Cuandoel usuario selecciona un mensaje, se abre una nueva Activity para ver ese mensaje,esta nueva Activity se agrega a la pila. En caso de que el usuario presione el bo-tón Back, esa nueva actividad finaliza y sale de la pila. Los usuarios deben tenerespecial cuidado con las tareas porque cuando tienen varias tareas ejecutándoseel sistema puede destruir algunas tareas para recuperar memoria por ejemplo. Enconsecuencia, el estado de las tareas que se destruyeron puede perderse.
Intent: Los Intent tienen por objetivo iniciar Activity, Service o BroadcastReceiversrealizando operaciones vinculantes en tiempo de ejecución. Cada Intent tiene unaestructura de datos donde se realiza una descripción abstracta de una operación.Por eso, la entrega de estos objetos se realiza de diferentes formas según el tipode componente que se active. En el caso de las Activity, el Intent se pasa a Con-text.startActivity() o Activity.startActivityForResult() para crear una Activity u obte-ner una Activity existente. Al resolver el Intent se puede hacer de manera explícitao implícita. En el caso de Intent explícito, el componente receptor se designa direc-tamente utilizando su nombre. Dado que los nombres de los componentes de otrasaplicaciones generalmente no son conocidos por los desarrolladores, estos tipos deIntent se utilizan principalmente en la comunicación interna de cada aplicación. Porotro lado, los Intent implícitos tienen el nombre del componente en blanco, ya queno se conoce. Este tipo de Intent generalmente se usa para activar componentes enotras aplicaciones. En este caso, es necesario que Android determine el mejor com-ponente para manejar el Intent implícito. Esto se hace comparando los contenidosde Intent con los de los IntentFilters, que son componentes asociados con aquellosque pueden resolver Intents.
IntentFilter: Activity, Service y BroadcastReceiver pueden tener uno o más IntentFil-ters para informar al sistema qué tipo de Intent pueden manejar. Cada IntentFilterdescribe las características del componente que recibir y manejar cierto tipo de In-tent. A través de estos IntentFilter, los Intent implícitos se pueden conectar con elcomponente correspondiente. Esta es la razón por la cual cada componente tieneun IntentFilter para cada trabajo que puede realizar. En la mayoría de los casos, losIntentFilter no están definidos en el código de Java, sino que están configurados enel AndroidManifest como elementos <intent-filter> porque Android debe conocer lascapacidades de los componentes antes de crearlos. La única excepción son los In-tentFilter utilizados por los BroadcastReceiver que pueden registrarse dinámicamentea través del método Context.registerReceiver().
BroadcastReceiver: Es un tipo de componente responsable de responder a los anun-cios de difusión. Estos anuncios pueden ser emitidos por el SO o por una aplicaciónen particular. En el primer caso se pueden encontrar anuncios como batería baja,mientras que el segundo caso podrían ser anuncios como aplicación o archivo des-cargado, utilizados para notificar a otras aplicaciones sobre algún elemento o datosque están disponibles para su uso.
PendingIntent: Es un contenedor de Intents que es responsable de compartir permi-
19
sos. Es decir que una aplicación puede otorgar permisos a otra aplicación a travésde estos objetos. Esto significa que una aplicación puede crear un PendingIntent paraotro componente y este último puede ejecutarlo como si fuera la aplicación original.
ContentProvider: Es el componente responsable de compartir datos persistentes através de aplicaciones proporcionando mecanismos para definir la seguridad de losdatos. Básicamente, un ContentProvider recibe una solicitud del cliente, la resuelvey devuelve los resultados. Un ContentProvider se identifica mediante una URI y susconsultas son similares a las consultas SQL. En particular, Android incluye Content-Providers que administran información como vídeo, audio, imágenes e informaciónde contactos
AndroidManifest: El archivo AndroidManifest.xml debe estar presente en todas lasaplicaciones de Android y contiene información esencial de la misma. Siguiendociertas pautas, este archivo especifica la asignación de procesos a las Activity y alos Service. Además, indica el paquete Java de la aplicación, describe los principa-les componentes de la aplicación, presenta sus capacidades y las clases que ejecuta,informa los permisos que necesita, declara los permisos que otras aplicaciones de-ben tener para interactuar con los componentes de la aplicación, indica la versiónde Android que el dispositivo necesita para ejecutar la aplicación y enumera lasbibliotecas requeridas por la aplicación.
Después de hacer una introducción a los componentes de las aplicaciones de Android,
presentaremos sus características generales. Las aplicaciones de Android están escritas
principalmente en Java porque es el lenguaje de alto nivel de Android. Sin embargo, es-
tas aplicaciones no se distribuyen como bytecode de Java, sino que se distribuyen como
bytecode especial. Para desarrollar aplicaciones los desarrolladores de Android deben
tener ciertos requisitos básicos de software como Java y AndroidStudio. En particular,
los desarrolladores deben tener el Kit de desarrollo de software de Android (SDK)2. En
particular, un SDK es un conjunto de herramientas de desarrollo de software que per-
mite la creación de aplicaciones particulares para un determinado paquete de software,
plataforma de software, hardware, sistema operativo, entre otros. En este caso, el An-
droid SDK proporciona las bibliotecas de la Interfaz de programación de aplicaciones y
las herramientas de desarrollo necesarias para crear, probar y depurar aplicaciones de
Android.
2.3. HPC en Smartphones
El área de computación de alto rendimiento (HPC -High Performance Computing-) escentral para la investigación de problemas complejos más allá de la informática, donde
2http://developer.android.com/sdk/index.html
20
los usuarios más comunes de HPC son investigadores científicos, ingenieros e institu-ciones académicas que necesitan un gran poder de cómputo. Para lograr el objetivo deproporcionar herramientas y soluciones a problemas complejos, HPC se basa en tecnolo-gías computacionales como clusters, supercomputadoras y cómputo paralelo. Además,la ejecución de HPC se puede llevar a cabo en entornos informáticos distribuidos talescomo Grids en los que los nodos deben ser capaces de ejecutar código computacionalintensivo para complementar/reemplazar supercomputadoras costosas y centralizadas.
Entonces, para introducir un dispositivo móvil en un entorno distribuido es necesario
demostrar que son capaces de ejecutar tareas intensivas. [Rodríguez et al., 2012b] mos-
tró que los smartphones son capaces de ejecutar código computacional intensivo incluso
cuando no fue diseñado para este tipo de dispositivo específicamente. En [Rodríguez
et al., 2012b] se usaron cinco benchmarks (PrimeBench, FFTBench, HanoiBench y Sieve-
Bench) para realizar las pruebas en cinco dispositivos diferentes (Dell Inspiron, Samsung
N150, ViewPad 10s, Nexus One y Samsung I5500). Las pruebas se ampliaron luego mi-
diendo el rendimiento de varios micro-benchmarks tales como la asignación de valores
de atributos y la creación de objetos, entre otros. En otras palabras, se comprobó empíri-
camente que los dispositivos móviles son adecuados para la ejecución del código HPC.
Específicamente, [Rodríguez et al., 2012b] muestra que los dispositivos móviles pueden
ejecutar una cantidad significativa de código intensivo antes de agotar su batería. En par-
ticular, en comparación con los dispositivos móviles contemporáneos de alta gama, como
notebooks o netbooks, un smartphone es capaz de ejecutar más operaciones computacio-
nales por unidad de batería. Por lo tanto, proponer buenas prácticas que permitan la
adaptación de códigos intensivos para optimizar el uso de los recursos limitados de los
dispositivos móviles podría reducir la brecha entre la ejecución en dispositivos tradicio-
nales y la ejecución en dispositivos móviles, así como también minimizar el consumo de
energía. Como nota al margen, cada propuesta para HPC es una propuesta interesante
para ser evaluada en aplicaciones de usuario final que tienen un uso elevado de CPU o
memoria.
Actualmente, trabajos como Pramanik et al. [2017] avalan esa hipótesis con las estadís-
ticas del potencial de computación de los smartphones. Los autores basaron su inves-
tigación en el hecho de que en un país como India muchas organizaciones no pueden
tener una supercomputadora. Los autores argumentan que el poder de computación de
los smartphones puede proporcionar la potencia informática equivalente a una super-
computadora moderna sin incurrir en altos costos.
2.4. Mobile Grids
De acuerdo con Foster and Iamnitchi [2003], un Grid es un sistema que coordina recursosdistribuidos y utiliza protocolos standard, abiertos y de uso general, y tiene interfacesque confieren una calidad de servicio no trivial. Este término nació debido a la existen-
21
cia de organizaciones que requerían una gran capacidad computacional para lograr susobjetivos pero que no podían obtener una supercomputadora. Como resultado, estas or-ganizaciones colaboraron compartiendo sus recursos de bajo costo y logrando un granpoder computacional equivalente o superior al de una supercomputadora.
Estos entornos distribuidos tienen características particulares. La primera característica
de un Grid es que los recursos están en diferentes lugares e interconectados a través de
una red, generalmente Internet. Por otro lado, la coordinación de estos recursos implica
que no existe una relación jerárquica. En consecuencia, dado que no debería haber un
control centralizado de los recursos, cada recurso podría basarse en diferentes SO. Por
lo tanto, los protocolos abiertos son necesarios para garantizar la interoperabilidad de
dichos sistemas.
La extensión de Grid Computing a dispositivos móviles ofrece una serie de ventajas Ro-
driguez et al. [2011b]. En primer lugar, los dispositivos móviles tienen una amplia gama
de sensores (micrófono, sensores de presión, etc.) que pueden compartirse. Estos sensores
permiten a los investigadores obtener y procesar datos de forma inmediata en situacio-
nes en las que antes era imposible realizarlos con dispositivos fijos. Como resultado, el
concepto de Grid puede llegar a lugares que eran inaccesibles como un área despoblada
(montaña, desierto). Este tipo emergente de sistemas Grid, que usan dispositivos móvi-
les, se conoce como Mobile Grid Li and Li [2010b].
Sin embargo, al extender el concepto de Grids a dispositivos móviles, el código fuente
de la aplicación debe adaptarse para su ejecución en este tipo de dispositivos con re-
cursos limitados. Particularmente, grandes secciones de código no pueden ejecutarse en
dispositivos móviles debido a su volatilidad y su autonomía energética. Entonces, es im-
portante lograr una refactorización correcta de las diferentes tareas que ejecutará el Grid
para obtener un uso óptimo de los recursos disponibles. En otras palabras, si las tareas
consumen grandes cantidades de energía, es posible que los dispositivos no terminen
una gran cantidad de ellas.
2.5. Green Computing
Green Computing es el uso ambientalmente responsable de las computadoras y los recur-
sos relacionados. Independientemente del entorno, la investigación de alto rendimiento
en informática se ha centrado tradicionalmente en la ejecución de tareas lo más rápido
posible. Sin embargo, toda esta investigación está siendo repensada para agregar eficien-
cia energética a la lista de factores críticos a considerar en el área de HPC, además del
rendimiento Basmadjian et al. [2015]. Se han llevado a cabo investigaciones que abarcan
la conocida pila de tres capas que comprende hardware (por ejemplo, adición de núcleos),
plataforma (por ejemplo, mejores planificadores de nivel de middleware) y aplicaciones
(por ejemplo, modelos de programación paralelos). De hecho, las estadísticas sobre el im-
22
pacto de la energía en los costos económicos en los Data Centers son impresionantes. Por
ejemplo, el consumo de energía representa el 15 por ciento de los gastos operacionales
totales Greenberg et al. [2008]. En 2007, la energía consumida en los centros de datos en
Europa Occidental fue de 56 TWh y aumentará a más de 100 TWh por año en 2020 Eu-
ropean Commission [2009]. Además de estas consecuencias, el manejo ineficiente de la
energía tiene consecuencias ecológicas negativas debido a las emisiones de CO2.
En respuesta, hay muchas propuestas Basmadjian et al. [2015] para aumentar la eficiencia
energética en los Data Centers. En el nivel del hardware, existen esfuerzos para mejorar
las CPU, los elementos de almacenamiento/red y la mecánica de los controladores de
refrigeración/calor. Dichas prácticas incluyen la implementación de CPU, servidores y
periféricos con uso eficiente de la energía, así como la reducción del consumo de recursos
y la eliminación adecuada de los desechos electrónicos (e-waste).
Con la creciente demanda de aplicaciones de software más complejas, las Tecnologías de
la Información y la Comunicación (TIC) han tenido un impacto negativo en el medioam-
biente debido a su creciente consumo de recursos y energía. El efecto de las TIC en el
desarrollo sostenible, especialmente en el software, es un tópico importante hoy en día
en Green Computing.
Recientemente se han realizado muchas investigaciones para obtener Green Software Ar-
dito and Morisio [2014], Pinto et al. [2015], Sahin et al. [2012], Dhaka and Singh [2016],
Hasan et al. [2016]. Algunos esfuerzos se centran en la creación de Green Software y
otros en la estructuración de procesos de diseño de software para ayudar a todos los in-
teresados en el desarrollo de Green Software. Otros enfoques se centran en la creación
de herramientas de software que miden el efecto del software en el medio ambiente y
el efecto de los entornos de desarrollo de aplicaciones en el software en términos de efi-
ciencia energética. Finalmente, hay trabajos que hacen hincapié en el SO para ayudar a
controlar el consumo de energía de las aplicaciones
2.6. Resumen
En este capítulo, proporcionamos la información básica necesaria para ayudar a los lecto-
res a tener una comprensión básica del área del problema de investigación y para promo-
ver la calidad general de nuestros análisis y conclusiones. Esta información proporciona
al lector el contexto esencial necesario para comprender el problema de investigación y
su importancia.
A lo largo de este capítulo presentamos el entorno en el que se presentará nuestro tra-
bajo. Todos los conceptos detallados (sistema operativo Android, aplicación Android,
HPC en smartphones, redes móviles y Green Computing) son necesarios para compren-
der el trabajo completo. Android es el SO seleccionado para ejecutar los experimentos
23
y, como consecuencia, necesitamos saber cómo desarrollar correctamente una aplicación
de Android. A medida que proponemos refactorizaciones para aplicaciones científicas,
mencionamos algunos trabajos que respaldan la hipótesis de que los dispositivos mó-
viles son dispositivos útiles para ejecutar aplicaciones HPC. Las dos últimas Secciones
(Sección 2.4 y Sección 2.5) presentan dos áreas importantes en las que nuestro trabajo
contribuirá colaborando para mejorar sus principales objetivos.
24
Capıtulo 3
Trabajos Relacionados
A lo largo de este capítulo, presentamos los trabajos relacionados que determinan el es-tado del arte en el área. En los últimos años, se han realizado esfuerzos para mejorar eldesarrollo de aplicaciones intensivas para aprovechar los recursos limitados y las nuevascapacidades de los dispositivos móviles. Una primera área relevante es Offloading. Offloa-ding es una técnica que promueve la transferencia dinámica de tareas intensivas de unaaplicación desde un dispositivo con recursos limitados a uno o más servidores que tienenmayor poder computacional, dando la ilusión de una gran potencia de computación enel dispositivo móvil. Esta técnica ahorra energía en los dispositivos móviles y logra unaejecución de código intensivo.
Desde entonces, la concepción tradicional sobre el valor de los dispositivos móviles ha
evolucionado para introducirlos como parte activa de las infraestructuras informáticas
intensivas. La experiencia ha demostrado que la ejecución de código intensivo en dis-
positivos móviles sin enviar el código a servidores externos es viable Rodriguez et al.
[2011b]. Por lo tanto, los recursos de los dispositivos móviles se ofrecen como recursos
para entornos informáticos distribuidos Rodriguez et al. [2011b], Murray et al. [2010].
Como resultado, en las siguientes Secciones describimos numerosos trabajos que han
centrado sus esfuerzos en la introducción de dispositivos móviles en infraestructuras
científicas, así como en el desarrollo de aplicaciones que aprovechan sus recursos limita-
dos. El resto de este Capítulo está organizado de la siguiente manera. En la Sección 3.1
se presentan y discuten trabajos relacionados con la técnica de Offloading. Después de
eso, la Sección 3.2 detalla las investigaciones cuyo objetivo principal es la introducción
de dispositivos móviles como proveedores de recursos en entornos computacionales dis-
tribuidos. En este tipo de entornos computacionales, el código fuente de las aplicaciones
debe optimizarse para consumir la menor cantidad de energía posible, ya que los dispo-
sitivos móviles dependen de su batería como suministro energético. Luego, la Sección 3.3
presenta trabajos que proponen técnicas para disminuir el consumo de energía modifi-
cando el código fuente de la aplicación. Finalmente, la Sección 3.4 presenta un resumen
25
de los trabajos analizados, los problemas abiertos y explica la relación de nuestro trabajo
con los trabajos presentados en este documento.
3.1. Offloading
La popularidad de los dispositivos móviles y la evolución de sus componentes de hard-ware ha llevado a los usuarios a esperar el mismo rendimiento de los dispositivos móvilesque de los dispositivos fijos. Sin embargo, los dispositivos móviles tienen recursos limita-dos que representan un desafío significativo para cumplir este objetivo. Por lo tanto, unasolución ampliamente utilizada en este contexto es una técnica llamada Offloading, queconsiste en delegar la ejecución de partes de una aplicación a otros dispositivos fijos [Sha-rifi et al., 2011]. Como resultado, esta técnica produce la ilusión de un procesamiento in-tensivo en el dispositivo junto con un mínimo consumo de energía. Básicamente, Offloa-ding reduce el consumo de energía en el dispositivo móvil y el tiempo de ejecución de lasaplicacioness mediante la delegación de la ejecución de la aplicación a entornos compu-tacionales como Clouds o servidores individuales en una modalidad cliente-servidor. Sinembargo, esta solución tiene algunas restricciones que afectan su usabilidad Kristensen[2010] (por ejemplo, los usuarios generalmente tienen que pagar por usar los serviciosde Clouds y los dispositivos móviles deben estar conectados a Internet). Luego, es ne-cesario analizar en qué situaciones aplicar Offloading es razonable. Esto significa que esimportante determinar cuándo Offloading podría ahorrar batería o reducir el tiempo deejecución sin aumentar excesivamente el uso de la red. En esta Sección presentamos tra-bajos relevantes que analizan cómo evaluar cuándo es conveniente aplicar Offloading. Enprimer lugar, la Tabla 3.1 resume los trabajos sobre Offloading utilizando 13 columnas,delas cuales se explican las columnas no triviales en los párrafos siguientes:
Táctica: Refiere a la táctica o criterio usado para evaluar cuando una tarea deberíaser ejecutada en un dispositivo externo.
Objetivo: Es el aspecto/cualidad que se desea optimizar.
Granularidad: Es una métrica de software que intenta cuantificar el tamaño de loscomponentes individuales que componen un sistema de software. Los componen-tes grandes (es decir, los que incluyen mucha funcionalidad) se denominan común-mente de granularidad gruesa, mientras que los componentes que proporcionanpoca funcionalidad se denominan generalmente de granularidad fina. Además, losOffloaders pueden trabajar con granularidades específicas.
Offloading restricicones: Son las características básicas que una tarea debe cumplirpara poder ser ejecutada en otro dispositivo. Si una tarea específica no cumple conestas características, no puede ser un candidata para ser enviada. Algunas de es-tas características se relacionan con el estado de la red (por ejemplo, un mínimo deancho de banda disponible es necesario o un máximo de latencia es tolerable), fide-lidad (por ejemplo, la fiabilidad del resultado debe estar por encima de un umbraldeterminado), tiempo de ejecución (por ejemplo, la tarea debe tener un mínimo detiempo de ejecución), etc.
26
Tipo de subrogados: Representa el tipo de subrogados que se utilizan para ejecutarlas tareas. Un subrogado es una entidad informática que se hace cargo del trabajocomputacional de alguna funcionalidad de una aplicación móvil. Un cliente es undispositivo que necesita algún software especial o características y configuraciónpara ser parte del sistema, mientras que una máquina virtual (VM) es una simula-ción de un sistema específico y se puede ejecutar en cualquier sistema. (Figura 3.1).
Tipo: Define el tipo de Offloader de acuerdo al momento en que se toman las deci-siones. Las decisiones se pueden tomar antes de la ejecución de la aplicación (está-ticas) o durante la ejecución de la aplicación (dinámicas).
Deployment de tareas: Indica la táctica utilizada para comunicar subrogados, ser-vidores y clientes.
Esfuerzo de desarrollo: Indica cuánto esfuerzo se necesita para usar el Offloaderen el software. Las categorías son: modificación de clases y métodos (alto), modi-ficación de la aplicación/clase principal pero no modificación de clases y métodosinternos (medio) o simplemente realizar alguna configuración sin modificar el có-digo de la aplicación (bajo).
Como se muestra en la Tabla 3.1 hay muchos factores que se deben considerar para de-terminar si es conveniente enviar una tarea a ser ejecutada en otro dispositivo. Primero,las tareas deben identificarse antes de enviarse. En particular, es necesario identificar quétareas están vinculadas a los recursos del dispositivo móvil local porque estas tareas no sepueden ejecutar en otro dispositivo. Por ejemplo, si una tarea utiliza el acelerómetro deldispositivo, sería imposible ejecutarla en otro dispositivo. Además, una evaluación de lasrelaciones de tarea podría ser necesaria. En total, el proceso de detección debe clasificarlas tareas en dos grupos principales: tareas descargables (aquellas que califican para serenviadas a otros dispositivos para su ejecución) y tareas no descargables (aquellas quesólo pueden ser ejecutadas en el dispositivo móvil).
Además, el Offloader debe evaluar si la ejecución remota de tareas descargables mejo-
ra la ejecución local. Una forma de evaluar si la descarga es beneficiosa es a través de
la evaluación del tiempo de ejecución de la tarea. Para esta evaluación es necesario te-
ner en cuenta el tiempo de ejecución (TE), la cantidad de código a transmitir (CT), el
número de bytes utilizados para recibir el resultado (DR), el ancho de banda de trans-
misión (TBW) y el ancho de banda de la red de recepción (BWR). Con esta información,
los desarrolladores pueden calcular el tiempo necesario para descargar el código con la
fórmula: To f f loading = CT/TBW + DR/BWR+ TE. Esta fórmula muestra que la descarga
es conveniente cuando el tiempo estimado de ejecución en el dispositivo móvil (MTE)
es mayor que To f f loading (MTE > To f f loading) Sharifi et al. [2011]. En un caso análogo, los
desarrolladores pueden usar el consumo de energía para determinar si realizan la des-
carga o no. Al igual que la evaluación del tiempo, la evaluación del consumo de energía
tiene una limitación: el consumo de energía de la aplicación varía según la plataforma
y los recursos utilizados [Flinn et al., 2002]. También, la evaluación consume recursos y,
como consecuencia, consume energía y necesita tiempo para ejecutarse. Como resultado,
27
Paper Año Táctica Objetivo GranularidadOffloading
restricciones
Tipo de
subro-
gado
TipoDeployment
de tareas
Esfuerzo de
desarrolloTest cases
Flinnet al.
[2002]2002
History-based
Latencia/Perfor-
mance/E-nergía
Fina Fidelidad Clientes Estática RPC Alto
Speechrecognition,
Latex documentpreparation
systemBalanet al.[2007,2002]
2002History-
based
Latencia/Perfor-mance
Fina Fidelidad/ Red Clientes EstáticaRPC/
wrapperMedio
Face Recognizer,Text to speech
Goyaland
Carter[2004]
2004 SiemprePerformance/
EnergíaGruesa
Seguridad/Fidelidad
VM Estática URL BajoSphinx SpeechRecognition,Data mining
Suand
Flinn[2005]
2005 Siempre Performance Gruesa Red VM EstáticaServidor y
proxyBajo
Speechrecognizer,
Remote desktop
Cuervoet al.
[2010]2010
Profile-based
Energía FinaCiclos de CPU/
RedClientes Dinámica RPC Bajo
Chess game,Face recognition
Kristensen[2010]
2010Dual
profileLatencia Gruesa
Red/ Tiempode ejecución
Clientes Dinámica RPC BajoImage
manipulationAbebe
andRyan[2012]
2012 Grafos Performance IndependienteRecursos dedispositivo/
RedClientes Dinámica - Bajo
NASA-WWJ,Hospital
Simulator
Verbelenet al.
[2012]2012
History-based
Performance/Energía
Fina
Recursos dedispositivo/Tamaño deargumentos
Clientes Dinámica Proxy AltoPhoto editing,
Chessapplication
Zhanget al.
[2012b]2012
Grafos yhistory-based
Performance Fina
Recursos dedispositivo/Dependencia
de tareas
Clientes Dinámica Proxy NingunoLinpack, Chessgame, 3D car
game
Cuadro 3.1: Resumen de Offloaders
28
el momento y la complejidad de la decisión es un tema de discusión e investigación en
esta área. Finalmente, en los párrafos siguientes discutimos una variedad de propuestas
relacionadas para implementar un Offloader para varios dispositivos móviles que usan
diferentes criterios para determinar qué tareas descargables deberían descargarse real-
mente.
Por último, las siguientes Subsecciones se dividen en dos áreas principales: enfoques
orientados al rendimiento y enfoques orientados a la energía. Esta clasificación es para
facilitar la comprensión de la gran cantidad de trabajos que se presentan en esta área.
Se eligió este orden para desarrollar las obras porque, cronológicamente, las primeras
investigaciones se centraron en mejorar el rendimiento de las aplicaciones. Además, los
enfoques de rendimiento son trabajos interesantes que podrían evaluarse para reducir el
consumo de energía en el dispositivo móvil.
3.1.1. Enfoques orientados a la performance
En este contexto, una de las primeras propuestas para manejar el Offloading es Spec-tra [Flinn et al., 2002]. Spectra se centra en la reducción de la latencia y el consumo deenergía, teniendo en cuenta la fidelidad, que se define como la fiabilidad de un resultadode la tarea (la fiabilidad de la respuesta del subrogado). Para medir el consumo de ener-gía y el tiempo de ejecución, Spectra calcula los recursos necesarios para ejecutar la tareaen un dispositivo. Esta estimación es una función basada en un perfil histórico de aplica-ciones, calculado utilizando un modelo de regresión lineal. Además, Spectra monitoreael comportamiento de la aplicación, modela el uso de recursos y predice las necesidadesfuturas de recursos. Por lo tanto, Spectra tiene monitores de recursos que miden la dis-ponibilidad de recursos locales y remotos, pero que a su vez consumen varios recursospara monitorizar y realizar los cálculos necesarios. La ecuación utilizada por Spectra paradecidir dónde se debe ejecutar la tarea se basa en la configuración del usuario. El usua-rio determina el peso de diferentes aspectos (tiempo, energía y fidelidad). Sin embargo,Spectra no está diseñado para admitir la ejecución paralela. Otra desventaja de este Of-floader es el hecho de que los comandos utilizados para la comunicación entre Spectra yla aplicación deben introducirse manualmente en el código de la aplicación.
Reducir el esfuerzo de los desarrolladores es una característica importante y deseablepara los Offloaders. En consecuencia, se propuso Chroma [Balan et al., 2007, 2002], quesubsume la funcionalidad de Spectra e intenta mejorarlo reduciendo el esfuerzo de losdesarrolladores. Para hacer esta mejora, Chroma proporciona una adaptación de códigosemiautomática. Además, en Spectra el soporte para monitorear recursos está fuera delcódigo de la aplicación, mientras que en Chroma está incluido en un conjunto de exten-siones del sistema operativo. Al igual que en Spectra, para decidir dónde ejecutar unatarea el usuario define una función de utilidad para cada tarea que describe el peso decada factor, como la velocidad y la energía de la CPU. Entonces Chroma intenta maximi-zar la tasa de fidelidad/latencia a través de la táctica seleccionada. Finalmente, Chromay Spectra tienen una desventaja ya que suponen que no es necesario enviar el código de
29
la aplicación porque la aplicación está instalada en los recursos de los subrogados queejecutan las tareas delegadas.
La siguiente etapa, que mejora el uso de subrogados, fue abordada por Goyal y Carter
en [Goyal and Carter, 2004] a través de un sistema basado en máquinas virtuales (VM),
como se muestra en la figura 3.1. La tecnología de VM permite utilizar el mismo subro-
gado para ejecutar diferentes aplicaciones desde diferentes dispositivos móviles y dis-
minuye el esfuerzo del desarrollador ya que no es necesario que modifique el código de
la aplicación. De manera similar, al igual que en los dos trabajos presentados anterior-
mente, el objetivo de Goyal y Carter es aumentar el rendimiento y reducir el consumo de
energía. Sin embargo, la sobrecarga de inicializar en el subrogado una máquina virtual
compatible con el sistema de Offloader en el subrogado es alta ya que la aplicación debe
descargarse de una URL específica. Como primer paso, el dispositivo móvil descubre to-
dos los subrogados posibles y, en un segundo paso, el dispositivo móvil envía una URL
y un script a los subrogados. Luego, los subrogados pueden descargar la aplicación de
la URL e instalarla en la VM utilizando la secuencia de comandos. 3.1 cuenta con un ser-
vidor de descubrimiento de servicios para conectar dispositivos móviles y subrogados.
Esto significa que cuando los dispositivos móviles usan el sistema, envían una solicitud al
servidor de descubrimiento de servicios y obtienen la dirección IP y el número de puerto.
El uso de VM aumenta la flexibilidad del sistema, y los subrogados no necesitan configu-
ración previa, evitando así el uso de un middleware específico. La principal desventaja
de este enfoque es que requiere que los dispositivos móviles estén conectados a Internet.
Otro sistema basado en VM es [Su and Flinn, 2005]. Como en Goyal y Carter, en Slings-hot se propone un sistema en el que el dispositivo móvil y los subrogados deben estarconectados a Internet, pero en Slingshot se presenta un nuevo componente, un servidor.Este servidor se usa para instalar la primera réplica de la aplicación, y luego de eso, lassegundas réplicas se instalan en los subrogados. Es importante mencionar un punto re-lacionado a considerar es que se necesita una red con baja latencia y conexión de anchode banda alto para usar este sistema con el fin de lograr aumentar el rendimiento de laaplicación, que es su objetivo principal. Dado esto, todas las tareas se ejecutan en más deun subrogado y los resultados se comparan en el servidor para verificar la confiabilidadde los mismos. Como nota al margen, si el servidor no está disponible, hay uno o másservidores auxiliares en la misma LAN. Finalmente, ninguno de los sistemas (Slingshot,y Goyal y Carter) tiene control sobre qué tareas deberían delegarse y cuándo. Entonces,una evolución de este tipo de sistemas reside en su capacidad para tomar decisiones entiempo de ejecución.
3.1.2. Enfoques orientados a energía
Aunque los trabajos descritos anteriormente representan un avance importante en Of-floading, ninguno de ellos tiene la reducción de consumo energético, que es el tema prin-cipal de esta tesis, como objetivo principal. Uno de los primeros sistemas cuyo objetivoprincipal es mejorar el consumo de energía y, además, minimizar el esfuerzo del desarro-llador se presentó en 2010 y se llama MAUI [Cuervo et al., 2010]. MAUI realiza Offloading
30
Figura 3.1: Cliente vs VM
de granularidad fina para aplicaciones OO, centrándose en aplicaciones de uso intensivode recursos. MAUI divide los métodos presentes en el grafo de la aplicación en localesy remotos para ejecutarlos utilizando programación reflectiva. Por lo tanto, MAUI hacedos versiones del código: una para la ejecución local en el dispositivo móvil y otra parala ejecución remota en el subrogado. Para delegar tareas, MAUI consta de tres módulos:una interfaz de decisión que reside en el servidor, un proxy que es responsable de contro-lar cada método candidato y un generador de perfiles que recopila información sobre laenergía consumida y otros datos. Para decidir qué tareas deben ejecutarse en los subro-gados, MAUI tiene un generador de perfiles que contiene información sobre la energíaconsumida por el CPU local por ciclo y sobre la latencia y el costo de energía del uso dela red para enviar y recibir las tareas. Finalmente, MAUI usa un mecanismo de tiempo deespera simple para evitar fallas en la ejecución de la aplicación.
En MAUI, se usa un sistema de perfiles único para evaluar dónde (smartphone o su-
brogado) se debe ejecutar una tarea; sin embargo, un nuevo sistema de doble perfil se
presenta en [Kristensen, 2010]. Este sistema se llama Scavenger y utiliza un sistema de
perfil individual y un perfil central para tomar decisiones sobre las diferentes ejecucio-
nes de tareas. Mientras que MAUI se centra en ahorrar energía, Scavenger se centra en
aumentar la potencia de la CPU y disminuir el tiempo de latencia de las aplicaciones, te-
niendo un mecanismo atractivo para evaluar en el área de consumo de energía también.
Por lo tanto, para disminuir el tiempo de latencia, el perfilador doble se basa en la estima-
ción del tiempo de ejecución según los tamaños de entrada y salida y la arquitectura de
la aplicación. Para hacer esta estimación, cada subrogado envía periódicamente su poder
31
de procesamiento disponible al dispositivo móvil. Sin embargo, los tiempos de ejecución
de diferentes tareas en cada arquitectura son diferentes y la potencia de procesamiento
de los subrogados debe calcularse de acuerdo con las tareas, lo que no se considera. Ade-
más, este generador de perfiles usa información adicional, como el ancho de banda y la
latencia de la red para estimar los tiempos de ejecución. Por otra parte, ni el factor de
estimación u otra información es predecible con lo que no es factible obtener una estima-
ción exacta. Otra innovación que introduce este sistema es la biblioteca de programación
que se debe incluir en la aplicación que los desarrolladores intentan modificar. Esta bi-
blioteca se puede importar automática o manualmente, de acuerdo con las preferencias
y el conocimiento de los desarrolladores, lo que reduce el esfuerzo a casi nada. Por otro
lado, los subrogados ejecutan un daemon para mantenerse conectados y para poder ins-
talar las aplicaciones a ejecutar. La última innovación en este sistema es un scheduler de
múltiples núcleos. Esto significa que las tareas y los perfiladores pueden aprovechar los
recursos de núcleos múltiples, una característica que falta en trabajos anteriores.
En la misma línea, se presenta un novedoso sistema basado en grafos Abebe and Ryan
[2012]. En este sistema, se usa un grafo que representa los recursos de los diferentes
subrogados para tomar decisiones para una ejecución eficiente y eficaz basada en una
heurística específica. No obstante, construir este grafo es una tarea compleja debido a la
complejidad de sus componentes. Los vértices modelan los componentes de la aplicación
(en la granularidad del nivel de clase), con el peso de un vértice como el uso de recursos
compuestos (memoria, energía, CPU, etc.) de todas las instancias del componente. Los
arcos representan el acoplamiento entre los vértices donde el peso de un arco se deter-
mina por la tasa de invocación y el costo de la misma. Entonces, un subrogado tiene que
ser responsable de construir el grafo. Como resultado, teniendo en cuenta los recursos y
el estado de la red, este sistema aumenta el rendimiento y disminuye el uso de recursos,
especialmente energía, en el dispositivo móvil.
En los últimos años, se describieron nuevos enfoques para reducir la energía. Por ejem-plo, AIOLOS [Verbelen et al., 2012] es un framework para Android presentado como uncomplemento para Eclipse. AIOLOS utiliza un modelo que tiene en cuenta los recursosdel servidor y el estado de la red para decidir en tiempo de ejecución si una tarea deberealizarse en un dispositivo móvil o enviarse a un subrogado. Delegar una tarea a unservidor subrogado es conveniente cuando el tiempo de ejecución remota es menor queel tiempo de ejecución local. Se mantiene un perfil basado en la historia para calcular eltiempo de ejecución local. Para estimar el tiempo de ejecución remota [Verbelen et al.,2012] introduce tres parámetros s, b y l, que representan la aceleración de CPU (una CPUde servidor es más rápida que la de un dispositivo móvil), ancho de banda de red y la-tencia de red respectivamente. Por último, la ecuación utilizada para estimar el tiempode ejecución remota es:
32
Tremote =1s ∑
iǫRM
(TCPU,locali)+
1b× (A + R)+ l + ∑
jǫCM
(TCPU,locali+
1b× (Aj + Rj)+ l) (3.1)
donde RM es la colección de tareas ejecutadas remotamente, CM define una colecciónde callbacks para manejar los resultados de tareas, A es el tamaño de la tarea delegada yR es el tamaño estimado de los datos de resultados devueltos.
Además, AIOLOS tiene en cuenta el uso de energía: una tarea debe descargarse si se aho-
rra energía mediante la ejecución remota (Esaved > 0). Finalmente, el potencial de ahorro
de energía se calcula con la siguiente ecuación:
Esaved = ECPUx ∑iǫRM
(TCPU,locali)−ETR × A−ERCV ×R− ∑
jǫCM
(ERCV × Aj +ETR ×Rj) (3.2)
En este caso, la decisión depende del modelo de energía del dispositivo móvil porqueECPU representa la energía consumida por unidad de tiempo por la CPU del dispositivomóvil. ETR y ERCV indican el costo de energía para transmitir y recibir un byte, respec-tivamente. No obstante, Verbelen et al. [2012] se centra en la optimización del tiempode ejecución porque estos parámetros de energía son difíciles de medir utilizando herra-mientas de software, mientras que los parámetros de tiempo se estiman a través de unperfil generado a partir de la historia de ejecución.
Mientras que los cuatro Offloaders previos proponen sistemas con componentes de de-cisión en tiempo de ejecución que incurren en gastos computacionales generales, Zhanget al. [2012b] describe DPartner, un sistema que permite preprocesar los códigos de apli-cación consumiendp menos recursos en el momento de ejecución. Básicamente, DPartnerenvía automáticamente las aplicaciones de Android modificando el bytecode de la apli-cación. Con este objetivo, Zhang et al. [2012b] divide el proceso de Offloading en cuatropasos. En primer lugar, con la ayuda de las anotaciones de código Java detecta qué tareasson movibles (descargables) clasificando como «ancladas» aquellas tareas que utilizanrecursos disponibles solo en el dispositivo móvil. En el segundo paso, las tareas movi-bles se refactorizan para poder descargarlas en los subrogados. En tercer lugar, el sistemadetecta qué tareas deberían descargarse. Para determinar qué tareas móviles se debenenviar a subrogados existen numerosas reglas y algoritmos. Como señalamos anterior-mente, tomar decisiones en tiempo de ejecución consume recursos; como consecuencia,los autores han estudiado algunos algoritmos de preprocesamiento estático para reducirlas decisiones de tiempo de ejecución. Finalmente, el último paso consiste en empaquetarla aplicación modificada en dos tipos de ejecutables (.jar y .apk).
Para determinar qué tareas deben descargarse, DPartner encuentra las principales n ta-reas intensivas para considerarlas para ejecutarlas en subrogados. Además, una instanciade tarea debe cumplir las siguientes dos fórmulas para ser adecuada para la descarga:
tphone
to f f load=
tphone
(dinput/r + tphone/i + doutput/r)≥ α where α ≥ 1,5 (3.3)
33
(EcpuO f f load + Ewi f iOr3G) ≤ EcpuLocal (3.4)
donde tphone es el tiempo de ejecución en el dispositivo móvil, to f f load es el tiempo deejecución en el servidor,dinput es el tamaño de los parámetros de entrada del método enbytes, doutput es el tamaño de los valores de retorno del método en bytes, r es la velocidadde transmisión de datos a través de la red, i = cpuserver/cpuphone es la relación de ciclode la CPU entre el servidor y el dispositivo móvil y E es el consumo de energía porunidad de tiempo de la aplicación. Ewi f iOr3G se calcula monitorizando los archivos deconfiguración de WiFi/3G, y EcpuO f f load se calcula utilizando el algoritmo de mapeo entrelas instrucciones bytecode y el consumo de energía propuesto en Binder [2006].
3.1.3. Resumen
Resumiendo, discutimos varios trabajos que representan los principales avances en elárea de Offloading. Hay algunos trabajos cuyo objetivo principal es mejorar el rendi-miento o la latencia, pero no el consumo de energía. Sin embargo, evaluar su impactoen el consumo de energía es interesante ya que, en general, el rendimiento y el consumode energía están relacionados Rodriguez et al. [2016a]. Disminuir el consumo de energíano es una tarea simple porque depende de la capacidad de recursos, características dered, valores de entrada y salida, etc. Aún así, mantener el uso de CPU, memoria y otrosrecursos bajos y disminuir el tiempo de ejecución es una buena táctica para reducir elconsumo de energía. Luego, utilizar los trabajos existentes para mejorar el consumo deenergía en los smartphones es una línea de investigación viable e interesante.
Después del análisis de trabajos representativos relacionados con Offloading, presenta-
mos algunos problemas comunes que surgen al tratar de reducir el costo de la ejecución
en dispositivos móviles mediante Offloading. En primer lugar, el esfuerzo de los desa-
rrolladores es una característica importante a tener en cuenta cuando se utilizan algunos
de estos enfoques. Sin embargo, incluso en el caso de los Offloaders que requieren poco
esfuerzo, la aplicación de cualquier técnica de Offloading no es una tarea trivial ya que
es necesario tener conocimientos previos sobre el Offloader que se está utilizando. En
segundo lugar, una buena estimación de los costos de las ejecuciones locales y remotas
para tomar la decisión es necesaria. Como se muestra, todos estos trabajos usan datos his-
tóricos para hacer predicciones. Entonces, las predicciones para las primeras ejecuciones
nunca son precisas. Además, esta información puede colapsar el sistema de almacena-
miento del dispositivo móvil debido a la gran cantidad de información que necesita el
Offloader. Una solución a este problema es usar un sistema de memoria caché distribui-
da [Sharifi et al., 2011]. En general, surge un nuevo problema cuando una tarea tiene una
amplia gama de variables de entrada y el modelo de estimación del Offloader no consi-
dera el efecto de introducir diferentes valores para estas variables [Sharifi et al., 2011].
34
3.2. Schedulers distribuidos para dispositivos móviles basados
en energía
Basado en la premisa de que los smartphones y otros dispositivos móviles son capacesde ejecutar código computacionalmente intensivo Rodríguez et al. [2012b], a continua-ción discutimos trabajos que consideran los dispositivos móviles para la ejecución decódigo intensivo en entornos distribuidos híbridos. A diferencia de Offloading, estos tra-bajos promueven la ejecución de código intensivo en dispositivos móviles. Sin embargo,en ambos casos, el objetivo principal es reducir el consumo de energía o el tiempo deejecución en el dispositivo móvil.
El comienzo de entornos distribuidos híbridos que unen recursos computacionales des-
de dispositivos móviles y servidores fijos, particularmente Gtids móviles, fue en 2003. No
obstante, uno de los primeros trabajos que demuestra la utilidad de los dispositivos mó-
viles para la ejecución de aplicaciones HPC utilizando entornos distribuidos es Huynh
et al. [2011], que a su vez motivó una mayor investigación. Los autores de Huynh et al.
[2011] proponen un modelo de computación híbrida para ejecutar secciones de código
paralelas semi-intensivas de aplicaciones en dispositivos móviles, incluidos los disposi-
tivos móviles como nodos activos. Usando este algoritmo paralelo, los autores desarro-
llaron dos soluciones: offline y online. En la solución offline, el algoritmo se ejecuta por
completo en una supercomputadora. Por otro lado, la solución online permite ejecutar el
mismo algoritmo complejo en varios dispositivos móviles, como smartphones o tabletss.
Como conclusión, los autores infieren que independientemente del hardware diferen-
te con capacidades muy diferentes, el resultado final es en cierto sentido agnóstico del
hardware: la predicción de la versión online es indistinguible del cálculo paralelo de la
supercomputadora. Finalmente, los autores afirman que han logrado ”supercomputación
en un smartphone”.
A pesar de que se han llevado a cabo investigaciones exhaustivas sobre plataformas dis-
tribuidas, la producción de aplicaciones de uso general para las plataformas distribuidas
que incluyen estos nuevos dispositivos móviles es un problema que no ha sido claramen-
te reconocido hasta hace poco tiempo Rodriguez et al. [2011b]. A pesar de los resultados
importantes con respecto a los métodos de paralelización Mateos et al. [2008, 2010a,b,
2011a] y las técnicas para facilitar la movilidad del software han surgido en el pasado
cercano Mateos et al. [2010c], Crasso et al. [2011], Fernando et al. [2013], Furthmuller and
Waldhorst [2012], Mateos et al. [2010a], estos avances se limitan a las infraestructuras pa-
ralelas y distribuidas tradicionales, que dependen de servidores fijos conectados a una
red con intervalos de tiempo predecibles y estables. Como resultado, han surgido dife-
rentes puntos de vista sobre la integración de dispositivos móviles en las infraestructuras
de Grid Computing que explotan estos avances anteriores. Por ejemplo, Rodriguez et al.
[2011b], Loke et al. [2015] se centran en las redes de procesamiento con uso intensivo de
CPU que integran dispositivos móviles como smartphones y tablets.
35
Al principio, los dispositivos móviles estaban conectados a Grids solo funcionando como
interfaces para administrar y supervisar recursos, pero en los últimos años, los disposi-
tivos móviles se han integrado para funcionar como nodos activos de Grids Fernando
et al. [2013]. Desde esta integración, se han propuesto varios métodos para hacer una in-
tegración adecuada, centrada principalmente en la programación de tareas. Por lo tanto,
la mayoría de estos nuevos schedulers se basan en la modificación de algunos paráme-
tros en schedulers existentes, en lugar de un scheduler nuevo y óptimo para dispositivos
móviles Rodriguez et al. [2010].
El primer ejemplo de estas adaptaciones se presentó en min Park et al. [2003], en el que
se propone un scheduler basado en la premisa de que los dispositivos móviles a menudo
se desconectan de la red. Básicamente, este scheduler envía una tarea al nodo con más
probabilidad de estar conectado cuando la tarea se completa. Esta probabilidad la cal-
cula según un modelo de Poisson. Sin embargo, una limitación de este trabajo es que el
scheduler necesita saber de antemano el tiempo de ejecución de cada tarea, lo que no
siempre es posible, e involucra un proceso de Poisson que necesita una gran cantidad de
procesamiento de CPU para ser computado. Además, min Park et al. [2003] presenta una
simulación para determinar la cantidad óptima de nodos móviles según la cantidad de
tareas y el tiempo de CPU necesarios.
Diferente del enfoque descrito en min Park et al. [2003], donde el scheduling es dinámico,
Shivle et al. [2006] analiza numerosos algoritmos de scheduling estática cuyo objetivo es
minimizar la energía consumida por las aplicaciones que se basan en la comunicación de
subtareas, es decir, tareas con dependencias. Las limitaciones de este estudio son que al-
gunos parámetros (por ejemplo, energía consumida dentro de una unidad de tiempo por
un dispositivo o cuántas unidades de tiempo son necesarias para completar una tarea)
se deben conocer de antemano y la asignación se realiza de forma estática (es decir, no
considera la posibilidad de que los dispositivos fallen antes de finalizar el procesamiento
de una tarea). Sin embargo, este trabajo compara seis heurísticas diferentes utilizando
diferentes parámetros y obtiene resultados interesantes, incluso cuando estas heurísticas
consumen menos CPU que el cálculo del proceso de Poisson. Para concluir, los autores
declaran que se puede seleccionar una heurística específica en función de las caracterís-
ticas del dominio de la aplicación.
En Ghosh and das [2010] las limitaciones del trabajo previo se abordan considerandotareas homogéneas independientes (los mismos requisitos de CPU, RAM y red). En estetrabajo, el scheduler negocia el pago con cada nodo para ejecutar tareas pendientes yrealizar una asignación de costos óptima. Un modelo de fijación de precios económicosrige los beneficios de costos de los propietarios de dispositivos móviles para permitir quese lleven a cabo tareas computacionales complejas en esos dispositivos. Luego, el objetivode los autores es diseñar un esquema de asignación de tareas costo-óptimo basado en unaestrategia de precios justos para Grids móviles que soporte la movilidad del nodo. Paraesta negociación, los autores simularon los resultados de la aplicación de tres algoritmos
36
diferentes con una complejidad de O(n) basado en la teoría de juegos. Este algoritmotiene dos limitaciones. Primero, las tareas rara vez consumen exactamente los mismosrecursos, y segundo, los pagos para cada tarea deben negociarse, lo que genera un tiempode ejecución adicional. Entonces, el objetivo de este algoritmo es minimizar los costossobre la maximización del uso de recursos limitados que se derivan en un scheduler queno toma en cuenta el consumo de energía u otros recursos limitados como memoria oCPU de dispositivos móviles. En consecuencia, una tarea puede agotar una batería móvilsin finalizar su ejecución o puede consumir varios recursos (por ejemplo, CPU o RAM),alterando otros usos del dispositivo móvil.
Por otro lado, Li and Li [2010a] propone un modelo en el que la utilidad del Grid es la
variable para maximizar sin exceder la capacidad de recursos, destacando la batería. Este
modelo presta especial atención al uso de la energía de las baterías, ya que es el recurso
el que determina la capacidad de la red: cuando la batería se agota, el dispositivo ya no
se puede usar. El principal inconveniente del modelo es su alto costo computacional, ya
que utiliza multiplicadores de Lagrange para calcular el costo de energía, el precio de la
capacidad de recursos informáticos y el precio de la capacidad de recursos de la red. Sin
embargo, el propósito de los autores es dividir el problema en dos subproblemas utili-
zando dos tipos diferentes de componentes -agentes- para resolverlos. En primer lugar,
los agentes de recursos de Grid representan los intereses económicos de los proveedores
de recursos; y, segundo, un agente de aplicación que contiene los intereses de la aplica-
ción de usuario Grid que utiliza el Grid para lograr su objetivo teniendo en cuenta una
función de utilidad descrita para cada dimensión de QoS (recursos y energía necesarios,
tiempo máximo, pago máximo, entre otros). Después de definir los agentes, el modelo
funciona en iteraciones, cada iteración consta de tres pasos:
1. Los agentes de recursos de Grid actualizan su ubicación
2. Los agentes de recursos actualizan su precio individual
3. Se publica una descripción del recurso en el mercado delvGrid para negociar con
los agentes de la aplicación
Como puede verse, este modelo tiene un problema compartido por varios trabajos: ne-
cesita conocer los parámetros, como la capacidad de energía y la capacidad de cálculo,
de antemano. En consecuencia, este modelo se evaluó utilizando una simulación de una
topología con múltiples LAN interconectadas en las que se consideraron y variaron los
estados de carga de la batería, la red y el sistema. Los resultados se midieron utilizan-
do diferentes parámetros como el porcentaje de energía consumida, el porcentaje de los
recursos totales utilizados, la eficiencia de asignación y el número de tareas cuyas restric-
ciones de plazos no superan el número total de tareas.
No obstante, los esfuerzos previos en el área, las fórmulas complejas que todos estosschedulers necesitan calcular, hacen que la planificación de tareas sea una actividad que
37
consume mucho tiempo y recursos. Como consecuencia, se presenta un algoritmo sim-ple de programación de tareas para dispositivos móviles llamado Simple Energy-AwareScheduling (SEAS) enRodriguez et al. [2010]. El algoritmo SEAS intenta estimar un buenuso de los recursos, especialmente la batería, teniendo en cuenta los estados previos yactuales de los dispositivos móviles. SEAS estima el tiempo de batería restante conside-rando la descarga como una constante y actualiza el tiempo restante de acuerdo con losestados anterior y actual. La principal ventaja de este algoritmo es que puede calcularseen tiempo real, es ligero en recursos computacionales y no requiere conocimientos pre-vios sobre parámetros inciertos, como cuánta energía consume un dispositivo por unidadde tiempo de ejecución, o cuántas unidades de tiempo de ejecución son necesarios paracompletar una tarea. Sin embargo, SEAS no considera las demandas computacionales dela tarea cuando asigna tareas a los dispositivos. Como consecuencia, SEAS puede enviaruna tarea a un dispositivo que no tiene la capacidad de terminarla.
En un trabajo posterior, los autores de Rodriguez et al. [2010] desarrollaron diferentesschedulers para Grids móviles basadas en técnicas de robo de tareas. El robo de tareasocurre cuando un nodo del Grid está inactivo y toma tareas de otros nodos para mante-nerse ocupado, tratando de equilibrar la carga en el Grid. Las técnicas de robo de tareasevaluadas en [Rodriguez et al., 2014] tienen en cuenta el consumo de energía, las capaci-dades computacionales y el estado de la batería como en Rodriguez et al. [2010]. Cuandose asigna una tarea a un dispositivo móvil, la tarea se pone en cola hasta que el dispositivomóvil pueda ejecutarla. A pesar de esta simple asignación, la tasa de consumo de energíavaría de acuerdo con varios factores, como la carga de trabajo y el uso de la red. Además,los sensores de batería de los dispositivos móviles no son muy precisos. Como resultado,la elección del scheduler puede no ser la mejor, pero la replanificación no es compatible.Por otro lado, los algoritmos de robo de tareas son una opción viable cuando un disposi-tivo finaliza todas sus tareas asignadas mientras que otros tienen tareas en sus colas. Losalgoritmos de robo de tareas permiten que los dispositivos tomen tareas para ejecutardesde otro dispositivo. Los algoritmos de robo aleatorio tradicionales consisten en elegirun dispositivo móvil aleatorio para robar, o víctima, y funcionan bien en muchos esce-narios y su costo computacional es muy bajo Van Nieuwpoort et al. [2010]. Teniendo encuenta la simplicidad, que es parte de la premisa de SEAS, Rodriguez et al. [2014] compa-ra una estrategia que considera el estado de la batería y el consumo de energía para elegira la víctima con los algoritmos tradicionales de robo aleatorio. En consecuencia, Rodri-guez et al. [2014] muestra que un scheduler de robo de tareas consciente de la energíaes más eficiente para las redes móviles que los algoritmos de robo aleatorio tradicionalesporque aumenta notablemente el número de tareas que se pueden ejecutar utilizando lamisma cantidad de energía.
Un nuevo entorno computacional híbrido apareció en 2013, proponiendo integrar dispo-sitivos móviles como recursos, llamado Mobile Cloud Computing Fernando et al. [2013].Como mencionan los autores, la integración de dispositivos móviles en este paradigmaes inminente porque representan una gran cantidad de poder de cálculo no utilizado.Como resultado, no solo se necesitan buenos schedulers de tareas sino también mode-los de desarrollo con conciencia energética para dispositivos móviles, de modo que loscódigos de tareas utilicen los recursos móviles con prudencia. En esta sección se presen-taron muchos esfuerzos centrados en schedulers conscientes de la energía que incluyendispositivos móviles como "ciudadanos de primera clase" en entornos distribuidos. Enparticular, ninguno de ellos evalúa el impacto dentro de la tarea o dentro de la aplicación.
38
La siguiente subsección se refiere a la eficiencia energética del código de aplicación, pre-sentando una línea de investigación complementaria que pretende refactorizar códigospara dispositivos móviles, independientemente de la técnica de planificación de tareas,es decir, del scheduler de trabajos móviles.
3.3. Modelos de desarrollo de software y metodologias basados
en energía
En los últimos años, se han realizado diferentes esfuerzos para aumentar la eficiencia
energética en los Data Centers al procesar aplicaciones de uso intensivo de recursos. En
esta área hay varios enfoques que disminuyen el consumo de energía en diferentes ni-
veles, como hardware, sistema operativo o código fuente de alto nivel (es decir, nivel de
aplicación). Mencionaremos algunos trabajos de cada nivel prestando especial atención a
los trabajos de código fuente de alto nivel, ya que nuestro objetivo principal es reducir el
consumo de energía a través de la refactorización de códigos.
Para analizar el consumo de energía en todos los niveles es necesario saber qué recursos
consumen más energía. Según Minas and Ellison [2009] la mayor cantidad de energía
consumida se produce por la pantalla, seguida del CPU y la memoria. Utilizando este
conocimiento, los científicos pueden proponer diferentes enfoques para desarrollar mo-
delos y directrices en cualquier nivel. Por ejemplo, Chen et al. [2012] presenta una herra-
mienta perfilado a1 nivel de proceso y un módulo de energía de sistema que elimina la
energía desperdiciada por las aplicaciones por su comportamiento anormal para el cual
la información de hardware es esencial. Como conclusión, Chen et al. [2012] afirma que
los investigadores deberían diseñar modelos de energía simples con buena capacidad de
respuesta para obtener mediciones reales e instantáneas para controlar el consumo de
energía.
Otros científicos analizan el consumo de energía de la fabricación y el uso del hardware
junto con el consumo en la ejecución de software Ardito and Morisio [2014]. Con respec-
to a la fabricación y el uso del hardware, la fase más costosa en términos de consumo de
energía es el diseño y la fabricación (54% del consumo total de energía), seguido del uso
(15%). Para la fase de uso, Ardito and Morisio [2014] presenta pautas para la eficiencia
energética en cuatro niveles diferentes: infraestructura, aplicación, sistema operativo y
hardware. En las directrices de nivel de aplicación incluye diseño eficiente de UI, utiliza-
ción de programación basada en eventos cuando sea posible, utilización de programación
de bajo nivel, reducción la redundancia de datos y utilización de herramientas de perfil
de energía.
Además, de acuerdo con Pinto et al. (2015) hay una gran variedad de trabajos que abor-
39
dan el problema del consumo de energía a nivel de aplicación y se pueden clasificar en
diferentes grupos. Las dos áreas principales en las que el consumo de energía es un te-
ma novedoso son la programación móvil y paralela. Las investigaciones de aplicaciones
móviles se centran en 6 cuestiones para reducir el consumo de energía: interfaz de usua-
rio, descarga de CPU, solicitud de HTTP, piratería de software, aplicación en ejecución
continua y operaciones de E / S. Por otro lado, en la programación paralela hay 3 fac-
tores principales: cadenas de copias excesivas, paralelismo de abrazo y programación de
GPU. Aunque Pinto et al. (2015) examina varios documentos presentados en las conferen-
cias de ingeniería de software más destacadas, los autores no analizan trabajos basados
en computadoras personales o servidores, esta última es nuestra plataforma de destino
secundaria para nuestras refactorizaciones con conciencia energética. Además, a diferen-
cia de Ardito y Morisio (2014); Pinto et al. (2015), estamos especialmente interesados en
estudiar primitivas de programación que no sean generales sino que sean concretas y
conscientes de la energía, ya que nuestro trabajo apunta a mejorar el consumo de energía
a través de refactorizaciones de códigos fuente impulsadas por primitivas comunes en
códigos HPC.
Además, de acuerdo con Pinto et al. [2015] hay una gran variedad de trabajos que abor-
dan el problema del consumo de energía a nivel de aplicación y se pueden clasificar en
diferentes grupos. Las dos áreas principales en las que el consumo de energía es un tópico
novedoso son la programación móvil y la programación paralela. Las investigaciones de
aplicaciones móviles se centran en 6 cuestiones para reducir el consumo de energía: inter-
faz de usuario, carga de CPU, solicitud HTTP, piratería de software, ejecución continua
de una aplicación y operaciones de E/S. Por otro lado, en la programación paralela hay
3 factores principales: copias de datos excesivas, paralelismo y programación de GPU.
Aunque Pinto et al. [2015] examina varios documentos presentados en las conferencias
de ingeniería de software más destacadas, los autores no analizan trabajos basados en
computadoras personales o servidores, los cuales son nuestra plataforma de experimen-
tación secundaria. Además, a diferencia de Ardito and Morisio [2014], Pinto et al. [2015],
nosotros estamos especialmente interesados en estudiar micro-benchmarks concretos y
basados en ahorro de energía, ya que nuestro trabajo apunta a mejorar el consumo de
energía a través de refactorizaciones de códigos fuente.
3.3.1. Dispositivos móviles
Los servidores y los centros de datos no son el único objetivo al reducir el consumo deenergía. Los dispositivos móviles dependen de su batería como fuente de energía; enton-ces, ahorrar energía es una preocupación importante cuando se desarrollan aplicacionesmóviles. No solo la motivación es extender la duración de la batería y, por lo tanto, au-mentar la experiencia del usuario móvil, sino también soportar cómputos complejos endispositivos móviles a la luz de paradigmas computacionales más nuevos Fernando et al.[2013]. Como consecuencia, hay varios trabajos cuyo objetivo principal es minimizar el
40
consumo de energía en las aplicaciones moviles y estos son los trabajos en los que estamosmás interesados. Las secciones anteriores describen las diferentes funciones de los dispo-sitivos móviles en entornos distribuidos, pero cómo desarrollar código para dispositivosmóviles es otro campo de relevancia en el área. En los siguientes párrafos, discutiremoslos trabajos relacionados con el consumo de energía de la programación de aplicacionesmóviles, la mayoría de ellos centrados en dispositivos móviles Android debido a la po-pularidad del sistema operativo Android. Es importante mencionar que algunos trabajosen esta área se centran en diversas características para mejorar el tiempo de ejecución yel consumo de energía o la calidad del software. Estamos especialmente interesados enel consumo de energía y el tiempo de ejecución, ya que es el objetivo principal de estatesis. La performance está estrechamente relacionada con el consumo de energía porquereducir el tiempo de ejecución sin cambiar la cantidad de procesamiento y el uso de lamemoria por unidad de tiempo equivale a reducir el consumo de energía.
Como un hecho interesante, aunque el resultado esperado es que el Código nativo tengaun mejor rendimiento que el código escrito en lenguajes de alto nivel como Java, losresultados reales muestran que el tiempo de ejecución depende del tipo de operación. Porejemplo, Cheng-Min et al. [2011] compara el código Java con el código nativo de Androiden términos de tiempo de ejecución utilizando 12 benchmarks populares divididos en lassiguientes 8 categorías:
Cálculo numérico con recursión: los benchmarks de Ackermann y Fibonacci eva-lúan el tiempo de ejecución de realizar llamadas a funciones recursivas y tambiénacumulan velocidad de administración de memoria.
Facilidades de biblioteca: Hash y Hash2 prueban el tiempo de ejecución de la im-
plementación de hashMaps en bibliotecas. En Java, se utiliza la biblioteca estándar
que provee la clase Hash Map, mientras que en C++ se utiliza el gcc no estandar
hash_map.
Estructura de datos creada por el usuario: las pruebas Heapsort y Matrix no depen-
den de una biblioteca sino que implementan estructuras de datos personalizadas y
prueban el tiempo de ejecución de sus operaciones.
Polimorfismo: esta prueba utiliza los benchmarks Methcall y Objinst para ver cuán-
to tiempo lleva hacer una llamada en un momento determinado.
Bucles anidados: esta prueba consta de seis bucles anidados, cada uno de los cuales
ejecuta N rondas.
Generación aleatoria de números: esta prueba usa cálculos numéricos puros con
solo algunas variables y sin estructuras de datos.
Tamiz de Eratóstenes: este es un algoritmo simple para encontrar números primos
de manera eficiente. Se usa una matriz de valores booleanos, donde cada elemento
representa si su valor de índice puede ser primo o no.
41
Cálculos con enteros Asignación de memoria
Número deentradas
100 300 500 800 1,000 100 300 500 800 1,000
Dalvik 15 172 561 1,453 2,338 114 150 311 538 647
Native C 5 63 197 510 827 11 33 54 83 109
Mejora 66% 63% 64% 64% 64% 90% 78% 82% 84% 83%
Cuadro 3.2: Evaluación (ms) Sangchul and Wook [2010]
Operaciones de cadena: la prueba strcat concatena un string al final de otro string.
Como resultado, los autores demuestran que Native Code es más rápido que el códigode Java en un promedio de 34.2%, tomando valores entre 99.98% y -158.39%. Si bien enalgunos casos particulares el código Java es mejor, en la mayoría de los casos, el Códi-go nativo supera a Java. En particular, Java supera a Native Code en Hash (-158.39%),Heapsort (-26.61%) y Random (-47.72%) benchmarks.
Otro trabajo similar analiza qué tipo de algoritmos son los que presentan mayores me-
joras en el tiempo de ejecución usando Native Code. Para determinar cuándo el Código
nativo proporciona un mejor rendimiento que los lenguajes de alto nivel, Sangchul and
Wook [2010] clasifica los algoritmos en cinco áreas: retardo de comunicación, operacio-
nes con enteros, operaciones de coma flotante, acceso a memoria y asignación de heap.
Para evaluar cada área, Sangchul and Wook [2010] desarrolla aplicaciones de Android
usando la biblioteca de códigos nativos usando C y una aplicación de Android usando el
mismo algoritmo desarrollado en Java y ejecutándose en la máquina virtual Dalvik. Los
autores muestran que los retrasos en la comunicación que se producen debido al uso de
la interfaz Java no tienen influencia en los resultados experimentales. Por otro lado, el
cálculo de enteros, el cálculo de coma flotante, el algoritmo de acceso a la memoria y la
asignación del heap logran resultados más rápidos utilizando la biblioteca C nativa que
utilizando el mismo algoritmo escrito en Java. Sin embargo, los algoritmos de acceso a
memoria no disminuyen su tiempo de ejecución cuando el número de parámetros de en-
trada aumenta cuando se utiliza C. Luego, a medida que aumenta el número de entrada,
la mejora obtenida usando C nativo aumenta también. En otras palabras, la diferencia de
tiempo de ejecución entre Dalvik y C nativo es proporcional en operaciones como cálcu-
los enteros, mientras que esa proporción cambia considerablemente para los algoritmos
de asignación de memoria cuando aumenta el número de entrada, como se muestra en la
Tabla 3.2.
En conclusión, aunque el código nativo fue más eficiente en todas las pruebas, el trabajorecomienda usar bibliotecas C nativas cuando la aplicación requiere accesos frecuentes ala memoria o realiza cálculos complejos.
42
A pesar de que Native C mejora el tiempo de ejecución en comparación con Java, es-
te último es un lenguaje muy popular para desarrollar aplicaciones de Android, ya que
proporciona portabilidad, seguridad, robustez y simplicidad Barisone et al. [2001]. De
hecho, Java admite programación OO, multithreading y computación distribuida imple-
mentada a nivel de lenguaje, independencia de plataforma, administración automática
de memoria y manejo de excepciones, lo que la hace interesante para aplicaciones de uso
general Barisone et al. [2001]. Además, varios estudios muestran que Java es un lenguaje
útil para desarrollar aplicaciones de HPC Taboada et al. [2011].
Sabiendo que Java es un lenguaje eficiente y viable para implementar HPC, podemos
evaluar diferentes propuestas para ahorrar energía utilizando este lenguaje. Comenzan-
do, Google propone sus propias prácticas de codificación Java para mejorar el tiempo
de ejecución de la aplicación Android1. Es importante mencionar que cuando se mantie-
ne el consumo de CPU y memoria por unidad de tiempo pero se reduce el tiempo de
ejecución, el consumo de energía también disminuye. La lista de estas prácticas incluye
algunas conocidas para mejorar el tiempo de ejecución: evitar crear objetos innecesarios,
preferir el uso estático sobre virtual, uso de constantes, evitar getters/setters internos,
usar la sintaxis mejorada de bucles, considerar paquetes en lugar de acceso privado con
clases internas privadas, evitar el uso de coma flotante, conocer y utilizar las bibliotecas,
y usar los métodos nativos cuidadosamente. En los siguientes párrafos, se explican estas
prácticas y se presentan algunos trabajos que las evalúan:
Evitar crear objetos innecesarios: la creación de objetos no es barata porque, a pesarde la existencia de un Garbage Collector que abarata la asignación, asignar memo-ria siempre es más costoso que no hacerlo. Además, cuando se asigna memoria esnecesaria una recolección periódica para liberar espacio de objetos no utilizados, loque también empeora el tiempo de ejecución de la aplicación. Por lo tanto, los desa-rrolladores deben evitar la creación de instancias de objetos que no sean necesarios.
Preferir el uso estático sobre virtual: si no necesita acceder a los campos de un objeto
se debe establecer el método como estático. Las invocaciones serán entre un 15%
y un 20% más rápidas, ya que las invocaciones estáticas no requieren una tabla
indirecta para alcanzar el método
Usar constantes: Considerar la declaración en la parte superior de una clase presen-tada en el Algoritmo 3.1.En este algoritmo, el compilador genera un método de inicialización de clase, lla-mado <clinit>, que se ejecuta cuando la clase se utiliza por primera vez. El métodoalmacena el valor 42 en intVal, y extrae una referencia de la tabla de constantes parastrVal. A partir de ese momento el código que hace referencia a intVal usará el valor
1http://developer.android.com/training/articles/perf-tips.html
43
1: static int intVal = 42;2: static String strVal = "Hello, world!";
Algorithm 3.1: Declaración estática
entero 42 directamente, y los accesos a strVal usarán una instrucción relativamenteeconómica. Sin embargo, es importante mencionar que esta optimización se aplicasolo a tipos primitivos y constantes de String.
Evitar Getters/Setters internos: una práctica común en OO es usar getters para ac-ceder a los valores de los atributos en lugar de acceder directamente a los campos.Sin embargo, las llamadas a métodos son costosas. Es razonable seguir prácticascomunes de programación OO y tener getters/setters en interfaces públicas perodentro de una clase los desarrolladores deben acceder directamente a los valores.
Usar la sintaxis mejorada para bucles: el bucle for forzado (for-each loop) se puede
usar para colecciones que implementan la interfaz Iterable de Java y para matrices.
Con las colecciones, se asigna un iterador para hacer las llamadas de interfaz a los
métodos hasNext() y next(). En cambio, con un ArrayList, un bucle contado escrito
a mano es aproximadamente tres veces más rápido. Al iterar usando las variables
de índice o iteradores se presentan oportunidades para errores de programación. El
bucle for-each evita la posibilidad de este error al ocultar el iterador o la variable de
índice además del compilador y las optimizaciones JIT que se obtienen con un bucle
for-each. Además, un bucle for-each evita el uso de estas variables adicionales, lo
que introduce un procesamiento adicional y afecta el tiempo de ejecución.
Considerar el uso de paquetes en lugar del acceso privado con clases internas: con-siderando la definición de clase privada presentada en el Algoritmo 3.2, se defineuna clase privada y la cual puede acceder directamente al campo definido en laclase externa. El problema reside en que para permitir que una clase interna accedaa miembros privados de una clase externa el compilador Java genera algunos mé-todos sintéticos que deben ser llamados por la clase privada y dar como resultadouna disminución de rendimiento "invisible". Los desarrolladores pueden evitar lasobrecarga al declarar que los campos y métodos a los que se accede tienen accesoal paquete.
Evitar utilizar Floating-Point: el punto flotante es dos veces más lento que los inte-ger en dispositivos Android. Sin embargo, en hardware moderno no hay diferenciaen términos de velocidad entre los tipos float y double, pero el double es dos vecesmás grande.
Conocer y usar las bibliotecas: la mayoría de los idiomas proporcionan bibliote-
cas integradas o funcionalidad incorporada cuyo objetivo principal es exponer las
funciones comunes para su reutilización. Los ejemplos son la funcionalidad pa-
ra buscar y clasificar estructuras de datos o algoritmos de generación de números
44
1: public class Foo {2: private class Inner {3: void stuff() {4: Foo.this.doStuff(Foo.this.mValue); {} }5: private int mValue;6: public void run () {7: Inner in = new Inner(); mValue = 27; in.stuff(); }8: private void doStuff(int value) {9: System.out.println("Value is - value); }
10: }
Algorithm 3.2: Acceso privado
aleatorios. Usar este soporte tiene ventajas significativas sobre el uso de implemen-
taciones ad-hoc. Al usar una funcionalidad incorporada, los desarrolladores apro-
vechan el conocimiento de los expertos que lo escribieron y la experiencia de quie-
nes lo usaron antes que ellos. Una segunda ventaja es que los desarrolladores no
tienen que perder tiempo escribiendo funcionalidades comunes. Además, el rendi-
miento de dicho soporte tiende a mejorarse con el tiempo. En particular, muchas de
las funcionalidades integradas de la plataforma Java se han reescrito a lo largo de
los años, lo que resulta en mejoras dramáticas en el tiempo de ejecución Bloch Bloch
[2001].
Usar los métodos nativos cuidadosamente: Desarrollar código nativo de Androidutilizando el NDK de Android no es necesariamente más eficiente que la progra-mación con el lenguaje Java. Hay un costo asociado con la transición Java-códigonativo. Además, el compilador JIT (Just In Time, que convierte activamente el códi-go de la aplicación en una forma que se ejecuta más rápido) no puede optimizar através de estos límites. También, el código debe compilarse para cada arquitecturaen la que se ejecutará.
Algunos trabajos científicos han verificado estas buenas prácticas y evaluado su impactoen el tiempo de ejecución y en el consumo de energía. Uno de estos trabajos es Toniniet al. [2012], que evalúa la mejora de evitar el uso de métodos getter y setter, y el usode la sintaxis apropiada para un loop. Además, Tonini et al. [2012] evalur el impacto deestas prácticas en una aplicación real. Los resultados muestran que evitar el uso de gettery setter es 2.9 veces más rápido que usarlos, y el uso de la sintaxis for-each adecuadaes 1.25 veces más rápido que no hacerlo. Finalmente, la aplicación real modificada es1.33 veces más rápida que la aplicación original. De acuerdo con Tonini et al. [2012] estoshallazgos serán ampliados por los autores para evaluar explícitamente la efectividad deestas prácticas.
Mientras que los trabajos anteriores se centran en la evaluación del tiempo de ejecución,
los párrafos siguientes discuten trabajos cuyo objetivo principal es optimizar el consumo
de energía en los dispositivos móviles. En esta área Gottschalk et al. [2012] propone detec-
45
tar y eliminar el código que consume excesiva energía mediante técnicas de reingeniería
de software. Gottschalk et al. [2012] analiza la estructura del código móvil para encon-
trar patrones de consumo de energía (malas prácticas), llamados olores codificados. El
olor a código de término se ha presentado y utilizado para el tiempo de ejecución en los
años 90, y se ha presentado y lo estudia exhaustivamente utilizando un catálogo de Code
Smells. Según Fowler [1999]: "un Code Smell es una indicación de superficial que generalmente
corresponde a un problema más profundo en el sistema". Otra forma de ver los Code Smells
es con respecto a los principios y la calidad del sistema Suryanarayana et al. [2015]: "los
Code Sells son ciertas estructuras en el código que indican la violación de los principios
de diseño fundamentales y afectan negativamente a la calidad del diseño". Finalmente,
Gottschalk et al. [2012] utiliza el mismo término pero para evaluar el consumo de ener-
gía. Luego, los autores presentan un método de detección y reestructuración para 7 Code
Smells:loop bug, dead code, in-line method, moving too much data, immortality bug,
redundant storage of data y using expensive resources que se describen en los párrafos
siguientes:
Loop bug: Se produce un error de ciclo cuando un ciclo se ejecuta indefinidamen-te en el background debido a causas externas, por ejemplo un servidor al que es-tá vinculada la aplicación se ha bloqueado. Como resultado, la aplicación intentacontactar al servidor consumiendo energía por la conexión. Como primer paso, esnecesario detectar los ciclos que vuelven al estado inicial del sistema. Después, paraevitar el error de cilclo, los desarrolladores pueden introducir un número máximode iteraciones para cada ciclo.
Dead code: Es código fuente que nunca se usa pero necesita cargarse en la memoriay, por lo tanto, consume energía. Algunos códigos muertos se pueden detectar yeliminar como una optimización de nivel de compilador. Algunos códigos muertosestán presentes en métodos que nunca se llaman. Este Code Smell de energía puededetectarse mediante la localización de métodos que nunca se llaman, métodos quese invocan bajo condiciones que nunca surgen. En este último caso, se debe realizarun análisis de código más detallado. Finalmente, si se detecta código muerto debedescartarse.
In-line method: Reemplazar una llamada de método con el cuerpo del método lla-mado puede ahorrar energía. In-line method es el opuesto a extracción de méto-do Fowler [1999] definido como una técnica para reducir el código duplicado yaumentar la capacidad de mantenimiento del código. Entonces, la aplicación de es-ta refactorización puede, por lo tanto, disminuir el mantenimiento y la legibilidaddel código. Para detectar llamadas a métodos que pueden afectar el consumo deenergía, es necesario realizar un análisis dinámico (es decir, realizar un perfil de laaplicación en ejecución y registrar la frecuencia con la que se produce cada llamadade método y refactorizar estableciendo un umbral del número de invocaciones).
Moving too much data: El movimiento de datos representa la comunicación entreel procesador y la memoria. Si varias partes de las aplicaciones o diferentes aplica-
46
ciones acceden al mismo conjunto de datos, generalmente se llama y se almacenavarias veces la misma información. Incluso si dos memorias separadas necesitanlos mismos datos que se calcularon antes la mejor solución es usar cachés de nivelsuperior. Cuando se desarrolla una aplicación, algunas veces los diferentes méto-dos necesitan datos que hayan sido guardados previamente por otro método (porejemplo, al consultar los métodos de lectura y escritura correspondientes). Los desa-rrolladores pueden reducir el consumo de energía usando una táctica similar a losaplicados para In-line method: los métodos que solo leen datos tienen que ser re-emplazados por el método que calcula los datos que se recuperarán (el uso de CPUconsume menos energía que el acceso a la memoria Barroso and Holzle [2007]).
Immortality bug: Describe la reaparición de una aplicación después de que el usua-rio la cerrara explícitamente. Una aplicación podría crear otra instancia de sí mismaal recibir la señal de cierre del sistema operativo, o bien, otra aplicación la monitoreay la reinicia inmediatamente después de su cierre (p. Ej., MediaServer2 o Google-Maps3). La detección de este comportamiento no es una tarea fácil, pero se puederesolver utilizando un número persistente de reinicios. Este número se compara conun número que indica los reinicios máximos consecutivos después de los cuales setermina el "ciclo de reinicio"
Redundant storage of data: Esta es la situación en la que diferentes métodos al-macenan los mismos datos en la memoria en lugar de compartirlos. Entonces, esnecesario identificar los métodos de almacenamiento de datos y compararlos paraencontrar aquellos que almacenan los mismos datos. Después de esta detección, sepueden combinar los métodos que almacenan los mismos datos.
Using expensive resources: Los desarrolladores deben tener en cuenta las diferen-tes alternativas para utilizar los recursos más baratos disponibles, por ejemplo losdatos de posicionamiento global mediante WiFi consume menos energía que el usodel GPS para el mismo objetivo. Entonces, los desarrolladores deben conocer el con-sumo de cada alternativa diferente. Si se encuentra un recurso costoso de energíase debe verificar si sería posible reemplazarlo por otro.
Finalmente, Gottschalk et al. [2012] demuestra que la detección de Code Smells es via-ble en la práctica utilizando GReQL (lenguaje de consulta de grafos) para mapear Co-de Smells a consultas de grafos Kullbach et al. [1999]. Particularmente, Gottschalk et al.[2012] representa el código fuente usando TGraphs Ebert et al. [2008] que son grafos diri-gidos con nodos y vértices tipados, valorados y ordenados. Los TGraph se acompañan detecnologías basadas en metamodelos para definir, manipular, analizar, consultar, visuali-zar y transformar grafos. Por otro lado, GReQL es un lenguaje de expresión declarativapara analizar TGraphs, que se puede aplicar a diversos servicios de ingeniería inversa,por ejemplo cálculo de referencias cruzadas, métricas de software, división de progra-mas, etc. Sin embargo, aún se requiere una mayor validación de las técnicas presentadasy una estimación del posible ahorro de energía para mostrar las ventajas y limitacionesdel enfoque. Esto significa que los beneficios de refactorizaciones específicas deben de-mostrarse en trabajos futuros.
2https://code.google.com/p/android/issues/detail?id=67653goo.gl/5RAzSmcontent_copyCopy short URL
47
En líneas similares, en Thiagarajan et al. [2012] se presenta un análisis del consumo deenergía producido por la navegación web. A pesar del hecho de que Thiagarajan et al.[2012] no se trata de HPC para dispositivos Android, evalúa el consumo de energía paraactividades comunes en aplicaciones móviles lo cual es interesante para nuestro trabajo.Específicamente, evalúa la energía utilizada por un navegador móvil para cargar pági-nas web utilizando páginas web populares como Amazon o Facebook, con y sin utilizarel caché del navegador. Entonces, Thiagarajan et al. [2012] estudia en detalle el consu-mo de energía de cada tipo de elemento cargado en una página web: JavaScript, CCS eimágenes. Además, analiza los beneficios de utilizar Offloading para representar páginasweb en dispositivos móviles. Los resultados indican que la creación de un contenido encaché del sitio web no evita el tráfico de red, ya que hay contenido dinámico que no sepuede almacenar en caché. Sin embargo, el consumo de energía es mayor cuando no serealizó el almacenamiento en caché. Teniendo en cuenta los elementos individuales, losresultados muestran que renderizar imágenes toma una fracción significativa de la ener-gía total de renderizado, JavaScript consume más energía cuando los archivos Javascriptson grandes y complejos, el costo de energía de los archivos CSS depende de la cantidadde elementos de estilo utilizados. Luego, para reducir la cantidad de consumo de ener-gía Thiagarajan et al. [2012] propone pautas para el desarrollo web móvil. Estas buenasprácticas incluyen:
Reducir el consumo de energía de JavaScript: reducir los JavaScripts en una páginamóvil para contener solo las funciones utilizadas por la página.
Reducir el consumo de energía de CSS: reemplazar varios archivos CSS con solo un
archivo CSS que contenga solo las reglas requeridas por la página puede reducir
significativamente la energía consumida (por ejemplo, la página de Apple redujo
su consumo de energía en un 40% con esta refactorización).
Consumo de energía de las imágenes: el formato JPEG es el formato con mayor
eficiencia en el consumo de energía para todos los tamaños de imagen probados
(este formato consume entre un 20% y un 30% menos de energía).
Como mencionamos anteriormente, Thiagarajan et al. [2012] evalúa el uso de la técnicade Ofloading para reducir el consumo de energía de renderizar páginas web en dispo-sitivos móviles. Al usar un proxy front-end que cambia el tamaño de las imágenes paraadaptarse a la pantalla del teléfono se puede reducir el consumo de energía, especialmen-te en sitios que no tienen una versión móvil. A pesar de estas mejoras espectaculares, estatáctica tiene algunas limitaciones: en primer lugar, los usuarios pierden la capacidad deacercar rápidamente las imágenes (con este enfoque, un acercamiento requiere descargarla parte ampliada de las imágenes). En segundo lugar, el contenido enviado cifrado me-diante SSL no puede ser reducido por el proxy. Por otro lado, el uso de un servidor deback-end para la descarga no es viable debido a la energía necesaria para transmitir orecibir datos a través de las radios (WiFi o 3G).
Este conocimiento se puede complementar con la evaluación del costo de envío, recep-ción y recolección de información a través de la red WiFi Li and Halfond [2014]. La prin-
48
cipal conclusión de Li and Halfond [2014] es que a pesar de asignar memoria no es gratisy los desarrolladores deben evitar asignar memoria, recolectar datos y transferir gran-des mensajes (1,000 bytes) es beneficioso en términos de uso de energía. Luego, a partirde estos trabajos, los desarrolladores proporcionan una guía de buenas prácticas paradesarrollar páginas web y sus contenidos.
En este contexto ADEL (Automatic Detector of Energy Leaks) Zhang et al. [2012a] presen-ta un software para detectar fugas de energía de comunicaciones de red innecesarias. Seproduce una pérdida de energía cuando las aplicaciones usan energía para realizar tareasinútiles. Los autores mejoraron el consumo de energía de seis aplicaciones en un 57% ydetectaron cuatro causas comunes de pérdidas de energía:
Interpretación errónea de la semántica de API en la devolución de llamada: unaaplicación que crea un subproceso de descarga separado puede no matar el sub-proceso y puede seguir descargando después de que la aplicación finalice.
Comportamiento de actualización de datos ineficaz: un widget que actualiza su
estado ya sea que la pantalla esté activa o no.
Descargas repetitivas: una aplicación que no almacena en caché el contenido que se
necesita varias veces.
Precarga anticipada agresiva: un esquema de captación previa realmente agresivo
que no mejora la experiencia del usuario.
Estos dos trabajos muestran que el uso correcto de los recursos puede disminuir el con-sumo de energía en una aplicación. Entonces, tener conocimiento sobre los recursos y lasdiferentes tácticas para usarlos es crucial para los desarrolladores móviles. Según Höpf-ner and Bunse [2010], es posible rediseñar un sistema de software en el que los recursosde hardware disponibles se utilizan de forma eficiente en energía, reemplazando recur-sos que consumen demasiada energía por uno o más recursos que optimizan el uso deenergía en aplicaciones locales y distribuida. Höpfner and Bunse [2010] analiza posiblessustituciones en torno a tres recursos:
CPU - Comunicación: una alta carga de CPU puede ser reemplazada por transferen-cia de datos y comunicación. Los cálculos con uso intensivo de la CPU se puedenenviar a un servidor o distribuirse entre varias computadoras. Además, uno puedereducir la transmisión de datos mediante la compresión, que, sin embargo, requiereun uso adicional de la CPU. La compresión de los datos a transmitir a veces requieremás energía que la transmisión de datos sin comprimir, ya que comprimir la infor-mación implica un costo de energía para la compresión y la descompresión. Por lotanto, es importante considerar la información sobre el contexto de la implementa-ción. Las refactorizaciones se pueden aplicar utilizando el patrón de estrategia bienconocido, lo que permite a la aplicación decidir dinámicamente si se usa compre-sión o no.
49
CPU - Memoria: la sustitución de la carga de la CPU por acceso a la memoria seconoce como la materialización de las vistas en el área de los sistemas de bases dedatos. Por lo general, representa la decisión de almacenar resultados temporales.
Memoria - Comunicación: las réplicas y los sistemas de caché pueden reducir la can-
tidad de comunicación. Sin embargo, la replicación completa solo reduce la eficacia
de la comunicación, mientras que las cachés de almacenamiento dependen de la ca-
pacidad de reutilizar los datos en caché. Los datos disponibles en un dispositivo no
deben transmitirse, pero los datos redundantes pueden estar desactualizados, por
lo que se requieren mecanismos de sincronización para comunicarse con el servidor
y recibir dichas actualizaciones.
Como conclusión, Höpfner and Bunse [2010] afirma que el uso de la CPU requiere menosenergía que el uso de memoria (primaria y secundaria), mientras que la comunicación dered requiere más energía que las otras dos.
Un trabajo muy interesante es Li and Gallagher [2016] que propone un framework para
optimizar el consumo de energía en aplicaciones móviles. El framework propone una ba-
se para la optimización de código mediante herramientas automáticas, siendo el primero
que logra esto para un lenguaje de alto nivel como Java. En un estudio de caso la eva-
luación experimental muestra un ahorro del 6,4% a l50,2% del consumo de energía de
la CPU. Este framework utiliza las siguientes estrategias de refactorización de códigos:
desdoblado de ciclos, desencadenamiento de ciclos, combinación de If, In-Line method,
eliminación de sub-expresiones comunes, propagación constantes, extracción de código
invariante en ciclo, eliminación de variables de inducción y reemplazo por función de
biblioteca.
Como mencionamos anteriormente, las aplicaciones móviles actuales requieren recursosde hardware y conectividad de red lo que aumenta el consumo de energía. Las técnicasde diseño de software para el ahorro de energía no solo se pueden aplicar al CPU, a lamemoria y al uso de la red, sino también a la evaluación de reasignación de métodosinternos y la descarga de métodos. Corral et al. [2015] evalúa dos técnicas de diseño desoftware diferentes: reasignación de método, que se refiere a la ubicación de fragmentosde código en diferentes ámbitos de ejecución dentro de un único objetivo (por ejemplo,nivel de kernel, nivel de aplicación, nivel compartido de biblioteca) y descarga de méto-do, que hace referencia a la ubicación de tareas en recursos externos. Aunque este trabajoevalúa el uso de Offloading como una forma de reducir el consumo de energía, su ob-jetivo es analizar la reasignación de métodos y la refactorización de aplicaciones paraaprovechar este análisis. Usando este análisis, se recomienda una reorganización de lasclases y métodos a través de los diferentes niveles de la pila de software. Finalmente,utilizando estos ámbitos, los autores evalúan los siguientes cinco benchmarks:
N-body: Realiza muchas simulaciones que requieren patrones de acceso a memoriapresentes en muchas operaciones como representaciones de imágenes.
50
Fasta: Genera y escribe secuencias aleatorias de ADN en una estructura de matriz.
Por lo tanto, presenta diferentes instrucciones en la administración de arreglos.
Chameneo-redux: Solicita encuentro simétrico de thread por lo que ejerce caracte-
rísticas importantes sobre el uso de threads.
Árboles binarios: asigna y desasigna árboles binarios ejerciendo la gestión de las
estructuras de datos.
Fannkuch-redux: accede a través de índices a una secuencia de enteros y genera
diferentes permutaciones. Luego, evalúa las operaciones altamente vinculadas a
E/S y el uso de CPU.
Para evaluar estos benchmarks en los diferentes ambientes los autores varían el valorde la entrada de datos N. Al analizar todas las combinaciones, concluyen que la energíaconsumida por Native Code tiende a ser similar a la del código de Java para valores pe-queños de N. Sin embargo, C siempre es más eficiente que Java para cualquier valor deN. Esto indica que la eficiencia energética en la utilización de recursos es mejor cuandolos métodos se ejecutan directamente en el shell del sistema operativo. En cuanto a Of-floading de métodos, concluyen que solo funciona mejor si los datos involucrados en laejecución son altos. Como conclusión, dependiendo de las necesidades computacionalespuede ser recomendable reasignar o enviar un método para ahorrar energía (hasta el 90%de la energía ahorrada).
Finalmente, otro recurso ampliamente utilizado para ejecutar aplicaciones en dispositi-vos móviles es utilizando técnicas de threading. Sin embargo, existen diferentes alternati-vas para desarrollar aplicaciones de múltiples threads y estas alternativas consumen dife-rentes cantidades de energía. Luego, en Pinto et al. [2014] los autores evalúan el consumode energía de diferentes alternativas de construcciones de gestión de threads y evalúan larelación entre el número de threads, las estrategias de división de tareas, el volumen dedatos y el consumo de energía. Para evaluar los diferentes aspectos, los autores utilizanvarios benchmarks conocidos:
Knucleotide: Benchmark de uso intensivo de memoria sin puntos de sincroniza-ción.
Maldebrot: Benchmark intensivo de CPU sin puntos de sincronización.
Spectralnorm: Benchmark de uso intensivo de CPU que sincroniza los threads uti-
lizando una barrera.
Imagenes más grande: Benchmark intensivo de E/S que tiene dos puntos de sin-
cronización.
N-queens: Benchmark intensivo de CPU sin puntos de sincronización.
51
Sunflow: rendering de imágenes.
Xalan: Benchmark de procesamiento de documentos.
H2: Benchmark de modelo de transacciones bancarias.
Una de las principales conclusiones es que el consumo de energía aumenta a medida que
aumenta el número de subprocesos, y luego disminuye gradualmente a medida que el
número de subprocesos se aproxima al número de núcleos de CPU, dibujando una cur-
va Λ. Además, en la mayoría de los benchmarks que usan técnicas de subprocesamiento
deberían mejorar el tiempo de ejecución, pero, como mencionamos anteriormente, el con-
sumo de energía aumenta a medida que aumenta el número de subprocesos. Entonces,
en este contexto más rápido no implica más verde. Los autores también evalúan tres esti-
los de programación diferentes para aplicaciones de múltiples threads: ForkJoin, Thread
y Executor. Concluyen que para aplicaciones intensivas de E/S, el tipo Thread tiene el
mejor consumo de energía, mientras que el ForkJoin tiene el peor consumo de energía.
Con respecto a la división de tareas, los hallazgos revelan que para ForkJoin las cargas de
trabajo asimétricas en aplicaciones centradas en datos son más amigables con la energía
que las cargas de trabajo simétricas. Además, se evaluó el ancho de forking y los autores
determinaron que un ancho de forking excesivo puede aumentar el consumo de energía.
Es importante mencionar que los experimentos asociados a la división de tareas no se
evaluaron para otros estilos porque sus patrones de programación no caen naturalmente
en estos estilos de división de tareas. Finalmente, la última contribución de ese trabajo
indica que el tamaño de los datos tiene un papel importante en el consumo de energía.
Como primera conclusión, determinaron que la relación entre el tamaño de los datos y el
consumo de energía sigue una curva convexa (mayor tamaño de datos, más consumo de
energía por unidad de datos).
Como conclusión, la Tabla 3.3 resume los trabajos detallados en esta sección. Las colum-nas de la Tabla son:
Nivel: indica en qué nivel se aplican las refactorizaciones (nivel de aplicación, nivelde hardware o nivel del sistema operativo).
Objetivo: detalla qué característica se evalúa en cada trabajo. Los trabajos presenta-
dos en esta sección evalúan el consumo de energía (batería) o el tiempo de ejecución
(performance).
Enfoque: muestra qué enfoque se define en el trabajo.
Casos de estudio: es el número de estudios de casos a través de los cuales se evalúa
el enfoque.
52
Paper Nivel Objetivo Operación
Casosde es-
tudioMejora Evaluación
Cheng-Minet al. [2011]
Aplicación PerformanceComparas Native code y
Java12 -158% - 99.98% Benchmarking
Sangchuland Wook
[2010]Aplciación/Hardware Performance
Comparas Native code yJava
5 63% - 90%Comunicación/
Cálculo/Memoria
Tonini et al.[2012]
Aplicación PerformanceEvalua la misma
funcionalidad con códigodiferente
3 22% - 65%Google’s
guidelines
Gottschalket al. [2012]
Aplicación BateriaDetecta y refactoriza Code
Smalls7 - Code smells
Thiagarajanet al. [2012]
Aplicación BateriaEvalua operaciones
comunes en web browsers3 20% - 30% Web browsers
Li andHalfond
[2014]Hardware Bateria
Evalua el tamaño óptimode los mensajes enviados
por la red1 -
Comunicacióny memoria
Zhang et al.[2012a]
Aplicación BateriaDetecta lagunas de
consumo de energía4 up to 57% Comunicación
Corral et al.[2015]
Hardware BateriaCompara Java code,
Native Code y regular C5 up to 90% Benchmarking
Pinto et al.[2014]
Aplicación/Hardware BateriaEvalua diferentes técnicas
de administración dethreads
8 -Técnicas deThreading
Höpfnerand Bunse
[2010]Sistema Operativo Bateria
Propone estrategias dereemplazo de recursos
3 - Uso de recursos
Cuadro 3.3: Resumen de guías
53
Mejora: muestra el porcentaje de mejora en el consumo de energía. Es importante
destacar que algunos autores no han informado los resultados exactos de sus enfo-
ques, que es una limitación importante en esta área.
Evaluación: indica el área de software/hardware cubierta por cada trabajo.
Podemos afirmar que estos trabajos contribuyen a producir guias de desarrollo o a detec-tar buenas prácticas para desarrollar aplicaciones móviles de buena calidad para apro-vechar los recursos de los dispositivos móviles. Como podemos ver, estos trabajos sepueden combinar para desarrollar diferentes tipos de aplicaciones móviles. En esta área,varios trabajos se centran en Java porque su popularidad y porque es un lenguaje conmuchas características interesantes para el software móvil, incluyendo portabilidad, se-guridad, robustez y simplicidad. Aunque el uso del código nativo es más eficiente enalgunos casos, existen numerosos desarrollos en Java para dispositivos móviles y mu-chos desarrolladores calificados en este lenguaje. De hecho, las estadísticas basadas en elrepositorio de aplicaciones de Google Play muestran que el 52.98% de las aplicaciones deAndroid disponibles, el 88.76% de las principales aplicaciones de Android y el 75.62% delas nuevas aplicaciones de Android usan la biblioteca de soporte de Android4, que estádesarrollada en Java. Sin embargo, una de las limitaciones de este catálogo de trabajoscientíficos es que el impacto real de aplicar estas prácticas en aplicaciones reales no siem-pre se evalúa. Luego, es necesario evaluar este impacto junto con el equilibrio entre elesfuerzo del desarrollador y el beneficio de su aplicación, teniendo en cuenta al mismotiempo los criterios de calidad tradicionales, como la reutilización y la modificabilidaddel código.
3.3.2. Servidores y computadoras personales
Estamos especialmente interesados en el nivel de código fuente de alto nivel ya que nues-tro enfoque apunta a mejorar el consumo de energía a través de la refactorización de có-digo. En esta línea, Sahin et al. [2012] comienza la evaluación en el desarrollo de alto nivelya que evalúa el consumo de energía de los patrones de diseño en servidores. En Sahinet al. [2012], los autores crearon una nueva herramienta para medir el consumo de ener-gía de una aplicación en ejecución y para generar el mapeo entre el uso de energía y lospatrones de diseño. Para mapear patrones de diseño y consumo de energía los autoresseleccionaron 15 patrones de diseño, 5 en cada una de las tres categorías: creacional, es-tructural y conductual. Utilizando estos patrones de diseño, los autores concluyeron queel uso de patrones de diseño puede aumentar y disminuir la cantidad de energía consu-mida. Sin embargo, los patrones de diseño dentro de una categoría no afectan el uso deenergía de manera similar, y los impactos en el uso de energía no pueden ser estimadosartefactos de este nivel.
Con respecto al diseño detallado de la aplicación, Dhaka and Singh [2016] estudia hasta
qué punto la corrección de un diseño incorrecto afecta el consumo de energía en función
4http://www.appbrain.com/stats/libraries/details/support_lib/android-support-library
54
de Code Smells. La investigación muestra que las permutaciones de eliminación de Code
Smells producen diferentes niveles de consumo de energía para las versiones de softwa-
re resultantes. Dhaka and Singh [2016] analiza el impacto sobre el consumo de energía
de la eliminación de tres de los Code Smells más comunes (God Class, Feature Envy y
Brain Method), individualmente y secuencialmente. Los resultados muestran tendencias
uniformes de energía en todas las aplicaciones cuando se crean versiones refactorizadas
eliminando estos Code Smells. También se observa que las versiones refactorizadas gene-
radas aplicando God Class, Feature Envy y Brain Method generan un consumo mínimo
de energía en comparación con las generadas al aplicar otras secuencias. Debemos des-
tacar que el código correcto genera una nueva versión que consume más energía que la
versión original. Esto significa que Dhaka and Singh [2016] propone la mejor secuencia
para generar el mejor código y consumir la menor cantidad de energía posible, siempre
priorizando el diseño sobre el consumo de energía.
En este contexto, hay trabajos que miden, controlan y comparan el consumo de energía delenguajes, bibliotecas, aplicaciones y algoritmos específicos. Noureddine et al. [2012] pre-senta la arquitectura POWERAPI que, junto con los módulos de energía, permite a losdesarrolladores calcular el consumo de energía de procesos y aplicaciones. Los primerosresultados muestran en tiempo de ejecución el consumo de energía de aplicaciones y al-goritmos. Algunos resultados indican que Java, usando las opciones predeterminadas, esbastante eficiente en términos de energía en comparación con otros lenguajes de progra-mación. Los autores también infieren que la eficiencia energética del lenguaje Pascal estáen el mismo nivel que C o C++. Sin embargo, otros resultados son más interesantes: Perles el lenguaje que consume más energía, OCaml es el segundo, luego Python y finalmenteProlog.
Trabajos más específicos evalúan el uso de prácticas comunes al desarrollar aplicaciones.
Por ejemplo, Procaccianti et al. [2016] evalúa dos prácticas para el desarrollo de software
energéticamente eficiente: el uso de consultas eficientes y poner la aplicación en reposo.
Por un lado, la limitación de la utilización de mecanismos de indexación u operaciones de
ordenamiento innecesarias (uso de palabras clave ORDER BY) puede aumentar el consu-
mo de energía de nuestras consultas. Por otro lado, un uso adecuado de la función Sleep
permite que la aplicación reduzca el uso de la CPU y mejore su eficiencia energética. En
general, los resultados muestran un impacto significativo y consistente de ambas prác-
ticas sobre el aumento de la eficiencia energética de las materias seleccionadas: Apache
WebServer y MySQL Database Server.
Otros trabajos interesantes estudian el uso de diferentes estructuras de datos y coleccio-nes. Primero, Hasan et al. [2016] evalúa el consumo de energía de operaciones comunesrealizadas en colecciones como Java List, Map y Set (por ejemplo, inserción, iteración,acceso aleatorio). Los resultados muestran que los tipos de datos alternativos para estasabstracciones difieren significativamente en términos de consumo de energía dependien-do de las operaciones. Los autores encontraron que elegir el tipo de colecciones incorrectopuede consumir 300% más de energía que la colección más eficiente. En segundo lugar,
55
Manotas et al. [2014] describe un soporte automatizado para optimizar el uso de energíade las aplicaciones mediante refactorings a nivel de código. Manotas et al. [2014] afirmaque las muchas capas de abstracción en las aplicaciones y las interacciones entre hard-ware y software sugieren que es difícil predecir cómo los refactorings afectan el consumode energía, que de hecho es nuestro objetivo en esta tesis para el caso de HPC en CPU.En consecuencia, Manotas et al. [2014] propone un framework que automáticamente a)genera versiones diferentes del mismo código combinando todas las instancias de colec-ciones, b) realiza ejecuciones supervisadas por energía de todas las versiones generadas,c) analiza los resultados, y d) genera una versión optimizada del original código. Sinembargo, el principal problema de este trabajo de investigación es que la recopilación yel procesamiento de muestras de energía puede tomar muchas horas dependiendo deltiempo de ejecución de la serie de pruebas, el número de repeticiones y el espacio deinvestigación.
3.4. Resumen
Los trabajos discutidos en este capítulo contribuyen a la introducción de dispositivos mó-viles en entornos computacionales como Grids y Clouds, tradicionalmente compuestosde PC y servidores. En la Sección 3.1 presentamos y analizamos diferentes trabajos cuyoobjetivo principal es ofrecer técnicas de Offloading de aplicaciones para ejecutar aplica-ciones intensivas en dispositivos móviles. El uso de Offloading presenta varias ventajas:primero, los usuarios pueden usar sus dispositivos como computadoras que ejecutanaplicaciones de recursos intensivos, mejorando el tiempo de ejecución de la aplicación, lalatencia o el consumo de energía; segundo, los científicos pueden aprovechar los sensoresy otros recursos en áreas remotas procesando datos en servidores. La principal limitaciónen esta área es que el procesamiento adicional necesario para determinar qué tareas soncandidatas a ser descargadas y cuál de estas tareas debe descargarse agrega tiempo adi-cional de ejecución y consumo de energía. Además, varios enfoques necesitan conoceralgunos parámetros, como los recursos necesarios para una tarea o la energía consumidapor una tarea para tomar decisiones, pero estos parámetros generalmente son desconoci-dos.
En la Sección siguiente (Sección 3.2) se presentaron diferentes enfoques para programar
tareas en Grid móviles. Este tipo de trabajos es una contribución importante para la co-
munidad científica, ya que hay miles de millones de dispositivos móviles en todo el mun-
do, lo que genera un increíble poder de cómputo. Luego, al enviar tareas pequeñas a
dispositivos móviles los científicos pueden ejecutar aplicaciones HPC sin la necesidad
de supercomputadoras costosas. Sin embargo, la mayoría de los trabajos en schedulers
distribuidos para áreas de dispositivos móviles son adaptaciones de trabajos anteriores
realizados para dispositivos fijos. Entonces, estas adaptaciones presentan numerosas li-
mitaciones y no consideran las peculiaridades del nuevo entorno relacionado con la falta
de fiabilidad de la conexión de los dispositivos móviles a la red, la cantidad limitada de
recursos disponibles y el suministro limitado de energía.
Finalmente, la Sección 3.3 muestra varias buenas prácticas para desarrollar aplicaciones
móviles. En esa Sección hay numerosos enfoques que investigan cómo reducir el consu-
56
mo de energía en dispositivos móviles (benchmarking, Code Smells, navegadores web,
entre otros). Además, la reducción de energía se puede realizar a nivel de aplicación, ni-
vel del sistema operativo y nivel de hardware. Sin embargo, todos estos estudios pueden
aplicarse para complementar cualquiera de los otros enfoques presentados anteriormen-
te. Esto significa que, teniendo en cuenta estas pautas y las buenas prácticas los desarro-
lladores pueden mejorar las técnicas de Offloading o las tácticas del Scheduler además
del código de la aplicación. Por ejemplo, al adaptar los sistemas HPC para que sean ami-
gables con la energía se puede mejorar la capacidad de un Grid, ejecutando así más tareas
con los mismos recursos. Además, saber qué operaciones consumen más energía puede
ser esencial para decidir si una tarea se ejecutará en un dispositivo móvil o fijo.
Además, varios intentos centrados en mejorar el consumo de energía de las aplicaciones
móviles se detallan en la Sección 3.3. Estos trabajos cubren varios temas y niveles (aplica-
ción, sistema operativo, hardware) que muestran la amplitud del área. Las aplicaciones
móviles se pueden mejorar teniendo en cuenta el uso de recursos (CPU, RAM, panta-
lla, etc.), el uso de la red, las funciones de red o los formatos de representación de los
diferentes elementos de la aplicación (imágenes, estilos, etc.). Como resultado, este inci-
piente área de investigación es extensa y, como tal, presenta interesantes líneas abiertas
de investigación. Como mencionamos anteriormente, las evaluaciones que se muestran
en la Sección 3.3 pueden ser útiles para tareas tan diversas como desarrollar aplicaciones
móviles, tomar decisiones en entornos computacionales, evaluar el impacto potencial de
una aplicación en un entorno de dispositivo móvil, entre otros.
Particularmente, la documentación operativa de Android tiene pautas para desarrollar
aplicaciones eficientes para dispositivos móviles, que cubre operaciones comunes tales
como getters/setters, loops y tipos de datos. De la misma manera, diferentes autores
evalúan el tiempo de ejecución y la mejora energética de la refactorización de algunas
malas prácticas bien conocidas llamadas Code Smellss. Sin embargo, estos trabajos tie-
nen algunas limitaciones: el primer trabajo solo se evalúa para las microoperaciones en
sí; luego, el impacto de aplicar estas pautas en aplicaciones reales no se evalúa; y, el se-
gundo no tiene evaluación experimental. Por otro lado, Thiagarajan et al. [2012] evalúa el
consumo de energía de los diferentes elementos de una página web individualmente y su
impacto en una página web real. Utilizando esa información, los desarrolladores pueden
evaluar diferentes intercambios de la aplicación de la guia propuesta. Aunque Thiagara-
jan et al. [2012] analiza el impacto de su enfoque en entornos reales, no puede emplearse
para el desarrollo de aplicaciones móviles de propósito general, lo cual es una limitación
significativa.
Otra área de investigación es HPC con dispositivos móviles. En esta área, una serie de
investigaciones evalúa el tiempo de ejecución o el consumo de energía. Una cantidad
considerable de trabajos evaluan el tiempo de ejecución de benchmarks conocidos y ope-
57
raciones de HPC, comparan diferentes lenguajes, pero ninguna evaluación hace experi-
mentos para evaluar las mejoras en aplicaciones reales. Por lo tanto, los desarrolladores
no pueden aprovechar efectivamente estos resultados al desarrollar aplicaciones. Final-
mente, en este contexto, una conclusión es que la mejora energética de diferentes micro-
benchmarks, que son parte de núcleos de aplicaciones científicas, junto con su impacto
en aplicaciones reales es un área inexplorada. Además, el análisis de refactorización se
puede complementar con un análisis de los trade-off de aplicar la refactorización en el
diseño de la aplicación contra el esfuerzo del desarrollador para aplicarlas. Además, co-
mo resultado secundario, se puede evaluar el impacto en el tiempo de ejecución, ya que
el consumo de energía y la ejecución del tiempo no tienen una relación lineal Rodriguez
et al. [2016a], Pinto et al. [2014].
Finalmente, este trabajo señala que varios problemas siguen abiertos. Por lo tanto, el usode dispositivos móviles como parte de un entorno distribuido, teniendo en cuenta el dise-ño y las mejoras del código para mejorar el rendimiento y el consumo de energía, puedeaumentar significativamente la cantidad de recursos disponibles. Como resultado, mejo-rar estas tres áreas principales diferentes (Offloading, schedulers distribuidos y modelosde desarrollo de software con eficiencia de energía) y combinarlas es un tema interesantetanto para la ciencia como para la industria.
58
Capıtulo 4
Micro-benchmarks y aplicaciones
Basado en una de las principales limitaciones para el desarrollo de aplicaciones para
dispositivos móviles, es decir, la capacidad limitada de las baterías, el objetivo princi-
pal de esta tesis es evaluar el consumo de energía de operaciones comunes en aplica-
ciones científicas para dispositivos móviles. Para minimizar el consumo de energía e,
indirectamente, el consumo de otros recursos como CPU y RAM, esta tesis busca encon-
trar la correspondencia entre las diferentes formas de implementar los mismos micro-
benchmarks y su correspondiente consumo de energía. Después de presentar nuestros
micro-benchmarks, discutimos el esfuerzo necesario para analizar y refactorizar los códi-
gos fuente.
Luego, la frecuencia con la cual los grupos de micro-benchmarks analizados aparecen en
aplicaciones reales puede verse en la Tabla 4.2, donde se estudian diferentes aplicacio-
nes científicas teniendo en cuenta las diversas operaciones presentes en ellas. Además, se
puede observar que estas aplicaciones son de gran importancia para la comunidad cientí-
fica ya que la mayoría de ellas se encuentran en un repositorio de aplicaciones de Satin1,
cuya utilidad se detallará en la Sección 4.2. Además, la Sección 4.1 explica el concepto
de micro-benchmark y sus peculiaridades en Java -el lenguaje de programación de alto
nivel de Android- y enumera y analiza cada grupo de micro-benchmarks seleccionados
para este trabajo. Como corolario, presentamos cómo los micro-benchmarks evaluados
también en aplicaciones científicas implementadas en servidores y qué aplicaciones re-
presentativas del usuario final real son particularmente probadas.
1http://gforge.cs.vu.nl/gf/project/ibis/scmsvn/?action=browse&path=%2Fapps%2Ftrunk%2Fsatin%2F
59
4.1. Micro-benchmarks
Algunos de los problemas más importantes para desarrollar aplicaciones para dispositi-
vos móviles son que, comparados con servidores potentes, sus capacidades son limita-
das en términos de capacidad de procesamiento de CPU y tiempo de batería. El objetivo
de este trabajo es mostrar la relación entre las diferentes formas de escribir los mismos
micro-benchmarks o las primitivas comunes, la mayoría de ellas utilizadas en aplicacio-
nes científicas basadas en Java, y su correspondiente consumo de batería (1). Como coro-
lario de la experiencia, derivamos pautas para programar tales primitivas en dispositivos
móviles de una manera consciente de la energía. Con estas pautas, el software científico
en particular y las aplicaciones en general pueden ser más eficientes en términos de uso
de la batería. Además, la mejora del uso de la batería generalmente conduce a mejores
tiempos de ejecución, Azeemi [2006].
Con esto en mente, elegimos ocho grupos de micro-benchmarks conocidos Bloch [2008,
2001], basando la selección en el uso recurrente de estas estructuras en aplicaciones cien-
tíficas. Estos grupos son copia de arreglos, creación de objetos, acceso a atributos de obje-
tos, manejo de Strings, manejo de excepciones, uso de tipos de datos primitivos, recorrido
de matrices y operaciones aritméticas. Los siguientes párrafos explican algunas de las ra-
zones por las que se seleccionaron estos grupos.
A lo largo del tiempo se han desarrollado diferentes bibliotecas para uso científico en
diversos lenguajes OO, como C++ y JavaHofschuster and Krämer [2004], Papadimitriou
et al. [2011]. Teniendo esto en cuenta, decidimos comparar la mejora del consumo de la
batería utilizando dichas bibliotecas para copiar un arreglo y evitar la implementación
manual de la misma funcionalidad.
Además, elegimos la creación de objetos no solo porque los objetos son el foco de la
programación OO, sino también porque la creación de objetos es una razón para la dis-
minución de la performance de la aplicación. Esta disminución de la pertformance se
debe a las costosas tareas de administración de memoria, por ejemplo, las realizadas por
el Garbage Collector en Java o la eliminación de objetos explícitos en C++, que recupera
la memoria de los objetos no utilizados. Como resultado, una cantidad excesiva de obje-
tos puede disminuir seriamente el rendimiento de la aplicación. En aplicaciones móviles,
estas tareas requieren energía para realizarse.
El siguiente grupo, invocación de método, se eligió por motivos similares: en la progra-
mación OO un método es una subrutina asociada a una clase. Como consecuencia, llamar
a un método es una operación común en aplicaciones OO. Esto nos llevó a analizar el con-
sumo de batería de llamadas a métodos que se utilizan para preservar la encapsulamiento
de objetos.
Por otra parte, las excepciones representan un mecanismo para el manejo de errores y se
60
usan comúnmente en los lenguajes que las soportan. Sin embargo, las excepciones pro-
ducen consumos generales que disminuyen la performance de la aplicación. En conse-
cuencia, trabajos como Lee et al. [2000] analizan los mecanismos para eliminar los costos
impuestos por los administradores de excepciones y nos motivan a medir su impacto en
el consumo de baterías.
Con respecto a estructuras de datos ampliamente utilizadas, las matrices son una estruc-
tura común en el software científico y tienen usos matemáticos y computacionales im-
portantes. Por ejemplo, transformaciones tridimensionales basadas en matrices Barisone
et al. [2001] y las multiplicaciones matriz-matriz son núcleos importantes en algoritmos
de álgebra lineal Nicolaos et al. [2012] Particularmente, basamos nuestro análisis en la
operación de recorrido de matrices.
El siguiente grupo de micro-benchmark es el uso de tipos de datos primitivos. La memo-
ria se desperdicia cuando las aplicaciones usan tipos de datos basados en objetos ya que
ocupan más memoria. Alternativamente, los tipos de datos primitivos usan la cantidad
mínima de bits necesarios para representar su valor. Luego, discutimos las ventajas de
usar tipos de datos primitivos contra el uso de tipos de datos de objeto.
Otro tipo de objetos importante en la programación son los objetos, la concatenación de
Strings es la operación de String más importante cuando se manioulan Strings de carac-
teres Christensen et al. [2003]. Por ejemplo, Hermelin et al. [2008] analiza el problema
de cubrir un conjunto de Strings S con un conjunto C de substrings en S (C cubre S si
cada string en S se puede escribir como una concatenación de las substrings en C). Por
último, con respecto al último grupo, históricamente varios estudios Vaidya [1990], Ba-
ron et al. [2006], Gurram and Agarwal [2007] han centrado sus esfuerzos en optimizar las
operaciones aritméticas o involucrar a un gran número de ellas.
A modo de resumen, la Tabla 4.1 presenta una breve descripción de los grupos de micro-
benchmak considerados.
Las siguientes subsecciones detallan cada grupo de micro-benchmark y mencionan algu-
nas características relevantes de Java, ya que es el lenguaje de programación de alto nivel
en el que se basa la plataforma Android. Los detalles sobre el alcance de cada grupo de
micro-referencia se discuten en las siguientes subsecciones.
4.1.1. Copia de arreglos
La mayoría de los lenguajes incluyen bibliotecas (una colección de rutinas precompila-
das) o funcionalidad incorporada cuyo objetivo principal es exponer la funcionalidad
común para su reutilización. Las bibliotecas son particularmente útiles para almacenar
rutinas usadas frecuentemente porque los desarrolladores no necesitan vincularlas explí-
citamente a cada programa que las usa. Un ejemplo paradigmático es la funcionalidad
61
Micro-benchmark Resumen
Copia de arreglos Compara el uso de System.arraycopy con la implementaciónmanual del mismo método
Creación de Objetos Compara el consumo energético de crear un nuevo objetocontra el consumo de reutilizar uno
Acceso a atributos deun objeto
Mide el consumo de batería de obtener el valor de un atributoa través de un método contra el consumo de obtenerlodirectamente
Manejo de Strings Compara la concatenación de Strings usando el operadot «+»contra el consumo de la concatenación utilizando la claseStringBuilder
Manejo deexcepciones
Compara el manejo de errores utilizando el mecanismo deexcepciones contra el manejo manual de un error
Uso de tipos de datosprimitivos
Mide el consumo energético de usar tipos de datos primitivosy de usar sus correspondientes wrappers
Recorrido de matrices Recorre una matriz de NxM por columnas y por filasOperacionesaritméticas
Evalua el consumo energético de sumar los distintos tipos dedatos numéricos
Cuadro 4.1: Grupos de micro-benchmark
para buscar y ordenar estructuras de datos. El uso de este soporte tiene ventajas signifi-
cativas sobre el uso de una implementación ad-hoc.
En primer lugar, al utilizar una funcionalidad incorporada los desarrolladores aprove-
chan el conocimiento de los expertos que escribieron la funcionalidad y la experiencia de
aquellos que la usaron antes que ellos. Una segunda ventaja es que los desarrolladores no
tienen que perder tiempo escribiendo funcionalidades comunes. Además, el rendimiento
de tales bibliotecas tiende a mejorarse con el tiempo. En particular, gran parte de la fun-
cionalidad incorporada de la plataforma Java se ha reescrito a lo largo de los años, lo que
ha producido mejoras notables en el rendimiento, Bloch [2001].
En esta línea, esta tesis compara el uso del método System.arraycopy con una solución
manual para la misma funcionalidad porque las estructuras de arreglos son una de las
estructuras más importantes en el software científico. Los programadores usan arreglos
en lugar de múltiples declaraciones de variables. Por ejemplo, en los arreglos de mate-
máticas se utilizan para representar polinomios.
4.1.2. Creación de objetos
La programación OO se basa en el almacenamiento de datos en conjuntos modulares
de elementos de información. En este contexto, un objeto es una instancia de una clase.
Entonces, la creación de objetos es inherente al paradigma porque diferentes entidades
62
con diferentes estados coexisten en la memoria en tiempo de ejecución. Además, la crea-
ción de objetos en la memoria y su mantenimiento siempre implican algún costo compu-
tacional porque ocurren varias cosas cuando se crea un objeto: la memoria se asigna, los
campos se inicializan a sus valores predeterminados y se invoca el constructor elegido.
Los desarrolladores a veces pueden evitar la creación de objetos nuevos mediante la re-
utilización de objetos de la misma clase que no se utilizarán después de restablecer sus
atributos. En consecuencia, analizamos el impacto en el consumo de batería que tiene la
creación de objetos sobre su reutilización. Como las posibilidades de evaluar este aspecto
son diversas, elegimos un objeto que representa una estructura de datos comúnmente
utilizada en la programación (científica): Listas. Por ejemplo, las listas se utilizan como
partes constituyentes de muchas otras estructuras de datos, como pilas, colas y sus va-
riantes. En esta tesis, comparamos los niveles de consumo de batería al crear un nuevo
objeto List (instancias de java.util.ArrayList) contra la reutilización de una lista existente.
Para reutilizar una lista existente, usamos un método de instancia para restablecer la lista
a su estado inicial (vacío).
4.1.3. Acceso a atributos de un objeto
En el paradigma de programación OO, los objetos tienen un conjunto de propiedades o
atributos, y un conjunto de métodos que implementan su comportamiento. Una de las
prácticas recomendadas por el paradigma es ocultar información. Esta práctica indica
que cada clase debe proporcionar ciertos métodos públicos conocidos como accessors
(getters), que podrían ser referidos por otras clases para acceder a los campos declara-
dos en la clase. Además, esta práctica proporciona diseños más flexibles. Por ejemplo, si
una aplicación tiene una clase con un atributo de distancia, que se mide en pulgadas, y
los desarrolladores deben cambiar esa representación a centímetros, los desarrolladores
pueden introducir ese cambio utilizando getters. Si los desarrolladores no usan un getter
y un setter, tendrán que rastrear cada uso de la clase y convertir entre las unidades allí.
Si bien esta práctica da como resultado diseños más flexibles, que son fáciles de compren-
der y mantener, la invocación de métodos getter -como cualquier otro tipo de método-
también tiene un impacto negativo en el rendimiento de la aplicación y consume batería.
Para nuestros propósitos, medimos el consumo de batería para obtener un valor de atri-
buto, que en un caso se realiza a través de una llamada de método, y en el otro se realiza
directamente, es decir, sin tener la funcionalidad encapsulada en un método.
4.1.4. Manejos de Strings
Los Strings son, en general, la principal forma de representar y manejar texto o datos en
los programas. Las aplicaciones Java a menudo usan el tipo de datos String para guardar
63
y leer datos, mostrar mensajes al usuario, entre otros usos. Normalmente, la concatena-
ción de estos Strings es necesaria para crear fragmentos de datos más grandes a partir de
fragmentos de datos más pequeños.
Luego, trabajamos con concatenación usando el operador "+" utilizado por la clase String
y usando el método asociado a la clase Java StringBuilder. Nuestra hipótesis es que la
clase String no es una clase amigable con la energía cuando el valor de la String necesi-
ta modificarse con frecuencia. Esta hipótesis se basa en la afirmación de que los Strings
en Java son objetos inmutables, es decir, sus valores no se pueden cambiar después de su
creación, entonces el uso del operador "+" tiene que crear un nuevo objeto cada vez que se
ejecuta. Resumiendo, declaramos que el uso del operador "+" o cualquier otro operador
que modifique el valor de la String no es eficiente para una gran cantidad de ejecuciones.
Según Bloch [2001]), el operador de concatenación de Strings es una forma rápida y con-
veniente de combinar algunas Strings en uno, por ejemplo, para generar una única línea
de salida o para construir la representación de String de un objeto pequeño. Sin embargo,
como mencionamos antes, esta práctica tiene un efecto negativo en el rendimiento.
Por otro lado, algunos autores sostienen que los compiladores optimizan este tipo de
operaciones ineficientes. Pero, a pesar del hecho de que el operador de concatenación de
Strings está optimizado por el compilador utilizando la clase StringBuilder, operar con
la clase String y su operador "+" es una práctica ineficiente ya que cada concatenación
con este operador implica una creación de un Instancia de StringBuilder, que consume
energía y representa una disminución del rendimiento.
En consecuencia, esperamos una mejora utilizando la clase StringBuilder en el código de
la aplicación. Es importante mencionar que, a pesar de que estas y otras buenas prácticas
son bien conocidas por la comunidad de desarrolladores, se ignoran en varios casos, por
ejemplo, la agenda de Android usa el operador "+" para unirse a Strings.
4.1.5. Manejo de excepciones
El manejo de excepciones es el mecanismo utilizado para administrar cualquier evento
inesperado como la división por cero o el acceso al puntero nulo. Básicamente, cuando
un objeto experimenta una condición que no puede manejar, el objeto crea y lanza una
excepción que tiene que ser capturada por alguien más en la pila de llamadas. En otras
palabras, el entorno de tiempo de ejecución de Java busca hacia atrás a través de la pila de
llamadas para encontrar cualquier método que pueda manejar la excepción. Finalmente,
los errores se pueden agrupar y categorizar mejor. La principal ventaja del mecanismo
de manejo de excepciones es separar el código de manejo de errores del código regular,
lo que mejora la legibilidad y la modificabilidad del código.
64
Sin embargo, el mecanismo de manejo de excepciones tiene un efecto negativo en el ren-
dimiento de la aplicación. En primer lugar, hay poco interés entre las máquinas virtuales
Java (JVM) en la optimización del manejo de excepciones porque este mecanismo fue
diseñado para situaciones excepcionales. Además, escribir código dentro de un bloque
catch evita que el compilador/máquina virtual realice algunas optimizaciones porque
las excepciones y el manejo de excepciones son situaciones excepcionales, es decir, códi-
go que rara vez se ejecuta. Esto significa que si este código está optimizado, representará
un pequeño beneficio para el rendimiento. Además, determinar dónde se origina el flujo
de control no es fácil o es casi imposible para el optimizador. Más importante aún, lanzar
una excepción implica la creación de objetos, que es una operación que consume recursos
y, por lo tanto, batería.
Por lo tanto, este trabajo analiza dos métodos que son funcionalmente equivalentes, uno
que utiliza excepciones para responder a una situación específica y otro que utiliza ex-
cepciones para responder a la misma situación. En otras palabras, mostramos la ventaja
-en términos de uso de energía- de usar excepciones solo en situaciones que el objeto no
puede manejar. Por ejemplo, detectar una división por cero es una tarea sencilla para los
programadores y, en muchas aplicaciones, saben cómo la aplicación debe responder a
esta situación (por ejemplo, devolver un código de error, un mensaje de error o un va-
lor no válido o pedir nuevamente los valores a dividir). Entonces, es fácil ver que hay
situaciones en las que los desarrolladores pueden evitar el uso de excepciones.
4.1.6. Uso de tipos de datos primitivos
En el pasado, los lenguajes de programación solo tenían tipos de datos primitivos (como
enteros, booleanos y strings) y procedimientos. Los desarrolladores podían definir sus
propios procedimientos y encadenarlos para crear programas más grandes. Entonces, la
aparición de tipos abstractos fue un salto cuántico en la programación de software.
No obstante, Java tiene tipos de datos primitivos que no son clases per se. Además de ca-
da uno de estos tipos de datos primitivos clásicos, en Java, tiene una clase correspondien-
te (por ejemplo, int -> Entero). Con respecto a la memoria, los tipos de datos primitivos
solo usan la cantidad de bits necesarios para representar su valor, mientras que el alma-
cenamiento de la misma información utilizando contenedores requiere más memoria.
Como resultado, este grupo mide el consumo de batería utilizando tipos de datos primi-
tivos frente al consumo de la batería utilizando sus clases de envoltura correspondientes.
Sin embargo, todos estos envoltorios son clases inmutables. Luego, debemos tener en
cuenta que el uso de wrappers no solo tiene las restricciones evaluadas en este grupo,
sino también los problemas evaluados en la Subsección 4.1.4 (cada vez que se modifica
un valor, debe crearse un nuevo objeto)
65
4.1.7. Recorrido de matrices
Las matrices son estructuras de datos que tienen muchos usos diferentes en matemáticas,
como representar problemas de manera conveniente y compacta, ayudar a resolver pro-
blemas con ecuaciones lineales y diferenciales, y coordinar cambios en algunos tipos de
integrales. Además, las matrices son una herramienta útil para estudiar grupos finitos.
Cada grupo finito tiene una representación como un conjunto de matrices invertibles; el
estudio de tales representaciones se llama teoría de la representación. Además, en la teo-
ría de grafos una matriz de adyacencia puede asociarse naturalmente a cada grafo donde
la posición [i, j] indica si el vértice [i] está conectado con el vértice [j]. Con esta matriz, por
ejemplo, se puede calcular el número de vecinos de un vértice particular.
Las matrices se usan en ingeniería, física, informática y otras áreas. Por ejemplo, las ma-
trices se utilizan para almacenar cualquier tipo de datos para el manejo de información
(es decir, tipos de datos u objetos primitivos) y son una estructura común en cualquier
aplicación 3D, donde a menudo se usan para aplicar transformaciones a imágenes 3D.
Además, la mayoría de los algoritmos de minería de datos utilizan matrices, ya que es
fundamental tanto para la teoría como para el manejo de datos. Como resultado, los pro-
gramadores no pueden evitar estas estructuras. Como las matrices son matrices multidi-
mensionales, nuestro alcance son matrices bidimensionales con pruebas de micro-puntos
de referencia donde las matrices [NxM] se recorren por filas y columnas.
4.1.8. Operaciones aritméticas
Las operaciones aritméticas son una de las primitivas más habituales en las aplicacio-
nes. Esto se ilustra mediante aplicaciones de gestión, aplicaciones de contabilidad, apli-
caciones de compresión de datos y aplicaciones matemáticas. Además, las aplicaciones
científicas con operaciones aritméticas son muy comunes y a menudo necesitan millo-
nes de cálculos. Como resultado, cuanto más eficientes en energía sean las operaciones
aritméticas, menor será el consumo de la batería.
Las operaciones aritméticas básicas son suma, resta, multiplicación y división, aunque
son posibles operaciones más avanzadas, como manipulaciones de porcentajes, raíces
cuadradas, exponenciación y funciones logarítmicas. Por otra parte, una operación es un
cálculo de cero o más valores de entrada (llamados operandos) a un valor de salida donde
las operaciones más comúnmente estudiadas son operaciones binarias.
Dado que la adición es la operación aritmética más común que los procesadores reali-
zan2, esta tesis se centra en medir el consumo de batería al agregar diferentes tipos de
datos primitivos. Para evaluar las operaciones aritméticas, los tipos considerados son int,
2http://www.mathworks.com/help/fixedpoint/ug/rules-for-arithmetic-operations.html
66
long, float y double. Esperamos que las operaciones con el tipo de datos entero sean más
eficientes que las operaciones de punto flotante. Esto se debe a la mayor complejidad
computacional inherente que presentan las operaciones de coma flotante en compara-
ción con las operaciones de enteros.
4.2. Aplicaciones
En términos generales, los llamados núcleos de aplicaciones científicas son un conjunto
de patrones que se representan en amplios tipos de aplicaciones. En general, consumen
mucha CPU y utilizan estructuras de datos primitivas, como arreglos y matrices. Por lo
tanto, son particularmente adecuados para probar nuestros micro-benchmarks.
Elegimos varias aplicaciones científicas ya desarrolladas para evaluar objetivamente las
mejoras en términos de consumo de batería después de usar las variantes de los gru-
pos de micro-benchmarks que favorecen el consumo energético, respondiendo Q2. Inclu-
so cuando las implementaciones originales de las aplicaciones podrían no ser óptimas,
nuestro objetivo fue tomar como entrada los códigos originales sin más modificaciones.
Esto se hizo con el fin de evitar la introducción de posibles sesgos debido a la inclu-
sión involuntaria de optimizaciones impulsadas por la energía, como las discutidas en la
sección anterior. Con base en los grupos de micro-benchmark anteriores, primero anali-
zamos algunas aplicaciones de Ibis/Satin Van Nieuwpoort et al. [2010], una plataforma
de código abierto para programación basada en Java que se enfoca en problemas intensi-
vos en computación científica. La Tabla 4.2 muestra las aplicaciones analizadas. Algunas
aplicaciones no fueron consideradas por su simplicidad (contienen pocos elementos para
modificar y evaluar su consumo de batería) o porque son versiones de las mismas apli-
caciones con cambios muy pequeños o contienen muchas operaciones de entrada/salida
(uso de disco) que consumen recursos e introducen ruido en el análisis. Recordemos que
estamos interesados en reducir el consumo de energía para aplicaciones con uso inten-
sivo de CPU. Además, seleccionamos aplicaciones de prueba que contienen una gran
cantidad de grupos de micro-benchmark para cubrir la mayor cantidad de grupos posi-
ble. Los grupos se clasificaron según su recurrencia en la aplicación. Finalmente, las tres
aplicaciones resultantes, son Fast Fourier Transform, Matrix Multiplication y Knapsack,
y se seleccionaron como aplicaciones caso de estudio con fines de experimentación en
dispositivos móviles.
Cuando extendimos nuestro trabajo a servidores y PC, consideramos aplicaciones adicio-
nales para cubrir nuestros grupos en diferentes áreas, como machine learning. Guiamos
la selección de aplicaciones representativas al considerar el trabajo de Colella [2004], que
identificó siete métodos numéricos (enanos de acuerdo con su terminología) que repre-
sentan la mayoría de las aplicaciones científicas y de ingeniería de alto rendimiento. Es-
67
tos métodos se especifican con un alto nivel de abstracción para permitir el razonamiento
sobre su comportamiento en una amplia gama de aplicaciones. Los programas que im-
plementan estos núcleos pueden hacerlo de manera diferente y los métodos numéricos
subyacentes pueden cambiar con el tiempo, pero la afirmación es que los patrones subya-
centes han persistido a través de generaciones de cambios y seguirán siendo importantes
en el futuro. Los siete enanitos definidos de esta manera son: Métodos espectrales, ál-
gebra lineal densa, álgebra lineal dispersa, métodos de N-cuerpo, Grid estructuradas,
Grids no estructuradas y reducción de mapa. Esa lista se amplió luego en Asanovic et al.
[2006] para considerar 6 nuevos granos o enanos. Estos nuevos enanitos son el resultado
de un análisis de la implementación de diferentes tecnologías de tendencias y dominios
de aplicación e incluyen lógica combinatoria, recorrido de grafos, backtracking, progra-
mación dinámica, construcción de modelos gráficos y máquina de estados finitos. Para
cubrir algunos de los enanos de Colella [2004] y de Asanovic et al. [2006] a través de
aplicaciones que podrían beneficiarse de la mayor cantidad posible de grupos de micro-
benchmark explicados anteriormente agregamos dos aplicaciones adicionales, una nueva
de Ibis/Satin y otra de GitHub. Por último, nos centramos en experimentar en servidores
utilizando los siguientes códigos concretos:
Fast Fourier Transform: Según la clasificación de Colella, la Transformada Rápida
de Fourier (FFT) se puede categorizar como Métodos Espectrales. Los métodos es-
pectrales son un conjunto de técnicas para resolver ciertas ecuaciones diferenciales,
y para ese propósito usan FFT.
Matrix Multiplication: en Asanovic et al. [2006] este núcleo se considera como una
categoría de álgebra lineal densa, nivel 3 (operaciones de matriz-matriz). Los nú-
cleos de Algebra Lineal Densa a menudo incluyen acceso a todos los elementos de
las estructuras de datos, y ese es el caso de la Multiplicación de Matriz.
Knapsack problem: este problema se establece en la categoría Backtracking, ya que
este es un problema de optimización combinatoria. Los núcleos Backtracking se
usan también en Integer Linear Programming y Boolean Satisfiability.
N-Queens: este problema es uno de los tipos más característicos de problemas en-
contrados en Backtracking. La solución a este problema implica el uso de una ver-
sión modificada de Backtracking para colocar las reinas en todas las posiciones po-
sibles.
Sequence alignment: este es un algoritmo utilizado para alinear dos secuencias con
el fin de analizar su similitud. Para lograr esto, los algoritmos de alineación de
secuencias usualmente usan programación dinámica, que es la base de la categoría
de programación dinámica.
68
La Tabla 4.3 resume las características de estas aplicaciones. Como mencionamos ante-
riormente, nos aseguramos de que las aplicaciones cubran la mayor cantidad posible de
los grupos de micro-benchmarks, contengan suficientes elementos de código para mo-
dificar y que no contengan muchas operaciones de entrada/salida (uso del disco) que
puedan introducir ruido en las mediciones de energía con el fin evaluar las variantes en
el consumo de energía de los refactorings propuestos a partir de los grupos de micro-
benchmarks.
Por otra parte, en este nuevo contexto, hay varias áreas que están en aumento y usan las
operaciones comunes presentadas en la Sección 4.1; por lo que decidimos extender nues-
tro trabajo en servidores a áreas como Machine Learning con el objetivo de encontrar
una respuesta completa a Q4. Machine Learning es un área de informática que se espe-
cializa en el diseño de algoritmos que permiten a la computadora "aprender" sin estar
explícitamente programadas las respuestas. Para lograr este objetivo, dichos algoritmos
generalmente funcionan con un conjunto de datos estructurados y con un conjunto de
funciones o propiedades. Básicamente, los algoritmos analizan estos conjuntos de datos
para encontrar cierta correlación entre los datos y, sobre la base de esa información, crean
un modelo que puede hacer estimaciones para nuevos datos.
Los algoritmos de Machine Learning se pueden dividir en dos grandes grupos: algorit-
mos de aprendizaje supervisado y algoritmos de aprendizaje no supervisados. Los algo-
ritmos supervisados están diseñados para conjuntos de datos donde cada entrada tiene
un conjunto de características y la salida asociada a esa entrada. El objetivo es entonces
estimar la salida para nuevas entradas dado el conjunto de características. Este grupo de
algoritmos también se puede dividir en dos subgrupos diferentes: algoritmos de clasi-
ficación y algoritmos de regresión. Los algoritmos de clasificación son útiles cuando la
salida puede tener un conjunto fijo de valores posibles, como 0 o 1. Los algoritmos de
regresión, por otro lado, funcionan cuando la salida es continua, como los precios de las
acciones.
Los algoritmos no supervisados se aplican cuando las entradas pertenecen a un conjunto
de datos que tiene una serie de características, pero no contiene la salida. Por lo tanto,
el propósito de estos algoritmos es encontrar una relación entre los datos y dividirla en
diferentes grupos o categorías. Por ejemplo, dado un conjunto de noticias un algoritmo
no supervisado proporcionaría un modelo que divide las noticias según el tema al que
pertenecen (deportes, política, economía, etc.).
Todos los algoritmos listados son intensivos en CPU, y puede llevar mucho tiempo crear
un modelo. Además, generalmente se modelan con matrices y se realizan muchas opera-
ciones sobre las mismas. Por lo tanto, muchos de los micro-benchmarks se pueden apli-
car para disminuir su consumo de energía. Particularmente, en esta tesis trabajaremos
con dos implementaciones de algoritmo: Gradient Descent y Bayes Network Classifier.
69
El primer algoritmo es la base de muchos otros algoritmos de Machine Learning y se pue-
de categorizar como álgebra lineal densa según la clasificación de Colella. Por otro lado,
Bayes Network Classifier es un algoritmo de clasificación que usa el teorema de Bayes
como base para construir el modelo. Este último algoritmo se clasifica como Construc-
ción de Modelos Gráficos de acuerdo con el modelo extendido Asanovic et al. [2006]. La
Tabla 4.4 resume las dos aplicaciones de Machine Learning empleadas.
Por último, propusimos medir el impacto de estas refactorizaciones en las aplicaciones
móviles reales de usuario final (Q5). Con esto en mente, seleccionamos dos aplicaciones
de usuario final que contienen un gran uso de CPU y memoria. Esta decisión se basó en
el hecho de que nuestras refactorizaciones propuestas son para aplicaciones de HPC por
lo que pueden producir un buen impacto en este tipo de aplicaciones. Como resultado,
las dos aplicaciones elegidas para responder Q5 son FiveStones y Sorter.
FiveStone: es un juego tradicional que evaluamos teniendo en cuenta a un jugador
que intenta ganar un partido cuando se enfrenta a la computadora. Usamos esta
modalidad porque el uso de la CPU aumenta durante el turno de la computadora.
Sorter: es una aplicación para el usuario final que le enseña al usuario los diferentes
algoritmos de ordenamiento. Un algoritmo de ordenamiento es un algoritmo que
coloca elementos de una lista en un orden determinado. La importancia de esta
aplicación radica en que la clasificación eficiente es importante para optimizar el
uso de otros algoritmos.
4.2.1. Fast Fourier Transform (FFT)
Esta aplicación implementa un algoritmo para calcular la transformada discreta de Fou-
rier, que tiene impacto en diferentes áreas como procesamiento de imágenes (JPEG) y
audio (MP3), reducción de ruido en señales, análisis de frecuencia de señales discretas y
análisis estadístico de materiales, entre otros.
Siendo x0, x1, ...., xn−1 números complejos, la transformación discreta de Fourier (DFT, pa-
ra abreviar) se define como f j = ∑n−1k=0 xke−
2πin jk j = 0,1, ...n− 1. Una evaluación directa
de esta fórmula requiere O(n2) operaciones aritméticas. Sin embargo, Gauss propuso un
método que requiere solo N log N pasos para evaluarlo. Investigadores de la Univer-
sidad de Princeton describieron cómo implementar el DFT de manera eficiente en una
computadora3, llamando al algoritmo FFT.
El algoritmo evaluado en este trabajo es una descomposición recursiva de FFT en fun-
ciones simples hasta obtener dos funciones de elementos donde k puede tomar solo los
3http://www.cs.princeton.edu/introcs/97data
70
valores 0 y 1. Esto significa que las funciones elementales son funciones con solo dos
elementos para operar. Una vez que se resuelven estas transformaciones simples, el al-
goritmo tiene que agruparlas en otros cómputos de nivel superior para que se resuelvan
nuevamente hasta alcanzar el nivel recursivo más alto. Al final de este proceso, estos
resultados deben reorganizarse para obtener el mismo resultado que la FFT original.
La implementación original de esta aplicación fue realizada por el staff de Ibis/Satin
para el curso Introducción a la informática Princeton 4, Radix-2. Sin embargo, esta im-
plementación tiene limitaciones: asume que N es una potencia de 2 y, por otro lado, no
es el algoritmo más eficiente en términos de uso de memoria. A continuación, explica-
mos brevemente cómo funciona este algoritmo. Primero, Radix-2 calcula las entradas
pares y luego las entradas impares. Después de eso, Radix-2 combina estos dos resulta-
dos para producir la secuencia completa de DFT, de acuerdo con f j = ∑n/2−1k=0 x2ke−
2πin/2 jk +
e−2πin j ∑
n/2−1k=0 x2k+1e−
2πin/2 jk = Ej + e−
2πin jOj.
Estas DFT tienen una longitud de N/2 elementos, y cada uno calcula N/2 salidas. Las
salidas para una DFT de longitud N/2 son idénticas a las salidas para 0 ≤ j < N/2 (i.e.,
Ej+n/2 = Ej y Oj+n/2 =Oj). El factor común e−2πij
n satisface la relación e−2πi(j+n/2)
n =−e−2πij
n .
En general, DFT se calcula como:
f j
Ej + e−2πi
n jOj 0 ≤ j < N/2
Ej−N/2 − e−2πi
n (j−N/2)Oj−N/2 j ≥ N/2
Esta ecuación es el núcleo del algoritmo Radix-2. Luego, Radix-2 acelera el DFT reutili-
zando los resultados de los cálculos intermedios.
4.2.2. Matrix multiplication (MMULT)
MMULT es una aplicación de prueba que toma como parámetros dos matrices (A, B) que
contienen números y devuelve otra matriz (C) que contiene el resultado de multiplicar
las dos primeras matrices. Claramente, el número de columnas en A debe ser el mismo
que el número de filas en B. Entonces, la matriz C se calcula como Amxn ∗ Bnxp = Cmxp
que se calcula como cij = ∑nk=1 aik ∗ bkj, donde i y j son los números de fila y columna.
Entonces, el elemento cij es la suma de los productos de cada elemento en la fila i en la
matriz A con el elemento correspondiente en la columna j en la matriz B. MMULT es, por
ejemplo, muy útil para resolver sistemas de ecuaciones. Además, se pueden encontrar
varias aplicaciones de multiplicación de matrices en el área del álgebra lineal.
4http://www.cs.princeton.edu/introcs/97data
71
Para producir la matriz C, la aplicación utilizada en este trabajo primero divide cada
matriz de entrada en cuatro cuadrantes. Esta división es recursiva hasta el último nivel
donde hay una matriz nxn con n dado como parámetro. Entonces, el resultado en cual-
quier nivel se puede calcular como C11 = A11 ∗ B11 + A12 ∗ B21; C12 = A11 ∗ B12 + A12 ∗ B22;
C21 = A21 ∗ B11 + A22 ∗ B21; C22 = A21 ∗ B12 + A22 ∗ B22.
Cada ecuación contiene cuatro multiplicaciones de matrices internas siguiendo la misma
lógica. La recursión se detiene en el último nivel de matrices, donde las celdas contienen
valores atómicos, es decir, n = 1. Esta decisión nos permite evaluar el impacto de los pun-
tos de referencia en el caso más extremo (el caso que implica la mayoría de las creaciones
de objetos, por ejemplo).
4.2.3. Knapsack (KP)
KP es un problema de optimización combinatoria cuyo objetivo es optimizar el valor
total (en términos generales) que una mochila puede contener. La mochila puede so-
portar un peso por defecto W y debe llenarse con elementos que tengan un valor v y
un peso w. La representación matemática del problema es max ∑ni=1 vixi with W ≥
∑ni=1 wixi where xi = number o f elements x.
Presentaremos un ejemplo práctico del problema. Un vendedor puede cargar su mochila
con 5 kg. o menos. Él tiene 3 productos, cada uno con un peso y valor en particular. A
pesa 4 kg. y su precio es de $4, B pesa 1 kg. y tiene un valor de $3, y C tiene un peso dw
2 kg. y un valor de $2. El problema es determinar qué productos debe llevar el vendedor
para obtener el máximo beneficio o valor.
Mientras que KP es fácil de describir, es un problema NP-completo cuya solución no tiene
algoritmo eficiente Garey and Johnson [1979]. De hecho, las soluciones existentes para el
problema no son efectivas para instancias de gran escala. Este es un problema recurrente
en ingeniería Zhang [2011] y en muchas otras áreas de estudio. Además, KP es la base
del primer algoritmo de encriptación asimétrica (o algoritmo de "clave pública") Zhang
[2011]. También, tiene varias aplicaciones en el contexto de gestión de operaciones y lo-
gística.
Finalmente, la versión del algoritmo KP empleado en este trabajo se basa en dividir los N
elementos iniciales en dos subproblemas recursivos para elementos N − 1, uno con el
elemento perdido colocado en la mochila y el otro sin él. Esta metodología continúa ope-
rando recursivamente hasta que la mochila esté llena o no queden más elementos.
72
4.2.4. N-Queens Problem
N-Queens es un clásico problema combinatorio, donde n reinas deben colocarse en un
tablero nxm para que no se ataquen dos reinas teniendo en cuenta las reglas del ajedrez.
A pesar de que este problema prescribe una estructura algorítmica simple, se ha utiliza-
do ampliamente como parte de aplicaciones más complejas Masehian et al. [2013] como
gestión de recursos informáticos (prevención de interbloqueos y asignación de registros),
pruebas VLSI, control de tráfico, diseño de sistemas de comunicación, colocación de ro-
bots para una cobertura máxima del sensor, problemas de permutación, esquemas de
almacenamiento en memoria paralela. N-Queens también se usa en muchas otras aplica-
ciones de Física, Informática e industriales Erbas et al. [1992], San Segundo [2011].
Este problema se considera un problema NP-Completo, y varios enfoques se han utiliza-
do para llegar a una solución San Segundo [2011], Jagota [1993], Bell and Stevens [2009].
Hay dos variantes básicas del problema: encontrar todas las soluciones posibles y en-
contrar una sola solución posible. En este documento, la implementación considerada
se refiere a la primera de esas dos alternativas que requiere más CPU. En particular, la
implementación se obtuvo del proyecto Ibis/Satin van Nieuwpoort et al. [2010], como
los primeros tres problemas. Aunque la implementación es bastante simple, se pueden
encontrar muchas refactorizaciones posibles para que sea más eficiente en términos de
energía.
Más específicamente, el algoritmo encuentra soluciones comenzando con una reina en la
esquina superior izquierda del tablero de ajedrez. Luego coloca otra reina en la segunda
columna y la mueve hasta que encuentra un lugar donde no puede ser golpeada por la
reina en la primera columna. Luego coloca una reina en la tercera columna y la mue-
ve hasta que ninguna de las dos primeras reinas pueda golpearla. Luego continúa este
proceso con las reinas restantes. Si no hay lugar para una reina en la columna actual, el
algoritmo vuelve a la columna anterior y mueve a la reina a esa columna. Como se puede
ver, este es un algoritmo recursivo simple de divide y conquista.
4.2.5. Sequence Alignment
Sequence alignment implica comparar dos secuencias de ADN e identificar las regio-
nes de similitud. Una secuencia de ADN está representada por una cadena de caracteres
siguiendo la nomenclatura IUPAC Cornish-Bowden [1985]. Cada letra representa un resi-
duo. Luego, cuando dos representaciones simbólicas de secuencias de ADN se disponen
una al lado de la otra para que sus elementos más similares se yuxtapongan, se dice que
están alineados. Estas alineaciones se conocen comúnmente como trazas. La Figura 4.1
muestra la alineación de dos secuencias, ambas son extracto de dos proteínas diferentes
73
(p53_human y p53_mouse). Los extractos sin la alineación se pueden ver en la parte iz-
quierda de la figura, mientras que la contraparte alineada se muestra en la parte derecha
de la figura.
Cada elemento en una traza es una coincidencia, una falta de coincidencia o una brecha.
Cuando una letra en una de las dos secuencias alineadas es idéntica a su contraparte en
la otra, los códigos de letras correspondientes en las dos secuencias se alinean vertical-
mente en la traza, por lo que se llama una coincidencia, representada con una línea verde
en la Figura 4.1. Cuando no hay espacio y dos letras están alineadas, pero las letras no
son iguales, se llama desajuste. Los desajustes se representan con una línea roja en la
figura. Por otro lado, hay dos razones para tener un espacio en lugar de una coinciden-
cia. En primer lugar, cuando un residuo en una secuencia parece haber sido eliminado,
especialmente debido a la supuesta divergencia de la secuencia de su contraparte, su au-
sencia está etiquetada por un guión en la secuencia derivada. Eso se llama eliminación.
En segundo lugar, cuando parece que se ha insertado un residuo para producir una se-
cuencia más larga, aparece un guión opuesto en la secuencia no aumentada, conocida
como inserción.
Hay dos tipos generales de métodos de alineación: global y local. El primero realiza la
alineación de todos los residuos de cada secuencia al mismo tiempo. Este enfoque es
particularmente útil cuando todas las secuencias tienen una longitud similar. El enfoque
local, en cambio, examina algunas partes de cada secuencia y las compara con una parte
de la otra. Particularmente, este documento se centra en uno de los algoritmos existentes
basados en la alineación local, el algoritmo Smith-Waterman Smith and Waterman [1981],
que se basa en la programación dinámica.
La alineación de secuencias se usa ampliamente en varias aplicaciones, especialmente
aquellas relacionadas con Bioinformática. No solo es útil encontrar la alineación de dos
secuencias de ADN, sino también explorar situaciones donde hay genes y obtener infor-
mación sobre el empalme alternativo Modrek and Lee [2002]. La alineación de secuencias
también se utiliza ampliamente en el procesamiento del lenguaje natural y en las ciencias
sociales, donde el algoritmo se utiliza, por ejemplo, para parafrasear oraciones Barzilay
and Lee [2003].
Figura 4.1: Secuencias de ADN
74
4.2.6. Gradient Descent
Gradient Descent es un algoritmo que optimiza la búsqueda del mínimo local para una
función. Cuando se trata de varias variables en una función, es muy costoso computacio-
nalmente determinar su derivada para encontrar el mínimo global. Además, no siempre
es posible llevar a cabo esa derivada. Por lo tanto, Gradient Descent es una forma de
obtener mínimos locales de una manera eficiente. Básicamente, es un algoritmo iterativo
que calcula el gradiente de la función en cada iteración y asigna un coeficiente a cada
variable de función. Su objetivo es moverse hacia la dirección opuesta del gradiente, ac-
tualizando los coeficientes. Esto es, en cada paso, el algoritmo actualiza cada coeficiente
variable para que se mueva en la dirección opuesta al gradiente.
Más específicamente, para llevar a cabo el gradiente de una función, los coeficientes se
separan de las variables. Los primeros se almacenan en un vector n-dimensional, donde
n es el número de términos en la función. Los valores de las variables también se pue-
den almacenar en un vector n-dimensional si solo hay un punto de datos. Sin embargo,
cuando se trata de un conjunto de datos con varias filas de datos para el conjunto de
variables, entonces se necesita una matriz nxm, donde m es la cantidad de puntos de da-
tos. Una vez que se obtienen las matrices, el algoritmo multiplica ambas matrices, realiza
cálculos específicos de la función y almacena los resultados en el vector de coeficientes
m-dimensional. Este proceso se lleva a cabo varias veces hasta lograr la convergencia.
Debido a su muy buen rendimiento, este algoritmo ha sido adoptado en varias áreas. El
más relevante es Machine Learning Burges et al. [2005]. La mayoría de los algoritmos de
Machine Learning basan sus cálculos en este enfoque o en una versión modificada del
mismo, como Regresión logística Hosmer Jr and Lemeshow [2004], Redes neuronales y
Aprendizaje profundo. Básicamente, hay tres tipos de Gradient Descent: Gradient Des-
cent por lotes, Gradient Descent estocástico y Gradient Descent de mini-lotes. El primero
toma en consideración todo el conjunto de datos para cada iteración y actualiza todos los
coeficientes. Esta alternativa generalmente encuentra una mejor solución que las otras,
aunque toma mucho tiempo tratar con grandes conjuntos de datos. La segunda variante,
en cambio, realiza una ronda de actualización de coeficientes para cada punto de datos
del conjunto de datos. Por lo tanto, suele ser mucho más rápido que el Gradient Descent
por lotes y también se puede utilizar en algoritmos de aprendizaje en línea, pero puede
no converger al mínimo local. Finalmente, el tercer enfoque toma grupos o lotes de k
puntos de datos. Por lo tanto, toma la mejor de las dos alternativas anteriores, y se usa
ampliamente para algoritmos de Aprendizaje Automático.
75
4.2.7. Bayes Network Classifier
Bayes Network Classifier es un algoritmo de clasificación supervisada de Machine Lear-
ning que aprovecha el bien conocido teorema de Bayes para clasificar instancias en un
conjunto de datos. Un clasificador es un algoritmo de Machine Learning que toma co-
mo entrada un conjunto de datos que contiene un número fijo de características y una
categoría o clase, y devuelve como resultado un modelo capaz de realizar estimaciones
para nuevos datos. El conjunto de datos se procesa para conocer la importancia que cada
característica tiene para determinar la categoría de una instancia. Finalmente, el modelo
obtenido toma nuevas entradas y predice cuál es la clase a la que pertenecen. Los clasi-
ficadores de la red Bayes, en particular, se usan en una amplia gama de áreas, como en
la recuperación de información de Campos et al. [2004]), Bioinformática Friedman et al.
[1997], o procesamiento de imágenes Luo et al. [2005].
El enfoque más común para explotar el teorema de Bayes es el clasificador Naïve Bayes,
que hace la suposición de que cada característica o variable es condicionalmente inde-
pendiente de todas las otras variables aleatorias. Este enfoque, aunque bastante simple,
da como resultado un algoritmo muy eficaz y eficiente Rish [2001]. Sin embargo, en algu-
nos casos, la suposición de independencia genera un alto sesgo en el modelo, por lo que
el rendimiento tiende a disminuir.
Por lo tanto, se presentó un enfoque alternativo en Friedman et al. [1997] teniendo en
cuenta el concepto de Bayes Network, que representa las dependencias entre cada varia-
ble en el modelo. Teniendo en cuenta, por ejemplo, una red Bayes donde la variable C
depende de las variables A y B (A → C y B → C, y ambas variables D y E dependen solo
de la variable C (C → D y C → E ).Con esto, fue posible ajustar un modelo más complejo
que considera las dependencias entre variables y, por lo tanto, es más efectivo y preciso
que el clasificador de Naïve Bayes.
Para la representación de la red Bayes, generalmente se usa una matriz mxm donde m
es el número de variables o características aleatorias. Cada celda de esta matriz indi-
ca la probabilidad de cada variable dada su variable anterior, es decir, la probabilidad
condicional de cada combinación posible de características. Por lo tanto, para hacer una
inferencia dada esta matriz, el algoritmo calcula la distribución de probabilidad posterior
para un conjunto de variables de consulta. Por ejemplo, en el ejemplo anterior, basado en
el valor de la variable E, se puede inferir el valor de C, o incluso A o B. Esto se hace
iterando la matriz mencionada y calculando la fórmula de Bayes para la probabilidad
posterior. Finalmente, para aprender las probabilidades condicionales, el algoritmo toma
como entrada un conjunto de datos de n puntos de datos y m características. Toda esta
información es procesada por el algoritmo, que devuelve la matriz que representa la red
de Bayes.
76
4.2.8. Aplicaciones de usuario final (FiveStones y Sorter)
FiveStones es una implementación del clásico juego ’cinco en linea’ (vea la Figura 4.2).
El juego se juega en un tablero en el que dos jugadores se turnan para participar. El
objetivo del juego es colocar fichas en turnos, tratando de obtener una línea de 5 fichas
consecutivas (vertical, horizontal o diagonal). Con respecto al código de la aplicación
utilizada, la aplicación tiene 64 clases, 290 métodos y 4700 líneas de código donde el
mayor computo se encuentra en la participación de la computadora como jugador.
Figura 4.2: FiveStones UI
Sorter es un juego didáctico que ilustra gráficamente algoritmos de ordenamiento de un
arreglo paso a paso (ver Figura 4.3). Dentro de los algoritmos implementados están el or-
denamiento por inserción, el ordenamiento por selección, el ordenamiento por burbuja,
el ordenamiento quick-sort y merge-sort. La aplicación muestra un conjunto de líneas de
diferentes tamaños desordenadas y, cuando se ejecutan los algoritmos, el usuario pue-
de ver cómo procede el pedido. En términos de cantidad de código, es una aplicación
pequeña. Sin embargo, el porcentaje de código modificado fue alto.
4.3. Resumen
A lo largo de este Capítulo se presentaron los grupos seleccionados de micro-benchmarks.
Para esta selección consideramos la recurrencia de estas operaciones en aplicaciones cien-
tíficas reales y su importancia dentro del paradigma OO ya que el lenguaje utilizado para
nuestra experimentación es Java. Luego, en este capítulo, se presentó una descripción de-
tallada de cada uno de los micro-benchmarks junto con ejemplos de su uso.
Además, la evaluación realizada en este trabajo está respaldada por experimentos lleva-
dos a cabo con aplicaciones reales donde se aplicaron buenas prácticas basadas en los ex-
perimentos realizados con los grupos de micro-benchmarks. Las aplicaciones utilizadas
77
Figura 4.3: Sorter UI
se tomaron de un conjunto de aplicaciones que pertenecen al repositorio de aplicaciones
Satin. Dentro de estos, seleccionamos aquellas aplicaciones que mejor cubran los grupos
de micro-benchmark para evaluar el número máximo de prácticas posibles. Finalmente,
obtuvimos la FFT, MMULT y Knapsack problem como aplicaciones. Con estas aplicacio-
nes podemos evaluar seis de los ocho grupos de micro-benchmarks, dejando de lado el
uso de excepciones y el uso de tipos de datos primitivos. En el primer caso, no encon-
tramos situaciones donde las excepciones se usaron para el flujo normal de la aplicación
y, en el segundo caso, se usaron tipos de datos primitivos y no envoltorios porque eran
aplicaciones originalmente transformadas de lenguaje C a Java por el equipo de Satin.
Luego, no solo agregamos nuevas aplicaciones de HPC obtenidas de Satin, sino que tam-
bién consideramos las aplicaciones de repositorios de proyectos de GitHub y Weka, al-
goritmos de aprendizaje automático y aplicaciones móviles para usuarios finales para
generalizar nuestro trabajo de investigación a los servidores.
78
Aplicación AC OC OFA SH EH PDT MT AO
Fast FourierTransform
- +++ +++ + + +++ - +++
MatrixMultiplication
- ++ - - + +++ +++ +++
Knapsack + ++ - - ++ +++ +++ +
Barnes-HutSimulation
+++ +++ - - + +++ - ++
Set CoveringProblem
- + - - + +++ - ++
Fibonacci - - - - + +++ - +++
Grammar-based text
compressor
- - - - + +++ - -
IterativeDeepening A*
- - - - + +++ ++ +++
Locus Route - - - - + +++ + -
Awari - - - - + +++ - -
Nqueens - - - - + +++ +++ ++
Othello Game - - - - + +++ - ++
TravelingSalesmanProblem
- - - - + +++ - -
AC = Copia de arreglosOC = Creación de objetosOFA = Acceso a atributos deun objeto
SH = Manejo de StringsEH = Manejo de escepcionesPDT = Uso de tipos de datosprmitivos
MT = Recorrido de matricesAO = Operaciones aritmpe-ticas
+ = Baja cantidad ++ = Mediana cantidad +++ = Gran cantidad
Cuadro 4.2: Resumen de aplicaciones de Ibis/Satin. El signo “+” representa una indicación cuan-titativa de la extensión de código que tiene ese grupo de micro-benchmarks
79
Aplicación AC OC OFA SH EH PDT MT AO Projectsource
FastFourier
Transform
- +++ +++ + + +++ - +++ Ibis/Satin
MatrixMultipli-
cation
- ++ - - + +++ +++ +++ Ibis/Satin
Knapsack + ++ - - ++ +++ +++ + Ibis/Satin
Nqueens - - - - + +++ +++ ++ Ibis/Satin
SequenceAlign-ment
- ++ ++ - - +++ ++ ++ GitHub
AC = Copia de arreglosOC = Creación de objetosOFA = Acceso a atributos deun objeto
SH = Manejo de StringsEH = Manejo de escepcionesPDT = Uso de tipos de datosprmitivos
MT = Recorrido de matricesAO = Operaciones aritmpe-ticas
+ = Baja cantidad ++ = Mediana cantidad +++ = Gran cantidad
Cuadro 4.3: Aplicaciones de casos de estudio. El signo “+” representa una indicación cuantitativade la extensión de código que tiene ese grupo de micro-benchmarks
Apkicación AC MT SH AO EH OFA OC PDT Projectsource
BayesNetworkClassifier
+ ++ - + - +++ +++ +++ Weka
GradientDescent
- +++ - ++ ++ +++ +++ +++ GitHub
AC = Copia de arreglosOC = Creación de objetosOFA = Acceso a atributos deun objeto
SH = Manejo de StringsEH = Manejo de escepcionesPDT = Uso de tipos de datosprmitivos
MT = Recorrido de matricesAO = Operaciones aritmpe-ticas
+ = Baja cantidad ++ = Mediana cantidad +++ = Gran cantidad
Cuadro 4.4: Aplicaciones de casos de estudio (Machine Learning). El signo “+” representa unaindicación cuantitativa de la extensión de código que tiene ese grupo de micro-benchmarkse
80
Capıtulo 5
Experimentos
Este capítulo presenta el hardware, el software y la metodología utilizados para los ex-
perimentos realizados en la tesis. Esta tesis mide el consumo de energía de 8 grupos de
micro-benchmarks y el impacto de las buenas prácticas obtenidas a partir de estos re-
sultados en siete aplicaciones científicas reales y dos aplicaciones móviles para usuarios
finales. Por lo tanto, a lo largo de este capítulo, se presentan una serie de limitaciones al
evaluar los micro-benchmarks en Java, que deben considerarse.
Entonces, para enfrentar estas limitaciones, decidimos utilizar un framework presentado
por Google llamado Caliper Google. Caliper es un framework de código abierto desarro-
llado por Google para escribir, ejecutar y obtener resultados de micro-benchmarks para
Java que minimiza los gastos generales introducidos por este lenguaje. Además, usamos
otro framework llamado Robotium para probar aplicaciones de usuario final. Además,
como mencionamos anteriormente, aprovechamos las ventajas del hardware especializa-
do para evaluar los micro-benchmarks y las aplicaciones reales en los servidores. Luego,
presentaremos el hardware utilizado en esta instancia junto con sus especificaciones.
Este Capítulo está dividido en 4 Secciones. La primera Sección 5.1 introduce Caliper,
el framework utilizado para realizar los experimentos. Luego, la Sección 5.2 muestra
la estructura general de la aplicación y detalla la metodología utilizada para evaluar
micro-benchmarks y aplicaciones HPC en dispositivos móviles. La Sección 5.3 presenta
el hardware introducido para probar micro-benchmarks y aplicaciones HPC en servido-
res. Además, se presenta el diseño de la aplicación. Finalmente, la Sección 5.4 muestra
la actualización de hardware para probar aplicaciones de usuario final en dispositivos
móviles.
81
5.1. Caliper
A diferencia de los lenguajes compilados tradicionales, el código compilado de Java (by-
tecode) es independiente de la plataforma. Las JVM proporcionan un entorno en el que
el bytecode de Java se puede ejecutar a) interpretando los bytecodes o b) siendo asistido
por un mecanismo just-time (JIT) mediante el cual se produce la traducción de bytecode
a assembly bajo demanda, mejorando el rendimiento. Además, las JVM tienen un intér-
prete equipado con un compilador dinámico que realiza una compilación optimizada de
las partes del programa más utilizadas Barisone et al. [2001]. No obstante, esto plantea
varios desafíos cuando se evaluan benchmarks en Java debido a que estos mecanismos
agregan "ruido":
realizar evaluaviones de rendimiento en JVM es difícil Sinschek et al. [2009] por-
que actúan como una capa de abstracción, lo que podría cambiar los resultados en
diferentes ejecuciones.
diferentes compiladores de Java hacen diferentes optimizaciones. Algunos compi-
ladores pueden detectar código muerto (código que no afecta a la salida) y elimi-
narlo. Se puede agregar código adicional que evite esta variación, pero esto podría
cambiar los resultados porque el código adicional agrega más código para ejecutar.
en Java, las iteraciones sobre un benchmark para obtener varias muestras estadís-
ticas de una operación de referencia incluyen una gran cantidad de compilación
dinámica. Las iteraciones posteriores suelen ser más rápidas porque incluyen me-
nos compilación y el código ejecutado está más optimizado Georges et al. [2007].
En este caso medir cuándo convergen las ejecuciones puede reducir el impacto.
el Garbage Collector puede activarse de forma asíncrona mientras se ejecuta un
código, lo que afecta el rendimiento del código porque el GC consume recursos
informáticos mientras libera la memoria.
la carga de clases al iniciar una aplicación puede causar que las primeras ejecucio-
nes consuman más recursos.
Después de analizar estos problemas, decidimos utilizar el framework de Caliper1 para
ejecutar nuestros experimentos. Caliper es un framework diseñado por Google para desa-
rrollar y ejecutar micro-benchmarks en Java. Si bien el enfoque principal de Caliper es la
medición de performance en micro-benchmarks, también se puede utilizar para tomar
medidas de diferente naturaleza como la asignación de memoria. La Figura 5.1 muestra
el formato general que debe tener un micro-benchmark Caliper para lograr su propósito.
1http://code.google.com/p/caliper/
82
Figura 5.1: Micro-benchmark
Este es un código muy simple, cuya única condición es extender la clase SimpleBenchmark
proporcionada por el framework, haciendo que el uso de este framework sea simple y
beneficioso.
Además de la clase donde se declara el micro-benchmark, hay más conceptos relaciona-
dos con Caliper que debemos tener en cuenta cuando desarrollamos micro-benchmarks.
Aquí hay algunos términos básicos que se necesitan para trabajar correctamente con Ca-
liper:
Benchmark method: es el método cuyo nombre debe comenzar con la palabra "time"
y cuyo propósito es ejecutar la parte del código desde el que quieren tomar las
métricas. Este método debe definirse dentro de la clase Benchmark que amplía la
clase SimpleBenchmark. Este es el método más importante para el desarrollador que
quiere obtener métricas.
Environment: es la descripción del hardware, sistema operativo y JRE en el que se
toma una medición. Es decir, son las condiciones de ejecución bajo las cuales se
prueba el micro-benchmark.
Medición: generalmente esta es la medición de performance.
Parámetro: se refiere a los valores que se inyectan en la clase de referencia con la
anotación @Param. Para cada parámetro, se puede configurar más de un paráme-
tro y luego probarse por separado y de forma automática. Entonces, estos valores
facilitan la experimentación con variaciones del mismo micro-benchmark de una
manera simple y rápida.
Reps: determina el número de veces que se debe ejecutar un escenario en cada in-
vocación. La ejecución repetida del mismo escenario permite obtener resultados ge-
neralizables y calcular valores estadísticos (como promedio y desviación estándar)
de ellos.
83
Escenario: es una instancia de un micro-benchmark de referencia completamente
especificado, es decir que tiene un valor específico para cada uno de los paráme-
tros definidos y para la variable Reps. Los escenarios tienen la propiedad de ser
ejecutables.
Ejecución: es el conjunto de escenarios ejecutados en lote en un único host. Es decir,
son ejecuciones realizadas en el mismo entorno.
Luego de presentar los conceptos básicos para trabajar con Caliper se presentan a conti-
nuación algunas buenas prácticas para la medición de micro-benchmarks. Estas prácticas
son para ejecutar siempre el mismo código dentro del cuerpo del micro-benchmark, y no
ingresar valores aleatorios ni usar el valor del contador de bucles dentro del cuerpo ya
que pueden introducirse desviaciones innecesarias. Después de definir correctamente el
microensayo para evaluar, puede tomar dos caminos diferentes para ejecutarlo:
1. La forma más sencilla de ejecutar los benchmarks de Caliper en Android es usar
una herramienta llamada Vogar.
2. Otra opción además de Vogar es compilar el micro-benchmark junto con Caliper y
sus dependencias en un archivo .jar y luego ejecutarlo en los dispositivos.
La metodología utilizada en este trabajo se basó en la segunda opción presentada.
5.2. Aplicación Android
Esta sección muestra el diseño del software de prueba para experimentos de HPC mó-
viles y su funcionamiento. El software de prueba es la aplicación móvil que contiene la
lógica necesaria para seleccionar y ejecutar micro-bechmarks y aplicaciones de prueba
científica. Vale la pena señalar que el software está disponible a pedido.
Una captura de pantalla del software se muestra en la Figura 5.2. El software tiene un
campo de texto configurable para indicar el número de ejecuciones para cada experi-
mento, que se ejecuta cuando se presiona el botón correspondiente. A continuación, la
Figura 5.2muestra las clases principales del software. En este diagrama, las clases App1 y
App2 crean instancias para cada aplicación de prueba y micro-benchmark. Este diagrama
incluye las clases principales del software y su funcionalidad. Sin embargo, hay clases
(por ejemplo, clases para registrar datos) que no se incluyen en el diagrama porque no
forman parte del núcleo del software. En este punto, es importante tener en cuenta que
cada prueba va desde e l100% de la carga de la batería hasta el estado de batería baja.
Cada clase del diagrama está explicada en los siguientes párrafos:
84
Figura 5.2: Aplicación Android: Diagrama de clases y Scrrenshot
App1, App2: Estas clases contienen la implementación de las aplicaciones y micro-
benchmarks, respectivamente. Las instancias de estas clases se ejecutan continua-
mente contando el número de ejecuciones hasta que la batería alcanza su límite de
capacidad baja (es decir, 15%).
Lock: es el Lock que permite que Runner y BatteryReceiver trabajen juntos cuando
se ejecuta el micro-benchmark. Además, evita que el Runner se ejecute cuando la
capacidad de la batería es inferior al 15%.
Runnable: es una interfaz proporcionada por Java como alternativa al uso directo
de la clase Thread. Las clases que lo implementan deben redefinir el método run(),
que permite la ejecución implícita de un micro-benchmark en un hilo diferente de
la aplicación principal.
Activity: es una clase proporcionada por el marco de Android que representa la
interfaz de usuario. En esta interfaz de usuario, el usuario selecciona diferentes pa-
rámetros de prueba, así como la prueba a ejecutar. Cuando el usuario selecciona la
85
ejecución que se llevará a cabo, la actividad es responsable de crear un servicio que
se ejecutará en segundo plano, impidiendo que una aplicación o micro-bechmark
deje de ejecutarse.
BatteryReceiver: esta clase extiende la clase BroadcastReceiver proporcionada por An-
droid para recibir cambios en el estado de la batería.
BatteryReceiverLowBATtery: esta clase extiende la clase BatteryReceiver. BatteryRecei-
verLowBattery recibe la condición de batería baja usando una clase IntentFilter -una
API Android- para este propósito. Cuando la capacidad de la batería alcanza el15%,
el micro-benchmark o la aplicación se detiene y las estadísticas de ejecución se al-
macenan.
BatteryService: este servicio tiene la responsabilidad de ejecutar la aplicación o micro-
benchmark seleccionada para ejecutarse. Este servicio contiene un atributo Power-
Manager que mantiene la CPU activa incluso si la pantalla se apaga.
SimpleBenchmark: es la clase que los micro-benchmark deben ampliar para usar el
marco Caliper.
Runner: esta clase extiende SimpleBenchmark e implementa Runnable para permitir
que los micro-puntos de referencia y las aplicaciones de prueba utilicen el marco
Caliper y ejecuten experimentos para drenar la batería. Luego, diferentes micro-
benchmarks y aplicaciones se extienden desde esta clase.
Finalmente esta lista incluye las clases principales que deben tenerse en cuenta cuando
se ejecuta el software de medición en Android.
5.2.1. Metodología
Teniendo en cuenta las restricciones de Caliper, desarrollamos una aplicación móvil para
contener todos los micro-benchmarks y aplicaciones de prueba para ejecutar. En la Sec-
ción 5.2 presentamos el diseño del software y su funcionamiento. Finalmente, nuestra me-
todología experimental fue la siguiente. Primero, medimos el número de ejecuciones de
cada micro-benchmark o aplicación de prueba en un ciclo de batería. Por ciclo de batería
nos referimos al tiempo transcurrido entre una batería completamente cargada y un es-
tado de batería baja. Usando esta metodología, cada micro-benchmark y cada aplicación
se evaluaron al menos 10 veces en cada tipo de dispositivo. Los dispositivos se cargaron
al 100% y todas las demás aplicaciones y servicios de los usuarios se desactivaron (ex-
cepto los esenciales para el sistema operativo); y las radios celulares/WiFi/Bluetooth y la
pantalla se apagaron para los experimentos. En una nota lateral, esta metodología es útil
para dispositivos modernos cuyas baterías no son extraíbles. Particularmente, usamos
86
teléfonos inteligentes Samsung Galaxy I5500, tabletas ViewPad 10s y Acer A100 cuyas
especificaciones se enumeran a continuación:
Samsung Galaxy I5500: 600 MHz CPU (MSM7227-1 ARM11 model), 256 MB ode-
RAM, 4 MB de default heap y una batería 1200 mAh Lithium Ion.
ViewPad 10s: 1 GHz CPU NVIDIA Tegra 250 SMP dual Cortex-A9, 512 MB de RAM,
8 MB de default heap y una bateria 3300 mAh Li-Polymer.
Acer A100: 1 GHz CPU NVIDIA Tegra dual core ARM Cortex-A9, 1 GB de RAM,
7 MB de default heap y una batería1530 mAh x 2 Li-ion battery.
En estas especificaciones, mencionamos el tamaño del almacenamiento dinámico, ya que
es importante considerar el impacto del GC.
Por último, los grupos de micro-benchmark fueron evaluados solo en smartphones por-
que estos son los dispositivos con menos recursos y son suficientes para evaluar si un
cambio en un código fuente tiene un impacto significativo en el consumo de energía. Sin
embargo, las aplicaciones se evaluaron en tres dispositivos diferentes para obtener resul-
tados más generales. La Ecuación 5.1 se usa para calcular el porcentaje de reducción en
el uso de energía introducido por las versiones de micro-benchmark eficientes:
EnergySaved = (1 −(∑ Executioni)/(nº of executions)
(∑ improvedExecutioni)/(nº of executions)) ∗ 100 (5.1)
5.3. Aplicación para Servidores
Del mismo modo que en la aplicación de Android, las aplicaciones se diseñaron para usar
un diseño de clase genérico para que cualquier otra aplicación se pueda adaptar fácilmen-
te al entorno y se pueda medir su consumo energético. Específicamente, las aplicaciones
diseñadas de esta manera reciben como entrada un conjunto de parámetros y devuelven
el consumo de su ejecución. Los parámetros dados como entrada son los siguientes:
Delay: Las primeras ejecuciones de un programa Java generalmente toman más
tiempo para ejecutarse que las posteriores, porque la JVM tiene que cargar todo el
código y los datos en la memoria. Por lo tanto, antes de ejecutar cada algoritmo hay
un retraso (configurable) para disminuir este ruido.
Number of threads: Número de subprocesos que se utilizarán durante la ejecución
("1" significa modo de núcleo único).
87
Ejecuciones: la lógica de la aplicación se ejecuta más de una vez dependiendo de
la aplicación, de modo que el tiempo total que toman las diferentes aplicaciones es
representativo en términos de intensidad computacional. Vale la pena señalar que
hay dos versiones diferentes de la misma aplicación, la rediseñada, es decir, el que
usa las versiones de eficiencia energética de los micro-benchmarks, y la original,
usan el mismo número de ejecuciones durante los experimentos.
Iteraciones: Esto indica el número de veces que se ejecuta la aplicación completa,
con todas sus ejecuciones. Esto se hace para obtener significancia estadística. Para
las aplicaciones, usamos 10 iteraciones.
El diagrama de diseño de clases se muestra en la Figura 5.3. La clase MainEvaluation es
la que lleva a cabo el proceso de ejecución de una aplicación tantas veces como se desee,
mientras realiza la administración de subprocesos y genera el resultado que contiene los
consumos medidos de cada aplicación. La clase RunnerThread implementa la interfaz Ja-
va Runnable, por lo que se puede iniciar en una secuencia separada. Cada RunnerThread
ejecuta una tarea determinada tantas veces como el valor de ejecución definido por los
parámetros. Finalmente, la clase Task define la tarea que se ejecutará para cada caso. Por
ejemplo, GradientDescentTask implementa el algoritmo de descenso de gradiente. Se pue-
de ver entonces que cada aplicación solo debe heredar esta clase abstracta y definir el
método run() para ajustarse al entorno de medición.
Cuando se inicia una prueba, la instancia de MainEvaluation recibe todos los parámetros,
los procesa y, finalmente, almacena la información en la clase de Properties. Luego, de
acuerdo con lo especificado por los parámetros, se crea un RunnerThread para cada sub-
proceso que se lanzará para preparar la tarea que se ejecutará. Una vez que las tareas
finalizan, MainEvaluation genera la salida especificando el tiempo total transcurrido y las
muestras de consumo de energía.
Para obtener medidas en los servidores, se utilizó un dispositivo externo llamado Power-
Meterr2, Figura 5.4. Este dispositivo mide el voltaje, el amperaje, la potencia activa y la
potencia aparente de una red eléctrica monofásica. Toma 2,000 muestras por segundo, y
es muy preciso ya que su error de medición es menor que e l2%. Este dispositivo fue ele-
gido específicamente porque introduce un ruido mínimo a la medida, ya que es externo
a la computadora que ejecuta los micro-benchmarks y las aplicaciones. Luego, conecta-
mos un procesador host APD AMD A8-5600K de 4 núcleos (corriendo a 3600 MHz), 8 GB
RAM DDR3 y Ubuntu 17.04 al dispositivo, que a su vez estaba conectado a la línea de
alimentación. La computadora obtiene mediciones periódicas del dispositivo a través de
un puerto MODBUS RS232. Por lo tanto, durante las pruebas, la conectividad de red se
deshabilitó y la pantalla de la computadora host se apagó. Finalmente, la Ecuación [ 5.2
2http://www.powermeter.com.ar/eco/
88
Figura 5.3: Diagrama de clases del software utilizado para medir el consumo de aplcaciones cien-tíficas en servidores
se usa para calcular el porcentaje de reducción en el uso de energía introducido por las
versiones de micro-benchmark eficientes:
EnergyUsageReduction= [∑ Joules(Executioni)− ∑ Joules(ImprovedExecutioni)
∑ Joules(Executioni)]/nºo f iterations ∗ 100
(5.2)
donde Joules(Executioni ) representa el consumo de una iteración individual de la versión
menos eficiente de un micro-benchmark, mientras que Joules(ImprovedExecutioni) es el
consumo de una iteración individual de una versión mejorada. Además, Joules consumi-
do por una iteración individual es la suma de las muestras de potencia activa (en vatios)
multiplicadas por el tiempo que lleva ejecutar la iteración (en segundos). Tener en cuenta
que la reducción del consumo de energía siempre es inferior a l100%, ya que incluso la
versión más eficiente de un micro-benchmark exigirá algo de energía para ejecutarse.
89
Figura 5.4: Power Meter
5.4. Aplicaciones de usuario final
Para estas pruebas ejecutamos las aplicaciones manualmente, sin presentarlas en un soft-
ware especial. Tomamos esta decisión ya que, en esta instancia de la investigación, obtu-
vimos hardware especializado que facilita la medición. Como estas aplicaciones necesitan
la interacción con el usuario, presentamos un nuevo software para generar nuestros esce-
narios. Usando una herramienta externa llamada Robotium para definir diferentes casos
de prueba se obtuvieron resultados numéricos y exactos. Robotium amplía el framework
de test de Android para que sea más fácil escribir tests. En otras palabras, Robotium
permite a los desarrolladores escribir y ejecutar pruebas para aplicaciones de Android3
y ofrece varias ventajas: código más breve, tiempo mínimo necesario para escribir ca-
sos de prueba sólidos, casos de prueba potentes que tienen un conocimiento mínimo de
la aplicación bajo prueba, maneja múltiples actividades de Android automáticamente,
la legibilidad de los casos de prueba es mejorada en gran medida en comparación con
las pruebas de instrumentación de Android, tiempos automáticos y retrasos, automática-
mente encuentra Vistas, toma sus propias decisiones automáticamente (cuándo despla-
zarse, etc.), la ejecución de la prueba es rápida, los casos de prueba son más robustos
debido al enlace de tiempo de ejecución a los componentes de la GUI, se integra sin pro-
blemas con Maven o Ant. Como resultado, con Robotium los experimentos se pudieron
ejecutar varias veces simulando escenarios muy similares validando los resultados.
En esta instancia de la investigación, los experimentos se realizaron en un Samsung Ga-
laxy SIII, con las siguientes características: CPU Quad-core de 1,4 GHz Cortex-A9, 2 GB
de RAM, 16 GB de almacenamiento interno y batería de ion de litio de 2.100 mAh. Este
nuevo hardware representa la evolución de los dispositivos móviles, lo que nos obliga a
actualizar cada nueva prueba que tenemos que realizar. Además, otra actualización en
la metodología fue la forma de medir el consumo de energía de cada aplicación, incor-
3http://code.google.com/p/robotium/
90
Figura 5.5: Power Monitor
poramos un hardware especializado. Específicamente, utilizamos Power Monitor4, una
herramienta capaz de medir la potencia de cualquier dispositivo que emplee una bate-
ría de litio a una frecuencia de 5Khz (5,000 veces por segundo). Esta herramienta viene
junto con una aplicación de software que muestra las medidas de voltaje y amperaje, y
permite al usuario exportar esta información en diferentes formatos (por ejemplo, CSV).
La Figura 5.5 muestra la configuración del dispositivo.
5.5. Resumen
Este Capítulo define claramente los métodos de investigación utilizados para realizar
el estudio. Se presentan diferentes limitaciones y problemas para medir el consumo de
energía. Además, explicamos cómo resolvimos estos problemas usando diverso software
y hardware. Se dan razones y justificaciones para el diseño de la investigación, los instru-
mentos de investigación, las fuentes de datos, las técnicas de recopilación de datos, etc.
Desarrollamos 5 temas: consumo de energía de Java, Caliper, Robotium, Power meter y
Power Monitor. Además, presentamos los dispositivos utilizados para medir el consumo
de energía.
Luego, se propondrán los siguientes capítulos para presentar y explicar en detalle los
resultados y trabajos futuros.
4http://www.msoon.com/LabEquipment/PowerMonitor/
91
92
Capıtulo 6
Resultados
Este capítulo tiene como objetivo mostrar, evaluar y analizar los resultados de las prue-
bas propuestas. Con los resultados obtenidos de la evaluación de micro-benchmarks, se
generan guías de buenas prácticas. Con estas guías, los desarrolladores pueden imple-
mentar aplicaciones científicas eficientes para aprovechar los recursos y capacidades de
los dispositivos Android, contribuyendo a la inserción de dispositivos móviles en el pro-
cesamiento científico. Además, junto con estas buenas prácticas, se propone una serie
de refactorizaciones para llevar aplicaciones tradicionales a dispositivos móviles, lo que
permite la creación de una herramienta automática para realizar la refactorización de
aplicaciones y facilitar el análisis del consumo de energía en dispositivos móviles. Tras
la evaluación de los micro-benchmarks individuales, se realiza la evaluación del impacto
de las buenas prácticas propuestas en aplicaciones científicas reales. Con esto en mente,
usamos aplicaciones científicas escritas en Java. Finalmente, la desviación estándar fue
inferior al 3% en todos los experimentos, lo que se considera un resultado aceptable. Esta
desviación es el resultado del consumo de energía generado por la activación impredeci-
ble de los servicios esenciales del sistema operativo.
Luego, en las siguientes Secciones, mostramos y explicamos la mejora obtenida en cada
uno de los ocho grupos de micro-puntos de referencia explicados en el Capítulo 4. Ade-
más, agregamos un análisis de código Dex para comprender qué ocurre después de la
compilación del código Java en las aplicaciones Android. Con este objetivo, solo agrega-
mos instrucciones Dex que representan el código de micro-benchmark, es decir, evitamos
las instrucciones de Dex-code que representan bucles (por ejemplo, loop para ejecutar n
veces el micro-benchmark) que son comunes para las diferentes versiones del mismo
micro-benchmark. Agregar este código nos permite analizar las optimizaciones del com-
pilador y el comportamiento de los micro-benchmarks. Además, este código presenta las
instrucciones que debe ejecutar la JVM que puede cambiar su ejecución de acuerdo con
la versión (por ejemplo, las bibliotecas del sistema se implementan de manera diferente
93
en cada JVM). Entonces, podemos hacer un análisis más profundo utilizando este código
intermedio.
Además, la sección 6.2 presenta un breve análisis sobre el esfuerzo de los desarrolladores
para refactorizar una aplicación real. A lo largo de esa sección evaluamos las tácticas y
el conocimiento que necesitan los desarrolladores. Por lo tanto, este análisis es un primer
paso para automatizar el proceso o parte de él en algunos casos.
6.1. Resultados de Micro-benchmark (Móviles)
Finalmente, la Tabla 6.1 y la Figura 6.1 resumen los resultados obtenidos para los diferen-
tes grupos de micro-benchmarks (cuanto mayor sea el número mejor será el resultado,
es decir, menor energía consumo). Sobre la base de esta tabla aplicamos la ecuación 5.1
(EnergySaved = (1 −(∑ Executioni)/(nº of executions)
(∑ improvedExecutioni)/(nº of executions)) ∗ 100) para calcular el porcentaje de ener-
gía ahorrado en cada caso.
6.1.1. Copia de arreglos
En este trabajo, se eligió System.arraycopy para evaluar el uso de librerías, que es un mé-
todo incorporado de Java para copiar arreglos que es una operación común en el software
científico. Para evaluar y comparar la eficacia de este método, utilizamos una implemen-
tación manual de la misma funcionalidad con un arreglo de 8192 caracteres (8 Kb de
información). Los resultados se muestran en la Tabla 6.1 y en la Figura 6.1a. El número
de ejecuciones obtenidas muestra que el uso del método proporcionado por Java me-
jora la copia manual del arreglo en casi un 17% de reducción del consumo de energía
en cada ejecución individual de la versión utilizando la biblioteca. Para este grupo de
micro-benchmark podemos observar que la disminución porcentual en el tiempo de eje-
cución es similar a la reducción del consumo de energía: esta refactorización disminuye
el 16% de tiempo de ejecución.
Los Algoritmos 6.1 y 6.2 muestran el código Dex de los dos micro-benchmarks represen-
tativos de la copia de arreglo. Podemos ver que en el caso del algoritmo de copia manual
de arreglos Algoritmo 6.1- los elementos individuales se copian uno por uno, mientras
que el Algoritmo 6.2 solo hace una llamada a Sistema.arraycopy que es un método nativo.
Un método nativo es un método implementado por la JVM que puede implementarse
de manera diferente por cada JVM y se puede optimizar de varias maneras que no son
una posibilidad para los desarrolladores de Java. Por ejemplo, la copia de la arreglos se
puede hacer con un único memcpy/memmove desde un método nativo, en oposición a n
operaciones de copia distintas en el nivel de Java en la copia de arreglos manual. A pesar
94
Micro-benchmark Versión Número de
ejecuciones
(promedio)
Reducción
de consumo
de energía
(%)
Desviación
estándar(%)
Tiempo de
ejecución
(ms)
Reducción
en tiempo
de
ejecución
(%)
Copia de arreglosCopia manual 11,103,650 0.6 2.84
System.arrayCopy 13,428,990 17 1.3 2.38 16
Creación de ObjetosCreación de objetosOn-demand
1,691,926,500 2.7 1.84E-2
Reuso de Objetos 15,433,805,000 89 2.8 1.74E-3 90
Acceso a atributos deun objeto
Uso de getter 115,459,467,000 2.9 1.97E-4
Acceso directo 919,194,540,000 87 2.1 3.22E-5 83
Manejo de StringsConcatenación de String(+)
1,791 2.5 17509.83
StringBuilder 1,399,352 99 2.8 22.33 99
Manejo deexcepciones
Uso de excepciones 2,612,158,650 2.9 1.19E-2
No uso de excepciones 250,029,732,150 98 2.9 1.17E-4 99
Uso de tipos de datosprimitivos
Clases 330,501,964,285 2.5 8.6204E-5
Uso de tipos de datosprimitivos
341,434,162,500 2 1.9 8.6221E-5 0
Recorrido dematrices
Por columna 149,443 2.2 237.72
Por fila 320,785 53 1.8 90.87 61
Operacionesaritméticas
Adición double 412,940,900,000 2.2 7.42E-5
Adición de float 435,343,470,000 37 2.5 7.10E-5 4
Adición de long 788,482,635,000 47 2.6 3.67E-5 50
Adición int 1,183,897,395,000 65 2.0 2.53E-5 65
Cu
ad
ro6
.1:R
esultad
od
eM
icro-benchmarks
(Móviles)
95
0
15000
30000
45000
60000
75000
90000
105000
120000
135000
150000
Array Copy
Executions/1
00 u
ntil battery
deple
tion
ManualArrayCopySystemArrayCopy
(a) Resultados de copia de arreglos
0
17500
35000
52500
70000
87500
105000
122500
140000
157500
175000
Object creation
Executions/1
00.0
00 u
ntil battery
deple
tion Creation
Reuse
(b) Resultados de creación de objeto
0
100000
200000
300000
400000
500000
600000
700000
800000
900000
1e+06
Object field access
Executions/1
,000,0
00 u
ntil battery
deple
tion
InvocationNoInvocation
(c) Resultados de acceso a atributosde un objeto
1 2 4 8
16 32 64
128 256 512
1024 2048 4096 8192
16384 32768 65536
131072 262144 524288
String handling
Executions/1
0 u
ntil battery
deple
tion
ConcatenationStringBuilder
(d) Resultados de manejo de Strings
0
27500
55000
82500
110000
137500
165000
192500
220000
247500
275000
Exception handling
Executions/1
,000,0
00 u
ntil battery
deple
tion
UseExceptionNoException
(e) Resultado de manejo de excepcio-nes
0
30000
60000
90000
120000
150000
180000
210000
240000
270000
300000
330000
360000
390000
Use of primitive data types
Executions/1
,000,0
00
ObjectPrimitive
(f) Resultados de uso de tipos de da-tos primitivos
0
30000
60000
90000
120000
150000
180000
210000
240000
270000
300000
330000
360000
Matrix traversal
Executions u
ntil battery
deple
tion
ColsRows
(g) Resultados de recorrido de matri-ces
0
125000
250000
375000
500000
625000
750000
875000
1e+06
1.125e+06
1.25e+06
Arithmetic operations
Executions/1
,000,0
00 u
ntil battery
deple
tion
DoublesFloatsLongs
Ints
(h) Resultados de operaciones aritméticas
Figura 6.1: Resultados de los grupos de micro-benchmarks96
1: :if 0
2: v0 = new char[v5]3: v1 = #04:
5: :goto 1
6: if (v1 < v5) :if 1
7: v2 = v2 + #18: goto goto 09:
10: :if 1
11: v4 = v3[v1]12: v0[v1] = v413: v1 = v1 + #114: goto goto 1
Algorithm 6.1: Dex-code copia de arreglosmanual
1: :if 0
2: v0 = new char[v3]3: java.lang.System.arraycopy(v4,v0,v4,v3)4: v1 = v1 + #15: goto goto 0
Algorithm 6.2: Dex-code System.arraycopy
de que elegimos esta biblioteca para hacer los experimentos, pueden extenderse a otras
bibliotecas que usan diferentes tácticas para mejorar el rendimiento.
6.1.2. Creación de objetos
La hipótesis de que la creación de objetos consume más energía que la reutilización de
objetos se refleja en los resultados presentados en esta subsección. La Tabla 6.1 y la Figu-
ra 6.1b muestran alrededor del 90% de reducción en el uso de energía y en el tiempo de
ejecución mediante la reutilización de objetos sobre la creación de objetos nuevos (listas
en nuestros experimentos). Ciertamente, el esfuerzo computacional para crear un nuevo
objeto consume más energía que el esfuerzo necesario para restablecer uno ya creado.
El Algoritmo 6.3 muestra el código para crear e inicializar una instancia de List. En este
caso, es necesaria una instrucción para crear la Lista y otra para inicializar la Lista. Por
otro lado, el Algoritmo 6.4 muestra el Dex-Code de la reutilización de un objeto. Para
reutilizar una Lista, solo es necesario llamar al método clear() que elimina todos los ele-
mentos que están contenidos en la Lista. A pesar de que el número de instrucciones para
ejecutar en los dos micro-puntos de referencia es muy similar, el costo de ejecutarlos es
significativamente diferente.
Como mencionamos anteriormente, el uso de la memoria por parte de los objetos y el
costo de crear objetos consume mucha energía. Esto significa que los desarrolladores no
deben crear objetos arbitrariamente en el código de la aplicación y en su lugar deben
reutilizar instancias ya creadas siempre que sea posible. Además, debemos considerar
que las mejoras pueden variar según los objetos que se crean: el esfuerzo computacional
97
1: :if 0
2: v1 = new java.util.ArrayList3: v1.<init>()4: this.list = v15: v1 = this.list6: v2 = "create caliper.list"7: v1.add(v2)8: v0 = v0 + #19: goto goto 0
Algorithm 6.3: Dex-code creación de objetos
1: :if 0
2: v1 = this.list3: v1.clear()4: v1 = this.list5: v2 = "create caliper.list"6: v1.add(v2)7: v0 = v0 + #18: goto goto 0
Algorithm 6.4: Dex-code reuso de objetos
necesario para crear un objeto simple, como un entero, es menor que el esfuerzo de crear
un objeto complejo, como un objeto con numerosos atributos . Sin embargo, en esta tesis
evaluamos listas que representan un tipo de objeto popular de tamaño mediano para
implementar otras estructuras de datos y objetos de dominio.
6.1.3. Acceso a un atributo de objetos
La obtención de atributos de objetos directamente y no a través de un getter represen-
ta una reducción del 87% en el consumo de energía y una disminución del 83% en el
tiempo de ejecución. La Tabla 6.1 y la Figura 6.1c muestran que el acceso directo a los
atributos que se utilizan con frecuencia da como resultado un menor consumo de ener-
gía que el acceso a través de un método. Sin embargo, los principios OO desalientan a
los programadores a declarar como públicos todos los campos de una clase, o combinar
varios métodos de una clase que no están relacionados para evitar invocaciones repe-
titivas. La pérdida de legibilidad y el alto acoplamiento de las aplicaciones resultantes
superarían el beneficio. En consecuencia, los desarrolladores deben determinar hasta qué
punto es valioso dejar de lado las cuestiones de diseño para favorecer el rendimiento.
Sin embargo, hay casos comunes en los que los principios de programación de OO no se
ven afectados y los desarrolladores pueden reducir el uso de energía y disminuir el tiem-
po de ejecución, por ejemplo, accediendo directamente a un atributo de clase cuando la
operación se realiza en la misma clase.
En este grupo de micro-benchmarks, el consumo de energía varía porque en el caso del
acceso directo solo hay una operación de acceso, mientras que en el caso del acceso me-
diante un método hay una invocación al método y, luego, el mismo acceso directo que
en el primer caso. Entonces, el segundo micro-benchmark implica el mismo esfuerzo
computacional que el primer micro-benchmark más un esfuerzo extra (invocación del
método). Podemos ver estos comportamientos en los Algoritmos 6.5 y 6.6. El Algorit-
mo 6.5 muestra las instrucciones que llaman al método getter, y el código del método que
98
1: :if 0
2: this.getField()3: move-result v14: v0 = v0 + #15: goto goto 06:
7: public int getField () {8: v0 = this.field9: return v0 }
Algorithm 6.5: Dex-code invocación de méto-dos
1: :if 0
2: v1 = this.field3: v0 = v0 + #14: goto goto 0
Algorithm 6.6: Dex-code acceso directo
contiene las instrucciones que se ejecutan directamente en el Algoritmo 6.6.
6.1.4. Manejo de Strings
Los resultados de las dos alternativas de este grupo de micro-benchmarks se muestran
en la Tabla 6.1. Como se esperaba, el uso de la clase StringBuilder reduce el consumo
de energía y el tiempo de ejecución en más del 90%. Debido a su gran diferencia, los
resultados se presentan con una escala logarítmica en la Figura 6.1d.
La razón principal de esta variación es que los strings en los programas Java, como "abc",
se implementan como instancias de la clase String. Los String son clases inmutables, por
lo tanto, sus valores no se pueden cambiar después de que se crean. En consecuencia,
usar el operador "+" para concatenar strings implica la creación de un objeto StringBuil-
der temporal, que requiere asignar memoria. En contraste, la clase StringBuilder mantie-
ne una matriz de caracteres mutable interna y proporciona métodos para modificarla sin
crear nuevos objetos. Podemos ver este comportamiento analizando el código Dex de ca-
da micro-benchmark. El Algoritmo 6.7 presenta Dex-code de la concatenación utilizando
la clase String y muestra que para concatenar dos cadenas usando la clase String es ne-
cesario crear un objeto StringBuilder, copiar el valor de la cadena, agregar las cadenas y
finalmente mueve el valor a la cadena original. Por otro lado, Algoritmo 6.8 solo necesita
agregar las dos cadenas para hacer la concatenación basada en StringBuilder. Mientras
que en el primer caso para cada concatenación se crea un objeto, se invocan tres métodos
y se copian tres resultados; en el segundo caso solo se llama un método.
6.1.5. Manejo de excepciones
Los resultados que se muestran en la Tabla 6.1 y la Figura 6.1e respaldan la primera
hipótesis presentada en la Sección 4.1.5. Como se esperaba, los desarrolladores pueden
99
1: v4 = new java.lang.StringBuilder2: java.lang.String.valueOf()3: move-result-object v5 v44: <init>(v5) v5 = "a"5: v4.append(v5)6: move-result-object v47: v4.toString()8: move-result-object v39: v4 = #1
10: v4 = v4 + v0
Algorithm 6.7: Dex-code String
1: v4 = "a"2: v0.append(v4)3: v4 = #14: v4 = v4 + v1
Algorithm 6.8: Dex-code StringBuilder
reducir el uso de energía de un programa al no usar excepciones. De acuerdo con esto, la
Figura 6.1e muestra la mejora cuando los desarrolladores no lanzan una excepción para
el flujo de código normal. Evitando el uso de excepcione, reducimos más del 90% del uso
energía y el tiempo de ejecución. Como se explica en la Sección 4.1.5, la creación de obje-
tos adicionales y las optimizaciones limitadas realizadas por la JVM producen un mayor
consumo de energía al lanzar excepciones. Además de las optimizaciones limitadas rea-
lizadas por la JVM, presentamos el Dex-code que implementa los dos micro-benchmarks
de este grupo. En el Algoritmo 6.9 podemos observar cómo lanzar una excepción lleva
a la creación del objeto de excepción más su proceso de lanzamiento y captura, que re-
quiere la ejecución de varias instrucciones. Sin embargo, en el Algoritmo 6.10 podemos
ver que el mismo código sin excepciones necesita un pequeño número de instrucciones
para ejecutar el micro-benchmark y estas son líneas que se ejecutan también en el primer
algoritmo. Como conclusión, una operación que incluye un lanzamiento de excepción
ejecuta las mismas líneas que la misma operación sin excepciones pero también agrega
una creación de objeto y el procesamiento de nuevas instrucciones.
Para garantizar el consumo de energía reducido, podemos concluir que el uso de excep-
ciones debe reservarse solo para situaciones de error que no pueden ser resueltas por la
clase. Por ejemplo, manejar manualmente una división por cero es una tarea sencilla para
los desarrolladores.
6.1.6. Uso de tipos de datos primitivos
Cada lenguajetiene elementos específicos como tipos de datos, operadores y declara-
ciones. En Java, casi todo es un objeto. Sin embargo, como mencionamos en la subsec-
ción 4.1.6, Java tiene algunos tipos de datos primitivos, que tienen su clase correspon-
diente (por ejemplo, la clase Boolean ajusta el tipo de datos primitivo boolean).
Asumimos que la memoria guardada mediante el uso de tipos de datos primitivos puede
100
1: :if 0
2: try
3: v0 = a0% #24: if (v0 != 0) :if 15: v0 = new excep-
tions.EvenException6: v0.<init>()7: throw v08:
9: :if 1
10: return-void11:
12: :goto 1
13: catch(exceptions.EvenException):catch 0
14: v1 = v1 + #115: goto goto 016:
17: :catch 0
18: move-exception v019: v2 = v2 + #120: goto goto 1
Algorithm 6.9: Dex-code excepción
1: :if 0
2: v2 = v0% #23: if (v2 != 0) :if 1
4: v1 = v1 + #15:
6: :if 1
7: v0 = v0 + #18: goto goto 0
Algorithm 6.10: Dex-code sin excepción
101
disminuir el consumo total de energía. Esta hipótesis es válida, pero aplicar la refactori-
zación asociada ahorra menos energía que el resto de los grupos de micro-benchmarks
evaluados hasta este momento. La Tabla 6.1 y Figure 6.1f muestran una reducción del
2% en el consumo de energía en este grupo. Por otro lado, el tiempo de ejecución no
mejoró. Aunque los experimentos se evaluaron solo para el tipo de datos long, se espera
que los resultados no tengan una variación significativa en otros tipos de datos porque
la lógica de las clases contenedoras y sus estructuras son similares a los otros casos. Pre-
sentamos el Dex-code de los dos micro-benchmarks en los Algoritmos 6.11 y 6.12. El
Algoritmo 6.11 muestra que operar con clases implica una llamada a método (valueOf())
cada vez que se ejecuta una operación con un objeto de este tipo, pero las otras instruc-
ciones son las mismas que las ejecutadas en el Algoritmo 6.12 donde se usan los tipos de
datos primitivos. En resumen, estas llamadas a métodos no son costosas en términos de
consumo de energía cuando se introduce una operación aritmética.
6.1.7. Recorrido de matrices
Como mencionamos en el Capítulo 4, las matrices son una estructura común en la pro-
gramación científica, y una de las operaciones más comunes utilizadas en las estructuras
matriciales es la de recorrer sus elementos. Esta primitiva sirve como base para imple-
mentar otras operaciones matriciales importantes como la multiplicación. Comparamos
el rendimiento del recorrido por filas con el recorrido por columnas utilizando una ma-
triz de 1024x1024 de enteros (tipo de datos int). Los resultados muestran una reducción
del 53% en el uso de energía y una disminución del 61% en el tiempo de ejecución. Estas
observaciones son respaldadas por los resultados presentados en la Tabla 6.1 y la Figu-
ra 6.1g.
En este caso particular, la asignación de memoria es el factor que influye en el consu-
mo de energía, en función de la proporción de aciertos de la memoria caché de la CPU
al recorrer matrices. Por ejemplo, las matrices en Java están representadas por objetos;
luego, una matriz bidimensional es un objeto en el que cada celda de la primera ma-
triz ha asociado otra matriz (Figura 6.2). En consecuencia, cuando la matriz es recorrida
por una fila, todas las celdas correspondientes a arr [0] se recorren primero, continuando
con arr [1] y haciendo un bucle de la misma manera hasta la última celda de la prime-
ra dimensión de arr. Al leer arr [0][0], se almacenan en caché las celdas que están cerca
(arr [0][0] to arr [0][n] y pueden almacenarse en caché algunas celdas de la siguiente fila).
Luego, cuando el algoritmo recorre la matriz por fila, la siguiente celda (arr [0][1]) proba-
blemente se almacena en caché, lo que es más rápido que recuperar la celda de la RAM.
Sin embargo, cuando el algoritmo recorre por columna, algunos de los siguientes accesos
a la celda (arr [1][0], arr [2][0], ..., arr [n][0]) es probable que causen una falta de caché.
102
1: v4 = #02: java.lang.Long.valueOf(v5)3: move-result-object v34: v2 = #05:
6: :goto_0
7: if (v2 < a0) :if_0
8: v3.longValue()9: move-result-wide v4
10: return-wide v411:
12: :if 0
13: v0 = #014:
15: :goto_1
16: v4 = this.limit17: int-to-long v4, v418: cmp-long v4, v0, v419: if (v4 < 0):if_1
20: v2 = v2 + #121: goto goto_022:
23: :if 1
24: v3.longValue()25: move-result-wide v426: v0 = v0 + v427: java.lang.Long.valueOf(v5)28: move-result-object v329: v4 = #130: v4 = v4 + v031: goto goto_1
Algorithm 6.11: Dex-code uso de clases
1: v3 = #02: v2 = #03:
4: :goto_0
5: if (v2 < a0) :if_0
6: return-wide v37:
8: :if 0
9: v0 = #010:
11: :goto_1
12: v5 = this.limit13: int-to-long v5, v514: cmp-long v5, v0, v515: if (v5 < 0) :if_1
16: v2 = v2 + #117: goto goto 018:
19: :if 1
20: v0 = v0 + v321: v5 = #122: v5 = v5 + v023: goto goto_1
Algorithm 6.12: Dex-code tipos de datos prim-itivos
103
arr
0 1 2
int[ ][ ] arr = new int [3][ ];
arr [0] = new int [3];
arr [1] = new int [4];
arr [2] = new int[1];
Figura 6.2: Arreglos en Java
1: :if 2
2: v4 = this.matrix3: v4 = v4[v1]4: v3 = v4[v0]5: v1 = v1 + #16: goto goto 2
Algorithm 6.13: Dex-code recorrido porcolumnas
1: :if 2
2: v4 = this.matrix3: v4 = v4[v0]4: v3 = v4[v1]5: v1 = v1 + #16: goto goto 2
Algorithm 6.14: Dex-code recorrido por filas
Además, presentamos el Dex-code de estas dos operaciones de recorrido. Como podemos
ver en los Algoritmos 6.13 y 6.14 la única diferencia entre los micro-benchmarks está en
que las líneas 3 y 4 que cambian el orden de la operación. Sin embargo, como explicamos
anteriormente, este simple cambio genera fallas en la memoria caché.
6.1.8. Operaciones aritméticas
Este grupo de micro-benchmarks implicó agregar un valor constante c a una variable
numérica declarada variando el tipo de dato utilizado; es decir que, resolvimos X + c
usando variables y constantes float, double, int y long. Luego, comparamos el consumo de
energía de diferentes tipos de datos. La Tabla 6.1 y la Figura 6.1h muestran los resultados.
Claramente, las operaciones con números flotantes tienen más costo que las operaciones
con números enteros. Por lo tanto, este último grupo usa menos energía que el primer
grupo. Además, este grupo de micro-benchmarks es un ejemplo de la ausencia de una
correlación lineal entre la reducción en el uso de energía y el tiempo de ejecución. Mien-
tras que los porcentajes de reducción en el uso de energía al usar los tipos de datos float,
long e int son 37%, 47% y 65% respectivamente, los porcentajes de tiempo de ejecución
disminuidos son 4%, 50% y 65%. Como resultado, usar el tipo de datos más específico
es una buena práctica para reducir el consumo de energía en dispositivos móviles.
104
En general, los tipos de datos double y long consumen más energía que los tipos de datos
float e int, respectivamente, porque los primeros tipos de datos proporcionan una mayor
precisión y/o un mayor rango de valores y requieren más espacio de memoria y más
tiempo de procesamiento que los segundos. En consecuencia, tener un rango más amplio
de valores (tipo de datos long y double) o más precisión (tipo de datos double) implica
un mayor consumo de batería. Finalmente, para este grupo de micro-benchmarks solo
presentamos el Algoritmo 6.15 porque la diferencia entre micro-benchmarks reside en el
tipo de variables.
1: :if 0
2: v3 = #1233: v3 = v3 + v14: v0 = v0 + #15: goto goto 0
Algorithm 6.15: Dex-code operación aritmética
6.1.9. Resumen micro-benchmarks en dispositivos móviles
Diferentes micro-benchmarks comúnmente encontrados en aplicaciones científicas ba-
sadas en Java fueron seleccionados para mostrar su consumo de energía en dispositi-
vos móviles Android. En todos los casos, estos experimentos muestran que los micro-
benchmarks que tienen un peor rendimiento en términos de tiempo consumen más ener-
gía también. Esta variación podría surgir como resultado de diferentes factores, que se
explicaron en detalle con los resultados para cada micro-benchmark. En resumen, los
resultados informados muestran que es mejor usar System.arrayCopy que una implemen-
tación manual de la misma funcionalidad. Además, algo tan trivial como el sentido de
recorrido de una matriz puede mejorar el rendimiento. Además, esta investigación refleja
la importancia de evitar operaciones con tipos de datos inmutables. Con respecto a los ti-
pos de datos numéricos, los desarrolladores deben analizar la aplicación y usar el tipo de
datos más específico para ahorrar energía, a veces a expensas de perder precisión. Otra
forma de reducir el consumo de energía es evitar el uso de excepciones en las aplicaciones
siempre que sea posible. Muchas veces, los objetos comunes pueden transmitir informa-
ción de error, lo que conduce a mecanismos para superar situaciones indeseables en la
aplicación sin lanzar una excepción. Finalmente, al referirnos a las primitivas básicas y
comunes en la programación OO, como el acceso al campo de objetos y la creación de ob-
jetos, mostramos que cuando estas primitivas no son necesarias, deben evitarse siempre
que sea posible, ya que consumen mucha energía. Por último, el uso de tipos de datos pri-
mitivos en lugar de sus clases correspondientes dio como resultado una pequeña mejora
energética.
105
1
2
4
8
16
32
64
128
256
512
1024
String Handling
Exception Handling
Object C
reation
Object Field Access
Arithmetic operations
Matrix Traversal
Array Copy
Primitive D
ata Type
Ga
in
Micro−benchmarks evaluation
Smartphone
Figura 6.3: Comparación de resultados de micro-benchmark
Por último, ofrecemos una comparación de la mejora de los grupos de micro-benchmarks,
ordenados de mayor a menor (ver la Figura 6.3).
6.2. ¿Cómo refactorizar aplicaciones?
En un intento de ilustrar el compromiso entre el esfuerzo de análisis de problemas y el
esfuerzo de ejecución de refactorización versus ganancia (en términos de energía) para
cada refactorización antes de presentar las aplicaciones de prueba, discutiremos el es-
fuerzo de los desarrolladores de aplicar las refactorizaciones asociadas a los grupos de
referencia. Aquí, "problema" se refiere a una imperfección del código que causa un con-
sumo de energía adicional.
Todos los grupos de micro-benchmarks necesitan un análisis previo antes de aplicar la
refactorización correspondiente. Esto se debe a que cualquiera de las refactorizaciones
implica un análisis semántico y un cambio de diseño; luego, podemos evaluar el esfuer-
zo necesario para realizar dos pasos: alcance del análisis y alcance de refactorización. De
esta forma, el alcance del análisis se refiere a la cantidad de unidades de código que los
desarrolladores deben analizar para determinar dónde refactorizar sin cambiar la fun-
cionalidad de la aplicación, es decir, si el análisis solo implica las secciones del código
donde aparece el problema (por ejemplo, creación de objeto). , llamada de método, etc.),
o incluye más elementos como métodos que llaman a esas secciones u otras clases. Por
106
otro lado, el ámbito de refactorización se refiere a cuántas secciones de código deben mo-
dificarse para aplicar la refactorización una vez que se han detectado las ocurrencias de
los problemas asociados. La Tabla 6.2 resume como se dan estos dos aspectos en nues-
tras refactorizaciones. En esta Tabla, los valores que pueden tomar los dos aspectos son
Sentencia, Método y Aplicación. En el ámbito de Análisis, el valor indica si los desarrolla-
dores deben analizar solo la semántica de las sentencias en los que aparece/se utiliza el
problema, la influencia del problema en el Método o su influencia en toda la Aplicación.
Por el contrario, los valores para el ámbito de Refactorización indican si los desarrollado-
res deben modificar solo las sentencias donde aparece el problema o si la refactorización
implica más esfuerzo.
Como podemos ver, algunas de las refactorizaciones requieren menos esfuerzo en ambos
aspectos, lo que significa que son más fáciles de analizar y aplicar. Primero discutimos
estas refactorizaciones. Comenzando con el acceso a los atributos de un objeto, donde la
refactorización implica la ruptura de la encapsulamiente de datos, su alcance de Análisis
y la determinación del alcance de Refactorización son tareas triviales que incluso pueden
automatizarse. En este caso, los desarrolladores solo deben tener en cuenta las restriccio-
nes de encapsulamiente y, luego, deben cambiar todas las llamadas al método Getter por
el acceso directo al atributo siempre que sea posible. Esta refactorización se puede aplicar
para cambiar solo los accesos de una clase a sus propios atributos o adicionalmente para
cambiar los accesos a atributos de clase externos (en este caso el atributo tiene que ser
un atributo público) pero el alcance del Análisis y el de Refactorización están circuns-
critos a la clase problemática. A continuación, para cambiar las clases contenedoras por
tipos de datos primitivos es necesario analizar si se utiliza algún método específico de
la clase; después de esto, el esfuerzo necesario para aplicar la refactorización es mínimo:
los desarrolladores deben cambiar el tipo de atributo y cambiar los métodos utilizados
por la operación equivalente en el tipo de datos primitivo. De esta forma, la refactori-
zación solo afecta las sentencias donde aparece el atributo y los desarrolladores pueden
detectarlas buscando el nombre del atributo. Ahora, después de presentar estas dos refac-
torizaciones, analizamos el resto de las refactorizaciones, que inherentemente necesitan
más esfuerzo en relación con los dos aspectos analizados.
Primero, antes de usar bibliotecas o métodos integrados de Java, es necesario tener co-
nocimiento sobre las bibliotecas y métodos existentes. Además, detectar las secciones de
código que pueden ser reemplazadas por funcionalidades incorporadas o métodos de
biblioteca no es una tarea trivial o automatizable. Por otra parte, las alternativas son di-
versas, y lo más apropiado depende de varios factores de ingeniería de software. Luego,
los desarrolladores deben analizar todo el código fuente teniendo en cuenta sus cono-
cimientos previos, ya que es posible que no tengan ninguna pista sobre dónde y cómo
deben aplicar la refactorización. El segundo grupo que mencionamos en la última sub-
sección es el recorrido de la matriz. Aplicar la refactorización de recorrido es una tarea
107
Grupos de Microbenchmark/Refactoring Alcance del análisis Análisis del Refactoring
Acceso a atributos de un objeto Sentencia Sentencia
Uso de tipos de datos primitivos Sentencia Sentencia
Copia de arreglos Aplicación Aplicación
Recorrido de matrices Método Método
Manejo de Strings Aplicación Sentencia
Operaciones arotméticas Aplicación Sentencia
Manejo de excepciones Método Aplicación
Creación de Objetos Aplicación Sentencia
Cuadro 6.2: Refactoring application effort
108
trivial en términos de código, pero no es una tarea trivial a la hora de analizar la semán-
tica del recorrido. Por ejemplo, el recorrido en la multiplicación de matrices no puede
cambiar. Sin embargo, después de un análisis, los desarrolladores podrían transponer las
matrices y, luego, cambiar el sentido del recorrido. Esto significa que incluso cuando el
paso de análisis no es una tarea fácil, existen diferentes estrategias que pueden emplear-
se para allanar el camino para aplicar la refactorización. Aún así, el alcance del análisis
cubre solo la sección donde se atraviesa la matriz y se utilizan sus elementos.
El siguiente grupo presentado es manejo de strings. Para generalizar este grupo, debe-
mos mencionar que los strings en Java se implementan a través de una clase inmutable.
Los desarrolladores deben evitar las clases inmutables cuando los valores de los objetos
cambian con frecuencia; aunque son útiles para preservar un valor de objeto. Entonces,
los desarrolladores necesitan tener conocimiento previo sobre la aplicación para deci-
dir si este tipo de clases es realmente necesario. Por ejemplo, son útiles en aplicaciones
concurrentes porque no pueden cambiar el estado y, como consecuencia, no pueden co-
rromperse por la interferencia de subprocesos o estar en un estado incoherente. Luego,
los desarrolladores deben analizar el código fuente en toda su extensión porque estas
clases pueden aparecer como parámetros de método, atributos de método, atributos de
clases, entre otros, lo que requiere un gran esfuerzo. El ámbito de refactorización, por
otro lado, se reduce, ya que los cambios debidos a este tipo de refactorizaciones implican
modificaciones de código a nivel de declaración.
Finalmente, las otras refactorizaciones (que corresponden a los grupos Operación arit-
mética, Manejo de excepciones y Creación de objetos) necesitan un análisis de código
previo aún más detallado. En otras palabras, los cambios dependen de la semántica de
las operaciones y del alcance de cada objeto. Es decir:
Para cambiar la precisión de una variable numérica los desarrolladores deben co-
nocer la precisión necesaria en esa aplicación o método.
Para evitar una excepción los desarrolladores deben saber cómo manejar el error o
la situación excepcional a lo largo de cualquier posible cadena de llamada al método
afectado.
Para reutilizar un objeto, los desarrolladores deben asegurarse de que el objeto no
se utilizará después de ese momento, es decir, los objetos se pueden usar durante
la ejecución en cualquier momento. Luego, los desarrolladores deben conocer la
secuencia de ejecución del código para ver si el mismo objeto se usa nuevamente o
puede ser reemplazado por otro.
Este último caso es uno de los más difíciles de detectar porque los desarrolladores tienen
que analizar el comportamiento del código en tiempo de ejecución. Además, el manejo
109
de excepciones es el único grupo en el que el ámbito de refactorización incluye no solo
el método M en el que se lanza la excepción sino también los métodos que llaman a M,
es decir, si la refactorización implica devolver un mensaje de error, es necesario cambiar
el métodos en la pila que se ven afectados por este error porque también tienen que
gestionar el mensaje de error.
6.3. Resultados de las aplicaciones de prueba en dispositivos mó-
viles
Después de obtener los resultados de los grupos de micro-benchmark, aplicamos estos
resultados a una selección de aplicaciones científicas reales obtenidas del proyecto Ibis/-
Satin. El objetivo principal de estas evaluaciones fue medir el impacto real de las buenas
prácticas en aplicaciones reales. En las siguientes subsecciones, explicamos los resultados
obtenidos para cada aplicación de prueba presentada en la sección 4.2. En esta sección,
evaluamos cada aplicación de prueba original (es decir, no modificada) contra una ver-
sión refactorizada en la que aplicamos cada primitiva de refactorización relacionada con
los grupos de micro-benchmarks previos. Medimos las mismas aplicaciones de dos ma-
neras: la primera medición no tiene en cuenta las capacidades multi-core de los dispositi-
vos móviles, mientras que la segunda usa esta capacidad para ejecutar dos instancias de
las aplicaciones al mismo tiempo. Las aplicaciones multi-core se ejecutan en tablets Acer
A100 que tienen un procesador de doble núcleo.
Las Tablas 6.3, 6.4 y 6.5 muestran los resultados de ejecutar las aplicaciones de prueba
en smartphones y tablets, respectivamente. Las Tablas 6.1, 6.3, 6.4, 6.5 y 6.6 presentan el
tiempo de ejecución individual para cada experimento. Con estos valores, podemos ver
que, al menos en nuestras condiciones experimentales, la reducción del uso de energía
implica menos tiempo de ejecución, pero no linealmente. En las siguientes subsecciones
analizamos estos resultados.
6.3.1. Fast Fourier Transform (FFT)
Como mencionamos en la Subsección 4.2.1, al refactorizar el código fuente el principal
cambio en esta aplicación fue la eliminación de las clases inmutables. Esto fue posible
mediante la modificación de una clase llamada Complex,que era inmutable en la aplica-
ción original. En la nueva versión, las instancias de clase Complex pueden cambiar los va-
lores de sus atributos sin crear una gran cantidad de instancias inmutables de dicha clase.
Sin embargo, en la aplicación refactorizada debemos tener especial cuidado cuando tra-
bajamos con estos objetos porque no podemos modificar los valores de los atributos de
los objetos en uso. Además, la precisión de los atributos se redujo sin alterar el resultado
110
Aplicación Versión Número de
ejecuciones
(promedio)
Reducción
de consumo
de energía
(%)
Desviación
estándar
(%)
Tiempo de
ejecución
(ms)
Reducción
en tiempo
de
ejecución
(%)
FFTOriginal 2,958,624 1.8 10.04
Refactorizada 4,501,692 34 2.7 6.64 33
MMULTOriginal 265,358 2.6 113.02
Refactorizada 620,446 57 2.0 49.09 56
KnapsackOriginal 764,696 1.3 38.56
Refactorizada 54,558,035 98 2.6 0.54 98
Cuadro 6.3: Resultados de aplicaciones (I5500 smartphone)
111
Aplicación Versión Número de
ejecuciones
(promedio)
Reducción
de consumo
de energía
(%)
Desviación
estándar
(%)
Tiempo de
ejecución
(ms)
Reducción
en tiempo
de
ejecución(%)
FFTOriginal 14,154,500 2.1 3.20
Refactorizada 21,848,470 35 2.9 2.08 35
MMULTOriginal 822,499 0.9 51.65
Refactorizada 1,398,069 40 1.3 33.69 34
KnapsackOriginal 2,887,815 2.0 15.79
Refactorizada 184,605,003 98 2.9 0.25 98
Cuadro 6.4: Resultados de aplicaciones (ViewPad 10s tablet)
112
Aplicación Versión Número de
ejecuciones
(promedio)
Reducción
de consumo
de energía
(%)
Desviación
estándar
(%)
Tiempo de
ejecución
(ms)
Reducción
en tiempo
de
ejecución
(%)
FFTOriginal 19,665,230 2.4 1.54
Refactorizada 35,238,914 44 1.4 0.91 40
MMULTOriginal 1,468,103 3.9 20.35
Refactorizada 3,948,948 62 0.9 7.70 62
KnapsackOriginal 4,303,748 3.24 6.81
Refactorizada 324,865,596 98 2.2 0.06 98
Cuadro 6.5: Resultados de aplicaciones (Acer A100 tablet)
113
Aplicación Versión Número de
ejecuciones
(promedio)
Reducción
de consumo
de energía(%)
Desviación
estándar
(%)
Tiempo de
ejecución
(ms)
Reducción
en tiempo
deejecución
(%)
FFTOriginal 12,202,676 2.9 2.24
Refactorizada 24,663,150 50 4.2 1.06 49
MMULTOriginal 1,363,580 1.5 17.50
Refactorizada 3,726,860 63 4.2 6.10 65
KnapsackOriginal 3,576,953 1.4 6.89
Refactorizada 241,204,637 98 4.9 0.10 98
Cuadro 6.6: Resultados de aplicaciones multicore (Acer A100 tablet)
114
0
50000
100000
150000
200000
250000
300000
350000
400000
450000
500000
(a) Samsung Galaxy I5500
Executions/1
0
OriginalModified
0
30000
60000
90000
120000
150000
180000
210000
240000
(b) ViewPad 10s
Executions/1
00
OriginalModified
0
40000
80000
120000
160000
200000
240000
280000
320000
360000
400000
(c) Acer A100
Executions/1
00
OriginalModified
Figura 6.4: FFT (Dispositivos Móviles)
115
de la aplicación. En resumen, obtuvimos una mejora favorable modificando los objetos
y disminuyendo la precisión de los atributos. Esta mejora fue constante en los diferentes
tipos de dispositivos móviles.
La Tabla 6.3 y la Figura 6.4 (a) muestran los resultados con las ejecuciones usando el
Samsung Galaxy I5500. De forma similar, la Tabla 6.3 y la Figura 6.4 (b) muestran los
resultados con la tablet ViewPad 10s. Por último, la Tabla 6.3 y la Figura 6.4 (c) muestran
los resultados con la tablet Acer A100. Las reducciones en el uso de energía son 34%, 35%
y 44% para el primer, segundo y tercer caso, respectivamente. Finalmente, la mejora en el
tiempo de ejecución es similar a los valores de reducción de uso de energía, a saber, 33%,
35% y 40%, respectivamente.
6.3.2. Matrix multiplication (MMULT)
Como en el caso anterior, el aspecto principal para evitar en esta aplicación fue la crea-
ción de objetos. Sin embargo, en esta aplicación la instanciación de diferentes clases se
realiza al comienzo de la ejecución (no se realiza progresivamente durante la ejecución).
Entonces, la principal diferencia con el caso anterior es que durante la ejecución de la FFT
hubo muchos objetos creados y utilizados de inmediato por la aplicación, mientras que
en MMULT las instancias de Matrix se utilizan desde el principio hasta el final de la eje-
cución . No usar una estructura recursiva tiene la ventaja de requerir menos objetos en la
memoria. La estructura de la matriz se rediseñó disminuyendo el número de creaciones
de objeto.
Presentamos los resultados obtenidos después de las ejecuciones. Los resultados del smartp-
hone Galaxy I5500 se muestran en la Tabla 6.3 y gráficamente en la Figura 6.5 (a). De la
misma manera, presentamos los resultados de la tablet ViewPad 10s en la Tabla 6.3 y la
Figura 6.5 (b). Finalmente, la 6.3 y la Figura 6.5 (c) muestran los resultados para la tablea
Acer A100. En esta aplicación se obtuvo una gran mejora ejecutando la versión refactori-
zada. Sin embargo, la variación en los resultados depende de la capacidad de RAM del
dispositivo, ya que el smartphone utilizado para las pruebas puede almacenar menos
objetos en la memoria que las tablets debido a la RAM total disponible.
Los porcentajes de reducción en el consumo de energía son del 57% para el smartphone,
del 40% para la tablet ViewPad 10s y del 62% para la tablet Acer A100. En base a es-
tos resultados, podemos concluir que una diferencia del 10% o más en la reducción del
consumo de energía implica una diferencia significativa en cómo se utiliza la energía de
la batería. Al evaluar esta aplicación obtenemos un 56%, 34% y 62% de reducción en el
tiempo de ejecución en el I5000, el ViewPad 10s y el Acer A100, respectivamente.
116
0
70000
140000
210000
280000
350000
420000
490000
560000
630000
700000
(a) Samsung Galaxy I5500
Executions/1
0
OriginalModified
0
15000
30000
45000
60000
75000
90000
105000
120000
135000
150000
165000
(b) ViewPad 10s
Executions/1
0
OriginalModified
0
40000
80000
120000
160000
200000
240000
280000
320000
360000
400000
440000
(c) Acer A100
Executions/1
0
OriginalModified
Figura 6.5: MMULT (Dispositivos Móviles)
6.3.3. Knapsack Problem (KP)
Para completar el análisis de los experimentos presentamos los resultados de la última
aplicación refactorizada, Knapsack Problem. En esta aplicación redujimos la cantidad de
objetos en la memoria a la mitad. En la versión original se crea una instancia de la clase
OrcaRandom y una de la clase Knapsack, mientras que en la nueva versión de la aplica-
ción de prueba creamos solo una instancia de la clase Knapsack. Otro cambio significa-
tivo para esta aplicación de prueba fue la reducción de llamadas a métodos, eliminando
métodos que fueron llamados por un solo método.
Finalmente, se logran excelentes resultados con estas simples modificaciones. Los resul-
tados en el smartphone se presentan numéricamente en la Tabla 6.3 y gráficamente en
la Figura(a). Además, la Tabla 6.4 y la Figura 6.6 (b) muestran los resultados de la tablet
ViewPad 10s. Finalmente, la Tabla 6.5 y la Figura 6.6 (c) muestran los resultados para el
Acer A100. Estos resultados implican una reducción significativa del consumo de energía
(superior al 90%).
117
0
60000
120000
180000
240000
300000
360000
420000
480000
540000
600000
(a) Samsung Galaxy I5500
Executions/1
00
OriginalModified
0
20000
40000
60000
80000
100000
120000
140000
160000
180000
200000
220000
(b) ViewPad 10s
Executions/1
,000
OriginalModified
0
35000
70000
105000
140000
175000
210000
245000
280000
315000
350000
(c) Acer A100
Executions/1
,000
OriginalModified
Figura 6.6: Knapsack (Dispositivos Móviles)
6.3.4. Aplicaciones Multi-core
En esta Subsección, analizamos el impacto de la aplicación de refactorizaciones en apli-
caciones multi-core. Usamos las mismas aplicaciones que evaluamos antes de evaluar la
variación entre el uso de un solo núcleo y el uso de todos los núcleos. Como podemos
ver en la Figura 6.7 y en la Tabla 6.6, al usar toda la capacidad de la CPU, el número de
ejecuciones disminuyó tanto para la aplicación original como para larefactorizada, pe-
ro la reducción de consumo de energía fue similar en comparación con el caso en el que
utilizamos solo un núcleo. Esto significa que las refactorizaciones tienen el mismo impac-
to en el resultado final, independientemente de la cantidad de núcleos. La disminución
en el número de ejecuciones es una consecuencia del costo de ejecutar una aplicación
de múltiples subprocesos porque la creación y ejecución de subprocesos toman tiempo e
introducen latencia en el procesamiento del código.
6.3.5. Resumen
Después de obtener los primeros resultados (impacto de los micro-benchmarks indivi-
duales en los dispositivos móviles, Sección 6.1) realizamos más estudios de casos en
118
0
40000
80000
120000
160000
200000
240000
280000
320000
360000
400000
440000
480000
520000
Mmult
Executions/1
0
OriginalOriginal MultiCore
ModifiedModified MultiCore
(a) MMULT
0
40000
80000
120000
160000
200000
240000
280000
320000
360000
400000
440000
480000
FFT
Executions/1
00
OriginalOriginal MultiCore
ModifiedModified MultiCore
(b) FFT
0
35000
70000
105000
140000
175000
210000
245000
280000
315000
350000
385000
420000
Knapsack
Executions/1
,000
OriginalOriginal MultiCore
ModifiedModified MultiCore
(c) Knapsack
Figura 6.7: Multi-core evaluation (Dispositivo Movil)
119
Aplicación Original vs refactorizadaIncremento en el número de ejecuciones
At 0.01? At 0.05?
FFT
Smartphone " "
ViewPad 10s tablet " "
Acer A100 tablet $ "
Multi-core $ "
MMULT
Smartphone " "
ViewPad 10s tablet " "
Acer A100 tablet " "
Multi-core " "
KP
Smartphone " "
ViewPad 10s tablet " "
Acer A100 tablet $ "
Multi-core $ "
Cuadro 6.7: Test de significancia estadística: Variación en número de ejecuciones
los que se midieron los impactos de las refactorizaciones en tres aplicaciones científi-
cas reales: FFT, MMULT y Knapsack Problem. En estas aplicaciones, los resultados para
diferentes dispositivos fueron similares. Esto significa que incluso en los casos en los que
hubo algunas variaciones en el uso de energía, la aplicación de la refactorización pro-
puesta reduce el consumo de energía. Estas variaciones son causadas por la diferencia
en la capacidad de RAM de los dispositivos, los smartphones utilizados en los experi-
mentos tienen menos capacidad de RAM que las tablets. Como consecuencia, el GC de
Android se activa en intervalos de tiempo más cortos en smartphones que en tablets, lo
que consume más energía.
Para validar estos resultados nosotros utilizamos el test Mann-Whitney U. Para cada tri-
pla T =< d, a,v,>, donde v ∈ {Smartphone,ViewPad10s, AcerA100, AcerMulti − Core},
a ∈ {FFT, MMult,KP} y v ∈ {original,re f actored}, una lista de número de ejecuciones.
Estudiamos la fuente de las reducciones de energía ejecutando pruebas estadísticas para
comparar, dado dos posibles triples T1 =< d, a,′ original′ > y T2 =< d, a,′ re f actored′ >, si
hay diferencias significativas estadísticamente en las medianas del número de ejecucio-
nes antes y después de aplicar refactorizaciones.
Como resultado, la Tabla 6.10 muestra los resultados de la prueba en los niveles de sig-
nificancia de 0.01 y 0.05. Observamos que los códigos refactorizados (T2) tienden a eje-
120
cutarse más veces que los códigos originales (T1). De la Tabla anterior se confirma que
cada aplicación refactorizada puede ejecutarse más veces que la misma aplicación sin
refactorizaciones, particularmente en el nivel de significancia 0.05.
6.4. Resultados de Micro-benchmarks (Servidores)
La Tabla 5 muestra el consumo promedio de energía (en jouless) de cada versión demicro-benchmark. Como explicamos en el Capítulo 5, para cuantificar la reducción deluso de energía por micro-benchmark utilizamos la siguiente fórmula:
EnergyUsageReduction= [∑ Joules(Executioni)− ∑ Joules(ImprovedExecutioni)
∑ Joules(Executioni)]/nºo f iterations ∗ 100
Agregamos los resultados de los experimentos realizados en dispositivos móviles como
una columna adicional para compararlos con los resultados obtenidos en servidores. Po-
demos observar que nuestro resultado no es independiente de la plataforma, la tendencia
se mantiene a lo largo de los experimentos. En otras palabras, si una acción reduce el con-
sumo de energía en los dispositivos móviles también reduce el consumo de energía en los
servidores. Los párrafos siguientes discuten los resultados de manera abreviada porque
las causas de estos resultados y el bytecode generado son similares a los de las versiones
móviles.
Los resultados muestran que el uso del método provisto por Java para copiar arreglos
reduce el consumo de energía en un 37.9%. Estos resultados están en línea con estudios
previos sobre la optimización de Java Zhang et al. [2002], donde el uso de la función
System.arraycopy en lugar de la copia de arreglo manual para todo el subsistema de flujo
de entrada salida de Java daba como resultado un aumento del rendimiento en términos
de tiempo. Vale la pena mencionar que es uno de los cuatro grupos en los que más di-
fieren los valores obtenidos en dispositivos móviles y servidores. Esto significa que, no
obstante, nuestras refactorizaciones propuestas tienen un impacto diferente en hardware
diferente, reducen el consumo de energía en diversos entornos.
A continuación, nuestra próxima afirmación muestra que la creación de objetos produ-
ce más consumo de energía que la reutilización de objetos. Analizamos el análisis para
reutilizar estructuras de datos lineales, como listas y vectores, que no solo son útiles per
se sino que también se explotan en la práctica para implementar muchas estructuras de
datos y objetos personalizados. De esta forma, se obtuvo una reducción de energía del
43.2%, la mitad de la obtenida en dispositivos móviles.
La obtención directa de un valor de un atributo de una clase de manera frecuente y no a
través de un getter o método auxiliar, arroja una mejora del 81,4%, como se muestra en la
Tabla 6.8. Además, la Tabla 6.8 muestra que el uso de la clase StringBuilder directamente
121
Micro-benchmark Version Consumo (J) Reducción
en consumo
de energía
(%)
Resultado en
dispositivos
móviles (%)
Copia de arreglosCopia manual 102.8
System.arrayCopy 63.8 37.9 17
Creación de ObjetosCreación de objetosOn-demand
813.1
Reuso de Objetos 461.6 43.2 89
Acceso a atributos de unobjeto
Uso de getter 9,190.0
Acceso directo 1,700.8 81.4 87
Manejo de StringsConcatenación deString (+)
4,456.1
StringBuilder 271.7 93.9 99
Manejo de excepcionesUso de excepciones 14,108.6
No uso de excepciones 28.1 99.8 98
Uso de tipos de datosprimitivos
Clases 3,082.3
Uso de tipos de datosprimitivos
2,356.2 23.5 2
Recorrido de matricesPor columna 53,776.8
Por fila 102.6 99.8 53
Operaciones aritméticas
Adición double 5,152.5
Adición de float 5,089.3 1.2 37
Adición de long 3,643.5 29.2 47
Adición int 838.8 83.7 65
Cuadro 6.8: Resultados de Micro-benchmarks (Server)
122
en lugar del operador "+" genera una mejora del 93.9% (se usaron 1,000 concatenaciones
de strings). En la Subsección 4.1.5 analizamos el uso de la excepción para manejar erro-
res; sin embargo, afirmamos que no es un recurso valioso cuando buscamos reducir el
consumo de energía. Como era de esperar, los programadores pueden ahorrar energía
significativamente al no usar excepciones. La Tabla 6.8 muestra una mejora del 99.8% en
el consumo de energía.
En oposición al grupo de copia de arreglos, el uso de tipos de datos primitivos reduce el
consumo de energía en los servidores más que en los dispositivos móviles. En realidad, el
uso de tipos de datos primitivos como int, float y boolean permite un ahorro de energía de
hasta el 23.5% en servidores mientras que ahorra solo un 2% de energía en dispositivos
móviles. Por otra parte, los resultados muestran una reducción de energía de mejora del
99.8% recorriendo las matrices por filas en lugar de hacerlo por columnas. Finalmente, el
uso de los tipos de datos float, long e int es 1.2%, 29.2% y 83.7% más eficiente que el uso
de datos double respectivamente. Como resultado, usar el tipo de datos más específico es
una buena práctica para reducir el consumo de energía en cualquier dispositivo.
Como conclusión, podemos afirmar que las versiones de código amigables con la energía
para servidores son similares a las obtenidas para dispositivos móviles. Estos experimen-
tos nos permiten extender las pruebas a las aplicaciones de los servidores y afirmar que
los resultados son independientes del hardware.
6.5. Resultados de aplicaciones en servidores
Luego utilizamos los resultados previos para refactorizar las siete aplicaciones científi-
cas reales descritas en el Capítulo 4. Tomamos implementaciones del proyecto Ibis/Satin
(FFT, MMULT, KP, NQ), de la biblioteca Weka (Naive Bayes - Bayes) y el sitio GitHub
(GD, SA). De esta manera, medimos el impacto de la energía de los micro-benchmarks
en las áreas representativos. Una vez más, evaluamos los códigos originales, contra los
códigos refactorizados que utilizan las versiones más eficientes de micro-benchmarks.
La Tabla 6.9 y la Figura 6.8 muestran el consumo de energía y el tiempo de ejecución
resultantes, donde las reducciones se miden en%. Aunque los valores absolutos en la
Tabla 6.8 no son comparables con los valores absolutos obtenidos para dispositivos mó-
viles porque los primeros no son valores de ejecuciones individuales, los porcentajes son
comparables. Todos los resultados demostraron ser estadísticamente significativos con
un nivel de confianza de 0.01, según la prueba de two-tailed Wilcoxon para datos. En es-
te caso, se crean cuatro muestras por consumo de aplicaciones (en joules) para alimentar
dos pruebas separadas, es decir, muestras originales de un thread versus muestras refac-
torizadas de un solo thread y muestras originales de múltiples threads versus muestras
refactorizadas de hilos threads.
123
Aplicación VersionoConsumo (J) Reducción de energía (%) Tiempo de ejecución (s) Reducción de tiempo (%)
Single-thread
Multi-thread
Single-thread
Multi-thread
Single-thread
Multi-thread
Single-thread
Multi-thread
FFTOriginal 1784.76 947.57 27.9 8.1
Refactored 1714.99 813.14 3.90 14.19 26.4 7 5.37 13.58
MMULTOriginal 34315.15 22692.00 496.2 183
Refactored 13123.99 8261.35 61.75 63.59 185.7 66 62.57 64.45
KPOriginal 5181.22 4320.79 71.3 36
Refactored 104.94 103.41 97.97 97.61 1.5 1 97.89 97.22
NQOriginal 55753.39 34394.70 854 300
Refactored 40315.14 22374.64 27.69 34.95 605 189.5 29.15 36.83
SAOriginal 40813.78 61832.88 613.6 680.7
Refactored 906.92 508.52 97.77 99.18 13.1 4.3 97.86 99.36
GDOriginal 6361.87 3630.05 94 29.1
Refactored 3131.95 1920.946 50.76 47.08 44.8 15.5 52.34 46.73
BayesOriginal 14566.14 11599.18 231.2 118.2
Refactored 11733.39 10415.26 19.44 10.20 173.7 119.6 24.87 -1.18
Cuadro 6.9: Resultados de aplicaciones de prueba en servidores
124
Figura 6.8: Consumo para single-thread (izquierda) y multi-thread (derecha). los valores tienenuna escala de log10
Además, ejecutamos las aplicaciones en modo de una solo thread y también en modo de
múltiples threads explotando la cantidad de núcleos de la computadora host (es decir, 4
núcleos). El objetivo de esto es cuantificar y comparar las ganancias globales de ejecutar
simultáneamente varias instancias del mismo código de tarea, un conocido modelo de
paralelización utilizado en clusters HPC. Para lograr este objetivo, cada aplicación se
dividió en varias iteraciones que luego se asignaron a los diferentes threads en la misma
aplicación de múltiples threads.
Los párrafos siguientes detallan los resultados obtenidos durante los experimentos, pres-
tando especial atención a las aplicaciones que se integran para evaluar las capacidades
del servidor y se refactorizaron porque esto no se discutió anteriormente.
6.5.1. Fast Fourier Transformation (FFT)
Obtuvimos nuevamente una mejora favorable modificando algunos objetos y disminu-
yendo la precisión de los atributos. La Tabla 6.9 muestra que las reducciones de energía
fueron 3.90% (un solo thread) y 14.19% (multi-thread). Como mencionamos en la Sub-
sección 6.3.1, la refactorización principal en esta aplicación fue la refactorización de la
clase Complex que en la versión original era una clase inmutable. Con esto se logró que la
refactorización de la aplicación consuma mucha menos memoria, entonces, como los dis-
positivos móviles tienen menos RAM que los servidores, es coherente que la aplicación
refactorizada produce una gran mayor en los dispositivos móviles.
125
6.5.2. Matrix Multiplication (MMULT)
Presentamos los resultados obtenidos después de las ejecuciones en la Tabla 6.9 y gráfica-
mente en la Figura 6.8. Como resultado, los porcentajes de reducción en el uso de energía
obtenidos son del 61.75% para la versión de único thread y del 63.59% para la versión de
multi-thread. Esta aplicación tiene resultados similares a los obtenidos para dispositivos
móviles. Si bien la refactorización de esta aplicación se basa en el mismo principio que
la aplicación anterior, como explicamos en la Subsección6.3.2, la refactorización tiene im-
pacto solo en el momento en que se lanza la aplicación, lo que genera un impacto similar
en dispositivos con diferentes capacidades.
6.5.3. Knapsack (KP)
En este caso, se lograron excelentes resultados (Tabla 6.9). Para la versión de un solo th-
read se logró una reducción en el uso de energía de 97.97%, mientras que para el multi-
thread la reducción fue similar, es decir, del 97.61%. Además, la Figura 6.8 también re-
presenta estos resultados. Esta aplicación abarca diferentes grupos de micro-benchmarks
que se detallaron en la Subsección 6.3.3. No hemos escapado a nuestro conocimiento de
que las refactorizaciones ejecutadas tienen un impacto similar en los dispositivos móviles
que en los servidores.
6.5.4. N-Queens problem (NQ)
Como se menciona en la Subección 4.2.4, esta aplicación es algorítmicamente bastante
simple. Solo hay una clase que implementa el algoritmo en sí mismo. Por lo tanto, la
refactorización principal para este caso particular fue cambiar los tipos de datos no pri-
mitivos y evitar la creación de objetos en casos muy específicos.
Esos cambios menores conducen a una reducción del consumo energético del 27.69% y
34.95% para las versiones de único thread y multi-thread, respectivamente. Estos resul-
tados se muestran en la Tabla 6.9, así como en la Figura 6.8.
6.5.5. Sequence alignment (SA)
La Tabla 6.9 muestra que ha habido una reducción sustancial en el consumo de energía.
Estos resultados se pueden ver gráficamente en la Figura 6.8 también. Las ganancias son
considerablemente grandes, es decir, 97.77% para la versión de la aplicación de un solo
thread. La mejora fue estable en la versión de múltiples threads obteniendo un resultado
muy similar, un 99.18% de ahorro de energía.
126
En la implementación hay una clase llamada Matrix, que representa la matriz de pun-
tuación que se utiliza en el algoritmo de Smith-Waterman. Esta matriz estaba compuesta
principalmente por una matriz bidimensional de Float. Por lo tanto, la refactorización
más importante en este caso fue modificar los tipos de datos no primitivos para su tipo
de datos primitivo correspondiente. También hubo modificaciones en la clase SmithWa-
termanGotoh, que gestiona todos los pasos del algoritmo, para evitar nuevas creaciones
de objetos e invocaciones de métodos también. Finalmente, vale la pena señalar que da-
do que la clase Matrix se invoca con frecuencia durante la ejecución, el impacto en el
consumo final es grande, aunque las modificaciones fueron bastante simples.
Se puede observar en la Tabla que la versión original multi-thread de SA en realidad
consumió mucha más energía que la versión de un solo hilo original. Específicamente, el
tiempo que tomó procesar los mismos datos usando un núcleo físico fue menor que ha-
cerlo usando todos los núcleos, lo cual es al principio contrario a la intuición. Después de
leer detenidamente el código de la aplicación original, descubrimos que la distribución
a ciegas del trabajo para varios subprocesos condujo a altos niveles de contención de la
memoria. Sin embargo, nuestro objetivo era tomar los códigos de la aplicación "tal como
están" antes de la refactorización. De hecho, las refactorizaciones aplicadas, es decir, evi-
tar el uso de clases cuando existen tipos de datos primitivos y la reducción de creaciones
de objetos, ayudaron a disminuir significativamente el uso de la memoria en la versión
refactorizada de un solo thread. Esto reduce la contención de la memoria en la versión
multi-thread refactorizada.
6.5.6. Gradient Descent (GA)
Para esta aplicación hubo varios cambios para mejorar la eficiencia energética. Básica-
mente, como se menciona en la Subsección 4.2.6, la implementación se basa en un con-
junto de matrices. La versión original de esta matriz se implementó utilizando una co-
lección con tipos de datos no primitivos, es decir, una lista de valores Double (instancia
de List). Además, para acceder a cada uno de los elementos era necesario usar métodos
de acceso. Por lo tanto, la refactorización aplicada en este caso fue reemplazar las clases
contenedoras por matrices de tipos de datos primitivos.
Una lista se puede ver como un caso particular de contenedor para una matriz, de la
misma forma que Double es un contenedor para un tipo de datos primitivo double. Por
lo tanto, cuando se cambia una lista completa para una única matriz, se aplican simultá-
neamente muchos refactorings. En primer lugar, habrá menos objetos, ya que la lista en
sí misma es un objeto que necesita memoria para ser asignada. Además, para obtener un
elemento en una posición particular, es necesario utilizar los métodos de acceso propor-
cionados por la lista. Si, en cambio, se utiliza una matriz, el elemento se puede obtener
127
accediendo directamente a esa posición sin involucrar una llamada a un método. Como
resultado, habrá menos llamadas a los métodos también. Finalmente, el uso de una ma-
triz en lugar de una lista permite a los programadores utilizar tipos de datos primitivos
que consumen mucha menos energía que los tipos de datos no primitivos. También vale
la pena señalar que no siempre es posible utilizar matrices en lugar de listas, sino prin-
cipalmente cuando se conoce la cantidad de elementos que se almacenarán a priori para
evitar los costos de tiempo asociados al redimensionamiento de matrices.
Los resultados mostrados en la Tabla 6.9 así como en la Figura 6.8 muestran que las re-
factorizaciones mencionadas tuvieron una gran influencia en el consumo final. Para la
versión de un solo thread la versión refactorizada redujo el uso de energía en un 50.76%,
mientras que la versión de múltiples threads arrojó un 47.08%.
6.5.7. Bayes Network Classifier (Bayes)
Las refactorizaciones también influyeron en esta aplicación. La Tabla 6.9 muestra una
reducción del 19,44% para la versión de un solo thread y del 10,20% para la versión de
múltiples threads. La Figura 6.8 también muestra estas mejoras gráficamente.
Para la implementación, la aplicación mapea cada entrada o punto de datos del conjunto
de datos en una clase llamada Instance. Cada una de estas instancias se procesa para
capacitar al clasificador de red Bayes y obtener el modelo. La información almacenada
en esta clase es dinámica y puede variar según los modelos. El conjunto completo de
instancias, que representa todo el conjunto de datos, se mantiene en otra clase llamada
Instances. Es decir, Instances es una colección de objetos de Instance, que proporciona los
métodos para obtener o poner información en ella y está compuesta principalmente por
una lista. Además, es posible conocer el tamaño del conjunto de datos a priori. Por lo
tanto, la refactorización propuesta para este caso fue muy similar a la mencionada en
la Subsección 6.5.6, es decir, eliminando la Lista y usando una matriz en su lugar. Dado
que esta clase se utiliza de forma recurrente en la aplicación, el impacto que tuvo esta
refactorización en el consumo final fue significativo.
6.5.8. Resumen
Nuestros resultados indican que las refactorizaciones y guías propuestas generaron re-
sultados útiles después de refactorizar/desarrollar la aplicación Java, ya sea móvil o no.
De forma similar a los dispositivos móviles, realizamos pruebas estadísticas para eva-
luar la validez de nuestros experimentos. Los párrafos siguientes explican en detalle la
información tomada en cuenta y la ejecución de prueba.
128
Aplicación Original vs refactorizadaVariación de Energía Decremento de tiempo de ejecución
At 0.01? At 0.05? At 0.01? At 0.05?
FFTSingle-thread " " " "
Multi-thread $ $ " "
MMULTSingle-thread " " " "
Multi-thread $ " " "
KPSingle-thread $ $ " "
Multi-thread " " " "
NQSingle-thread " " " "
Multi-thread " " " "
SASingle-thread " " " "
Multi-thread " " " "
GDSingle-thread " " " "
Multi-thread $ $ " "
BayesSingle-thread " " " "
Multi-thread " " " "
Cuadro 6.10: Significancia estadística de test en aplicaciones reales en servidores
129
Como se explicó anteriormente, la energía consumida por una versión de la aplicación
(original o refactorizada) que emplea o no múltiples threads se calcula en función de dos
factores: potencia activa (en Watts) y tiempo transcurrido en segundos. Para cada triple
T =< a,v, th>, donde a∈ {FFT, MMult,KP, NQ,SA, GD, Bayes}, v∈ {original,re f actored}
y th ∈ {single − thread,multi − thread}, se obtiene una sola lista con las muestras de po-
tencia activas después de ejecutar i iteraciones, más i tiempos individuales transcurridos.
Estudiamos la fuente de las reducciones de energía ejecutando pruebas estadísticas para
comparar, dado dos triples T1 =< a,′ original′ , th > y T2 =< a,′ re f actored′ , th >, si hay di-
ferencias estadísticamente significativas en la potencia activa y los tiempos transcurridos.
Para determinar la significancia estadística en potencia activa, tomamos las listas de
muestras de potencia activa T1 y T2 y dado que ambas listas pueden diferir en longi-
tud -por las diferencias en los tiempos transcurridos- ejecutamos el test two-tailed Mann-
Whitney-Wilcoxon para datos no apareados. Para determinar la importancia en el tiempo
transcurrido, y dado que ambas listas tienen la misma longitud (i muestras) y las mues-
tras difieren entre sí en que se aplica un tratamiento (refactorización), usamos la prueba
de two-tailed Wilcoxon para datos emparejados. La Tabla 6.10 muestra los resultados de
la prueba en los niveles de significancia 0.01 y 0.05. Como observamos que los códigos
reajustados (T2) tendían a exigir más potencia activa pero menos tiempo para ejecutar
que los códigos originales (T1), como se muestra en la Tabla, probamos la significancia
estadística del incremento de potencia activa y decremento del tiempo de ejecución de
los códigos refactorizados sobre los códigos originales.
De la tabla anterior se confirma que, considerando los experimentos que usan códigos de
un solo thread, las versiones refactorizadas demandaron más poder activo que las ver-
siones originales (2-4% en promedio). La excepción a esta regla es KP, cuya versión refac-
torizada tenía 3.72% menos de potencia activa que la versión original en promedio. Sin
embargo, para códigos multi-thread, esta tendencia general no es válida y, de hecho, las
versiones refactorizadas introdujeron reducciones promedio de potencia activa en com-
paración con los códigos originales en cuatro casos, es decir, 0,70% (FFT), 13,83% (KP),
23,18% (SA ) y 0,65% (GD). Vale la pena señalar que estas reducciones de potencia activa
introducidas por códigos refactorizados son significativas en los niveles de confianza 0.01
y 0.05. En conclusión, no hay un ganador claro en términos de potencia activa, y el con-
sumo puede depender de la naturaleza algorítmica de las aplicaciones. Otra observación
es que, como se esperaba, los códigos multi-thread exigieron mucha más potencia activa
([90.83-125.17] Watts en promedio) que los códigos de un solo thread ([63.36-72.66] Watts
en promedio).
La Tabla muestra que todas las pruebas son significativas con respecto al tiempo de ejecu-
ción y confirman que los códigos refactorizados se ejecutan más rápido que los códigos
originales, excepto para la versión de múltiples threads de Bayes en la que la versión
130
refactorizada es 1.18% más lenta que la versión original. Aceleraciones obtenidas1 (es de-
cir, la versión original sobre el tiempo de la versión refactorizada) varió en [1.05-47.53]
para las ejecuciones de único thread y [1.15-158.30] para las ejecuciones de múltiples th-
reads. Por lo tanto, se puede ver el efecto multiplicativo y beneficioso de utilizar muchos
threads para ejecutar código refactorizado sensible a la energía y, por lo tanto, muchos
núcleos físicos en reducciones de tiempo en comparación con el uso de un thread/nú-
cleo. En general, como se muestra en la Tabla 6.9, dichas reducciones de tiempo dieron
como resultado ahorros de Joules promedio por iteración de alrededor de [69-39900] (un
thread) y [134-61300] (multi-thread).
6.6. Aplicaciones de usuario final en dispositivos móviles
Usando una herramienta externa llamada Robotium para definir y ejecutar diferentes ca-
sos de prueba obtuvimos resultados preliminares para las aplicaciones móviles del usua-
rio final (GUI-oriented). Estos resultados nos permiten evaluar el esfuerzo y el compro-
miso de aplicar refactorizaciones en aplicaciones reales de usuarios finales. La Tabla 6.11
muestra el consumo medido por el hardware Power Monitor para cada aplicación.
Para analizar los resultados, es importante mencionar que el consumo total de energía se
calcula con la siguiente fórmula: consumption = time ∗ power, donde time representa el
tiempo de ejecución del caso de prueba y power representa el promedio de Watts mues-
treados por unidad de tiempo durante el ejecución. Vale la pena señalar que se consideró
una frecuencia de muestreo de 5 kHz. Teniendo en cuenta estos valores, los desarrolla-
dores deben saber que una aplicación puede reducir su consumo de energía al reducir su
consumo de energía por unidad de tiempo.
Ahora, analizando los resultados que respaldan las preguntas de investigación presen-
tadas en esta tesis. En primer lugar, para la versión eficiente de FiveStones, en la que se
eliminan los métodos de acceso, el consumo de energía se redujo en un 5,505%. En Sorter
este porcentaje fue menor, es decir, alrededor de., 1,02%. Una de las razones principales
de esta diferencia en los porcentajes entre las aplicaciones científicas orientadas a GUI y
no científicas es que la interfaz gráfica es un componente importante que consume gran-
des cantidades de energía Carroll and Heiser [2010]. En general, utilizar nuestras pautas
para reducir el uso de CPU y memoria es una buena alternativa para complementar otras
técnicas amigables con la energía para las aplicaciones del usuario final y particularmen-
te la gestión de pantallas y GUI Dong et al. [2009], Dong and Zhong [2011], mejorando la
reducción del consumo de energía en este tipo de aplicaciones.
1A speedup factor greater than 1 means execution time improvement
131
Aplicación Versión Power (Watts) Tiempo (s) Consumption (J) Desviación
estandar (%)
Reducción en
uso de energía
(%)
FiveStonesOriginal 1.375 26.246 36.108 3.005
Refactorizada 1.326 26.246 34.224 2.532 5.505
SorterOriginal 0.717 102.347 74.646 5.347
Refactorizada 0.709 104.111 73.832 3.055 1.102
Cuadro 6.11: Resultados de aplicaciones de usuario final en dispositivos móviles
132
6.7. Eficiencia energética vs. diseño OO
Después de analizar cuantitativamente la mejora en términos de consumo de energía
y performance, analizaremos el equilibrio entre la eficiencia energética y la calidad del
diseño OO debido a la refactorización. Con esto en mente, analizaremos uno por uno los
ocho grupos de micro-benchmark que presentamos antes.
Con respecto al uso de bibliotecas en lugar de desarrollar manualmente una funcionali-
dad específica, en Korson and McGregor [1990] se enfatiza la importancia de construir
sistemas de software a partir de partes reutilizables en lugar de desarrollar sistemas ma-
nualmente. La abstracción funciona de forma casi intuitiva para algunos dominios como
las bibliotecas matemáticas pero la idea se puede aplicar a cualquier dominio. Entonces,
el uso de bibliotecas no solo ahorra energía sino que también se ajusta a los principios del
paradigma OO, particularmente la reutilización.
En el paradigma OO, el término objeto está asociado a una instancia particular de una
clase que contiene propiedades y métodos necesarios para hacer que un determinado
tipo de datos sea útil. Además, los objetos tienen relaciones entre ellos. Como consecuen-
cia, reutilizar un objeto para evitar la creación de uno nuevo implica restablecer todos
sus atributos y relaciones y crear los correspondientes a la nueva instancia. Aunque la
reutilización de objetos no afecta el diseño OO de una aplicación, es propenso a errores y
tiene un alto costo de análisis de código por parte del desarrollador para evitar el cambio
o la pérdida de instancias de clases que la aplicación debería utilizar más adelante.
La encapsulamiente o el ocultamiento de información es uno de los conceptos principales
en la programación OO. Un objeto tiene que proporcionar a sus usuarios solo informa-
ción esencial para la manipulación, sin exponer detalles internos. Un objeto solo conoce
sus propiedades y las funcionalidades que otro objeto proporciona públicamente. Todo
lo demás está oculto internamente bajo la cubierta de otros objetos. No sabe sobre el
funcionamiento interno de otros objetos porque no necesita hacerlo. Como resultado, la
refactorización Acceso a un atributo de un objeto mejora el consumo de energía pero
afecta directamente uno de los principios del paradigma OO: encapsulamiente.
En la programación OO, se dice que un objeto es inmutable si su estado no se puede mo-
dificar después de haber sido creado (por ejemplo, cadenas). Este tipo de objetos ofrece
varias ventajas: son más simples de construir, probar y usar, siempre son seguros para
subprocesos, ayudan a evitar el acoplamiento temporal, su uso es libre de efectos secun-
darios, se evita el problema de la mutabilidad de identidad, tienen la atomicidad de la
falla, son mucho más fáciles de almacenar en caché y evitan las referencias NULL. Por
lo tanto, evitar objetos inmutables no afecta el diseño OO de una aplicación, pero podría
afectar algunas de estas ventajas que ofrecen los objetos inmutables. Entonces, evitar el
uso de objetos inmutables cuando muchas operaciones cambian su valor puede significar
133
un gran ahorro de energía sin afectar el diseño de la aplicación (cuando un String consiste
en la concatenación continua de substrings, por ejemplo).
Como mencionamos anteriormente, el manejo de excepciones es un mecanismo para ma-
nejar errores y no está limitado a la programación OO. Particularmente, cuando se pro-
duce una excepción dentro de un método Java, este último crea un objeto de excepción
que contiene información sobre el error (su tipo, el estado del programa cuando se pro-
dujo el error) y lo transfiere. En OO, las excepciones de programación se deben definir
con una jerarquía de herencia. Se utilizan separando el código de manejo de errores del
código normal y propagando errores en la pila de llamadas y agrupando y diferencian-
do los tipos de error. Como una clase es una definición de plantilla de los métodos y
variables en un tipo particular de objeto, se manejan los errores sin utilizar fuerzas de
mecanismo de excepción que incluyen responsabilidades para clases específicas, que no
sigue la herencia y la jerarquía presentada del paradigma de OO.
A diferencia de las clases contenedoras, los tipos de datos primitivos no son objetos. Esto
significa que usar tipos de datos primitivos no está contemplado en OO. En consecuencia,
nuestra refactorización propuesta -que sugiere que el uso de tipos de datos primitivos
consume menos energía que el uso de las clases contenedoras correspondientes- desde
un punto de vista conceptual, atenta contra la pureza del código OO. Finalmente, las dos
últimas refactorizaciones (recorrido de matriz y operaciones aritméticas) se refieren a la
forma de pasar por una estructura en la memoria y la precisión de los datos utilizados,
respectivamente, que no tienen ninguna relación con el diseño OO de una aplicación.
Resumiendo, solo 3 de las 8 refactorizaciones propuestas tienen un impacto negativo en
los principios de OO, lo que demuestra que considerar la eficiencia energética no siempre
va en detrimento de la explotación de las ventajas del paradigma de OO, como manteni-
miento, reutilización, software de alta calidad, etc.
6.8. Resumen
En resumen, las pruebas presentadas a lo largo de este capítulo muestran cuánto se puede
reducir el consumo de energía y, por lo tanto, indican que el impacto de refactorizaciones
simples puede ser significativo en el consumo de energía. Por lo tanto, concluimos que
las mejores prácticas o guía propuestas para el desarrollo de aplicaciones móviles son una
contribución importante a la comunidad de programación científica. Además, cuando se
integran dispositivos móviles en infraestructuras informáticas distribuidas, como Grids,
es esencial que los usuarios del dispositivo puedan continuar utilizando sus dispositi-
vos normalmente. Por lo tanto, si desarrollamos aplicaciones científicas que descarguen
la batería dentro de un período corto de tiempo, los usuarios serán reacios a ejecutarlas
134
nuevamente. Estos resultados son un paso hacia la reducción del consumo de energía en
estos escenarios. Además, hicimos un breve análisis sobre el impacto de estas refactoriza-
ciones en el diseño de OO. Finalmente, el próximo Capítulo detalla nuestras conclusiones
y trabajos futuros.
135
136
Capıtulo 7
Conclusiones y Trabajos Futuros
A lo largo de este trabajo de doctorado presentamos una hipótesis junto con un plan
y una metodología que nos permiten realizar experimentos interesantes y analizar sus
resultados. Como vimos anteriormente, obtuvimos resultados por encima de cualquier
expectativa. Luego, para finalizar este trabajo, presentaremos nuestras conclusiones y el
plan para futuras investigaciones.
7.1. Conclusiones
Después de desarrollar y analizar la prueba realizada durante este doctorado, podemos
concluir que se obtuvieron los resultados esperados. En esta investigación, hemos evalua-
do empíricamente el impacto energético de considerar versiones amigables con la ener-
gía de primitivas comunes (o micro-benchmarks) en códigos científicos basados en OO.
Particularmente, nos hemos centrado en Java y en núcleos de aplicaciones científicas re-
presentativas para demostrar las mejoras en el consumo de energía después de las de
refactorizaciones. Esto se aplica tanto a aplicaciones refactorizadas que explotan uno o
varios núcleos de CPU. Por lo tanto, nuestro estudio representa una contribución pa-
ra proporcionar a los investigadores pautas para desarrollar software eficiente en ener-
gía para funcionar en smartphone, tablets y servidores, que complementa los enfoques
energéticos ya propuestos a nivel de plataforma y hardware. Mientras que los grupos
de micro-benchmark se evaluaron solo en smartphones, las aplicaciones de prueba se
probaron en smartphones, tablets y servidores para garantizar una mayor generalidad.
Además, dos aplicaciones de usuario final fueron probadas en dispositivos móviles.
En el Capítulo 1 planteamos 5 preguntas para responder durante esta investigación de
doctorado; luego, las siguientes subsecciones se centran en responderlas.
137
7.1.1. Q1 ¿Pueden ser refactorizaciones simples útiles para ahorrar energía en
aplicaciones científicas con uso intensivo de recursos computacionales?
Para responder a esta primera pregunta, seleccionamos 8 grupos de micro-benchmarks
y dos o más versiones de cada uno para evaluar cuál de esas versiones es más eficiente
en términos de consumo de energía en dispositivos móviles. En esta línea, no solo tra-
tamos de cubrir prácticas comunes de desarrollo sino que también cubrimos diferentes
usos de CPU y RAM. Como resultado, cada grupo junto con su conclusión particular se
especifican en los párrafos siguientes:
Copia de arreglos: el uso de bibliotecas en lugar de programar manualmente la mis-
ma funcionalidad no solo disminuye el esfuerzo del desarrollador y la probabilidad
de cometer algún error, sino que también puede reducir significativamente el con-
sumo de energía. Sin embargo, la principal limitación de esta propuesta es que los
desarrolladores deben conocer las bibliotecas relevantes. Entonces, usar las biblio-
tecas proporciona varias ventajas: reduce el consumo de energía, reduce el tiempo
de ejecución y mejora el diseño mediante la reutilización.
Creación de objetos: aunque la creación de objetos es inevitable cuando se programa
con un diseño OO, esta investigación de doctorado muestra que una sección de
código que reutiliza un objeto existente puede consumir un 89% menos de energía
que una sección de código que crea un nuevo objeto. Esta práctica requiere un gran
conocimiento sobre el problema y su ejecución, pero tiene la ventaja de que no
afecta el diseño de OO.
Acceso a atributo de un objeto: esta es la primera práctica que rompe el diseño OO
de una aplicación porque es contraria al principio de encapsulamiento. Acceder di-
rectamente a un atributo puede ahorrar hasta el 87% de la energía, proporcionando
una ventaja interesante en términos de energía que el desarrollador debe evaluar al
tomar la decisión de romper los principios del paradigma.
Manejo de strings: las clases inmutables brindan varias ventajas, pero modificar
sus valores implica la creación de un nuevo objeto y, como consecuencia, un mayor
consumo de energía. Una vez más, los desarrolladores y arquitectos deben evaluar
el compromiso de garantizar estas ventajas en contra de ahorrar hasta un 99% de
energía.
Manejo de excepciones: el mecanismo para manejar los errores propuestos por el
lenguaje se adapta correctamente al paradigma OO pero genera llamadas a mé-
todos y creación de objetos que consumen energía. Entonces, esta es la segunda
práctica que presenta una relación de compromiso con los principios del paradig-
138
ma: los desarrolladores pueden ahorrar hasta el 98% de la jerarquía y la herencia
que renuncian a la energía.
Uso de tipos de datos primitivos: esta práctica no ahorra tanta energía como las
prácticas anteriores; sin embargo, es una práctica simple y no privada de tantas
ventajas como otras prácticas. El uso de tipos de datos primitivos en lugar de en-
voltorios puede ahorrar un 2% de energía.
Recorrido de matrices: esta práctica muestra que el uso eficiente de la memoria
puede ahorrar una cantidad importante de energía. En este caso, recorrer una ma-
triz por filas ahorra el 53% de la energía en comparación con recorrer una matriz
por columnas. Las fallas de memoria y la carga de memoria son operaciones que
requieren energía para llevarse a cabo. Como resultado, es importante que los desa-
rrolladores sepan cómo se administra la memoria internamente.
Operaciones aritméticas: el CPU tiene la capacidad de sumar números usando sus
diminutos transistores, que consumen energía. Por lo tanto, aunque se necesita más
precisión, se consume más energía. Al reducir la precisión de los datos numéricos,
una operación puede consumir hasta un 65% menos de energía. A pesar de esta
reducción significativa, los desarrolladores deben tener cuidado cuando reducen la
precisión, ya que puede ser crítico en algún tipo de aplicaciones.
Los resultados muestran que la respuesta a la primer pregunta es positiva. Hmos obteni-
do resultados más que significativos para dispositivos móviles.
7.1.2. Q2 ¿Cuál es el impacto que estas refactorizaciones generan en aplica-
ciones científicas reales?
Después de evaluar cada grupo por separado, elegimos 3 aplicaciones científicas reales
para refactorizar y medir el impacto de estas refactorizaciones en términos de consumo
de energía. En este paso evaluamos el impacto de aplicar la mayoría de las refactorizacio-
nes posibles en una aplicación. Con esto en mente, catalogamos numerosas aplicaciones
Satin con el objetivo de cubrir todos los grupos presentados anteriormente. Las 3 apli-
caciones seleccionadas son: FFT, MMULT y Knapsack problem. Además de cubrir los
grupos de micro-benchmarks, estas aplicaciones tienen otras ventajas, como ser el núcleo
de varias aplicaciones científicas y ser parte de aplicaciones comunes para el usuario final
(por ejemplo, reproductores de sonido).
Estas aplicaciones se probaron en 3 dispositivos móviles diferentes (un smartphone y
dos tablets), obteniendo resultados significativos ([35% -98%] de energía ahorrada). A lo
largo de esta fase, demostramos que, a pesar de la diferencia de hardware, refactorizar
aplicaciones genera un resultado positivo en cualquier dispositivo móvil.
139
Grupo de Micro-benchmarks Principio OO Impacto
Copia de arreglos Reuso a
Creación de objetos — —Acceso a atributos de un objeto Encapsulamiento
Manejo de Strings — —Manejo de excepciones Encapsulamiento/Jerarquia/Herencia
Uso de tipos de dato primitvos Paradigma OO
Recorrido de matrices — —Operaciones Aritméticas — —
Cuadro 7.1: Eficiencia energética vs. diseño OO
7.1.3. Q3 ¿Cuál es el impacto de estas refactorizaciones en el diseño orientado
a objetos y la calidad de la aplicación?
La Sección 6.7 inspecciona el impacto de mejorar la eficiencia energética en aplicaciones
Java. Aunque la Sección se centra en evaluar el impacto de aplicar las refactorizaciones
o seguir las directrices sobre el diseño, también evaluamos el impacto en otras caracte-
rísticas del software, como la precisión. Como conclusión, afirmamos que no siempre la
eficiencia energética deteriora el diseño de OO. De hecho, concluimos que solo tres de las
prácticas propuestas deterioran el diseño de OO (acceso a tributos de objeto, manejo de
excepciones y uso de tipos de datos primitivos), mientras que uno lo mejora (Copia de
arreglos) y cuatro no lo afectan (Creación de objetos, Manejos de Strings, Recorrido de
matrices y Operaciones aritméticas). La Tabla 7.1 resume el impacto de las refactorizacio-
nes en el diseño OO de la aplicación.
7.1.4. Q4 ¿Cómo impactan estas refactorizaciones en el consumo energético
en aplicaciones científicas en servidores?
Una vez que evaluamos completamente el impacto de nuestras prácticas en el consumo
de energía en dispositivos móviles, evaluamos los mismos grupos de micro-benchmarks
en un servidor. Como resultado, obtuvimos resultados relevantes, luego decidimos eva-
luar el impacto de las refactorizaciones en aplicaciones reales. De manera similar a lo
realizado para dispositivos móviles, probamos las tres aplicaciones seleccionadas previa-
mente y agregamos cuatro nuevas aplicaciones para cubrir un espectro más amplio de
aplicaciones comunes en los servidores. Las cuatro nuevas aplicaciones son: N-Queens,
Sequence Alignment, Gradient Descent y Bayes Network Classifier.
Durante los experimentos no solo obtuvimos un gran resultado en términos de consumo
de energía ([5.37% -97.98%]) sino que también obtuvimos un resultado interesante don-
de el total de energía consumida se redujo mientras el tiempo de ejecución aumentaba.
140
Este resultado difiere de los demás porque hasta la ejecución del clasificador de red Bayes
en su versión multi-core, el consumo de energía se redujo junto con el tiempo de ejecu-
ción. Esto significa que, aunque una forma de reducir el consumo de energía es reducir
el tiempo de ejecución y mantener el consumo por unidad de tiempo, existen algunas
operaciones que pueden afectar de manera diferente estas variables.
7.1.5. Q5 ¿Qué tan adecuadas son estas refactorizaciones para aplicaciones de
usuario final?
Finalmente, la última pregunta que propusimos para cubrir un mayor campo de aplica-
ción de nuestras refactorizaciones en el trabajo se refiere al impacto de nuestras prácticas
en las aplicaciones reales del usuario final. Para responder a esta pregunta, refactoriza-
mos dos aplicaciones reales: FiveStones y Sorter. El primero es un juego conocido en el
que el usuario puede jugar un juego contra la computadora, y el segundo es una aplica-
ción que simula los algoritmos de ordenamiento. Como consecuencia, ambas aplicaciones
utilizan intensamente la CPU, lo que nos ayuda a contrarrestar el efecto negativo en el
consumo de energía de la pantalla (la pantalla es el recurso que consume más energía
cuando está encendida).
Por lo tanto, medimos el consumo de energía de la aplicación original y refactorizada.
Como esperábamos, en este contexto las mejoras fueron menores ([1.102% -5.505%]).
Aunque estos resultados no son tan significativos como los resultados de las aplicacio-
nes científicas, indican que los desarrolladores pueden reducir el consumo de energía en
aplicaciones de usuario final utilizando nuestras prácticas.
7.1.6. Resumen
En resumen, estas experiencias muestran un menor uso de energía y, por lo tanto, indi-
can que el impacto de refactorizaciones simples puede ser significativo en el consumo de
energía. Además, concluimos que las prácticas propuestas o directrices para el desarro-
llo de aplicaciones móviles son una contribución importante a la comunidad de progra-
mación científica. La razón principal es que es esencial que los usuarios de dispositivos
puedan continuar usando sus dispositivos normalmente cuando integran dispositivos
móviles en infraestructuras informáticas distribuidas, como Grids. Por lo tanto, si desa-
rrollamos aplicaciones científicas que agotan la batería en un corto período de tiempo,
los usuarios serán reacios a ejecutarlas nuevamente. Este trabajo es un paso hacia la re-
ducción del consumo de energía en estos escenarios.
Finalmente, este trabajo se extendió a entornos de servidor como en Perez-Castillo and
Piattini [2014]. En esta línea, la energía se midió a través de un nuevo hardware espe-
141
cializado llamado PowerMeter1. Los resultados muestran que nuestras directrices gene-
ran un alto porcentaje de reducción del consumo de energía en entornos de escritorio
(hasta un 98% en algunos micro-benchmarks). Esto significa que podemos seguir estas
buenas prácticas no solo para ahorrar energía en dispositivos móviles sino también para
crear Green software para computadoras personales y servidores. Además, es importan-
te mencionar que la reducción del consumo de energía en todos los nodos de una red
móvil, es decir, nodos móviles y fijos, es un problema central.
7.2. Trabajos Futuros
Este trabajo puede extenderse en varias direcciones. En primer lugar, analizaremos la po-
sibilidad de utilizar otros grupos de micro-benchmarks para evaluar las capacidades de
los dispositivos móviles y evaluar su consumo de energía tanto en dispositivos móvi-
les como en servidores. Por ejemplo, algunos grupos de micro-benchmark podrían estar
relacionados con el manejo de estructuras de datos lineales (Vector, LinkedList) en memo-
ria, o diferentes representaciones de matrices multidimensionales Carvalho Junior et al.
[2013]. También planeamos extender nuestro estudio más allá de las aplicaciones cien-
tíficas, ya que claramente muchos primitivos son lo suficientemente generales. La edad
de oro de los data centers Basmadjian et al. [2015] ha causado una proliferación de nue-
vos tipos de aplicaciones alojadas en la nube, incluidos microservicios, aplicaciones SaaS
(Software as a Service) y Restful Web Services Pautasso et al. [2014]. Incluso cuando los
requisitos de recursos para ejecutar estas aplicaciones pueden ser mucho más bajos en
comparación con las aplicaciones científicas, los primeros están sujetos a cargas mucho
más elevadas, ya que se accede simultáneamente desde miles de clientes web. Por lo tan-
to, pequeñas mejoras de energía podrían generar un gran impacto. Curiosamente, Java
también es popular en el desarrollo de back-end. Además, podrían considerarse nuevas
operaciones comunes en Java y en el desarrollo de servicios web. Por ejemplo, se podrían
evaluar diferentes estrategias para especificar, formatear y representar los parámetros y
valores intercambiados entre los servicios y las aplicaciones del cliente y su impacto en el
consumo de energía.
En segundo lugar, estamos explotando nuevas ideas en el contexto de la programación
OO. Rodriguez et al. [2016b] estudia el trade-off entre producir buenos diseños de clase
en términos de OO versus los costos de energía inherentes. Particularmente, este último
explora hasta qué punto es aconsejable introducir refactorizaciones de código orientadas
a eliminar los llamados Code Smells -como God Classes, Brain Classes y Feature Envy-
para aumentar la extensibilidad y mantenibilidad de la aplicación sin comprometer la
energía.
1http://power-meter.com.ar/products.html
142
Por lo tanto, estudiaremos cómo modificar automáticamente una aplicación existente pa-
ra utilizar la versión de eficiencia energética de los micro-benchmarks antes de la com-
pilación, o al menos ofrecer a los desarrolladores una herramienta para detectar auto-
máticamente puntos de mejora potenciales en el código. Para algunos micro-benchmarks
esto es fácil de hacer (por ejemplo, el acceso a atributo de un objeto) pero para otros
(por ejemplo, la reutilización de objetos) la modificación automática o el reconocimiento
es muy desafiante. Como corolario, la herramienta debería permitir a los desarrollado-
res controlar cómo se aplica la refactorización agresivamente para equilibrar la eficiencia
energética y la pureza de OO, dependiendo de los requisitos de la aplicación. Claramen-
te, contar con dicho soporte de herramientas aumentaría el valor práctico de nuestros
resultados.
Además, evaluaremos el impacto del uso de la GPU para ejecutar estas aplicaciones cien-
tíficas. Aunque esta no es una práctica común en la actualidad porque una GPU es un
circuito electrónico especializado diseñado para generar imágenes, existen técnicas que
permiten a los desarrolladores aumentar el rendimiento de sus aplicaciones a costa de
escribir códigos complejos para usar las capacidades de la GPU. Por ejemplo, Yang et al.
[2012] presenta RenderScript, un lenguaje de programación utilizado en Android para
explotar la GPU. Del mismo modo, Guihot [2012] propone un marco para escribir pro-
gramas que se ejecutan en plataformas heterogéneas que constan de CPU, GPU, procesa-
dores de señal digital (DSP), FPGA y otros tipos de procesadores. En esta área, Yang et al.
[2012] muestra un traductor de OpenCL a RenderScript. A pesar de que RenderScript
pretende paralelizar trabajos en todos los procesadores disponibles en un dispositivo,
RenderScript es especialmente útil para aplicaciones que realizan procesamiento de imá-
genes, fotografía computacional o visión artificial. Por lo tanto, se necesita más investi-
gación para adaptar dichos soportes para permitir a los usuarios desarrollar aplicaciones
científicas y de uso general.
Finalmente, probaremos el impacto de las refactorizaciones propuestas en dispositivos
móviles usando aplicaciones nativas de Android, que también es un tema candente en
el área de Cheng-Min et al. [2011], Sangchul and Wook [2010]. Los resultados obtenidos
usando un nuevo lenguaje son valiosos para tomar una decisión al momento de desarro-
llar una nueva aplicación.
7.3. Publicaciones
Durante este doctorado produjimos resultados que se han publicado en varias revistas y
conferencias nacionales e internacionales. Vale la pena señalar que no solo se publicaron
artículos relacionados con el tema principal de esta tesis. Durante los últimos años se
tomaron varios cursos y se escribieron algunos artículos interesantes basados en ellos.
143
Estas publicaciones se enumeran a continuación separadas en revistas y conferencias.
Para los artículos que aún están en prensa, la fecha reportada es la fecha de notificación
de aceptación.
7.3.1. Revista
M. Hirsch, A. Rodriguez, J. M. Rodriguez, C. Mateos, A. Zunino: "Spotting and
Removing WSDL Anti-pattern Root Causes in Code-first Web Services Using NLP
Techniques: A Thorough Validation of Impact on Service Discoverability". Compu-
ter Standards \& Interfaces. In press. Elsevier. 2017. ISSN 0920-5489. [Thomson ISI,
IF JCR2014=0.879].
A. Rodriguez, C. Mateos, A. Zunino: “Improving Scientific Application Execution
on Android Mobile Devices via Code Refactorings”. Software: Practice and Expe-
rience. John Wiley & Sons. 2016. ISSN 0038-0644. [Thomson ISI, IF JCR2014=1.6].
7.3.2. Capítulos de libro
RODRÍGUEZ, ANA; MATEOS, CRISTIAN; ZUNINO, ALEJANDRO; LONGO, MAT-
HIAS. “An Analysis of the Effects of Bad Smell-driven Refactorings in Mobile Ap-
plications on Battery Usage”. Modern Software Engineering Methodologies for Mo-
bile and Cloud Environments (Advances in Systems Analysis, Software Enginee-
ring, and High Performance Computing Series). IGI Global. 2015.
7.3.3. Conferencias
ANA RODRÍGUEZ. “Reducing Energy Consumption of Resource-intensive Scien-
tific Mobile Applications via Code Refactoring”. Estados Unidos de América. New
Jersey. 2017. ICSE 2017 - Doctoral Symposium.
C. MATEOS, A. RODRIGUEZ, M. LONGO, A. ZUNINO: “Energy Implications of
Common Operations in Resourceintensive Java-based Scientific Applications”. 4th
World Conference on Information Systems and Technologies (WorldCist’16), Recife,
Brasil. 2016. Advances in Intelligent Systems and Computing. ISSN 2194-5357.
RODRÍGUEZ, ANA; LONGO, MATHIAS; MATEOS, CRISTIAN; ZUNINO, ALE-
JANDRO. “Using bad smell-driven code refactorings in mobile applications to re-
duce battery usage”. ASSE - 44° JAIIO - Rosario, Santa Fe, Argentina. 2015. [Latin-
dex].
144
HIRSCH, MATÍAS; RODRÍGUEZ, ANA; RODRÍGUEZ, JUAN MANUEL; MATEOS,
CRISTIAN; ZUNINO, ALEJANDRO; ORDIALES COSCIA, JOSÉ LUIS. “A tool for
building retrievable code-first Web Services”. Argentina. Buenos Aires. 2014. Libro.
Artículo Completo. Congreso. 2014 IEEE Biennial Congress of Argentina (ARGEN-
CON). IEEE Seccional Argentina. A.
RODRIGUEZ, C. MATEOS y A. ZUNINO: “Mobile Devices-aware Refactorings
for Scientific Computational Kernels”. XIII Argentine Symposium on Technology
(AST2012) - 41 JAIIO. ISSN 1850-2806. La Plata, Buenos Aires. Agosto-Septiembre
de 2012. SADIO. [Latindex].
145
146
Bibliografía
E. Abebe and C. Ryan. Adaptive application offloading using distributed abstract class
graphs in mobile enviroments. The Journal of System and Software, 85:2755–2769, 2012.
L. Ardito and M. Morisio. Green it available data and guidelines for reducing energy
consumption in it systems. Sustainable Computing: Informatics and Systems, 4(1):24 –
32, 2014. ISSN 2210-5379. doi: http://dx.doi.org/10.1016/j.suscom.2013.09.001. URL
http://www.sciencedirect.com/science/article/pii/S2210537913000504.
K. Asanovic, R. Bodik, B. C. Catanzaro, J. J. Gebis, P. Husbands, K. Keutzer, D. A. Patter-
son, W. L. Plishker, J. Shalf, S. W. Williams, et al. The landscape of parallel computing
research: A view from berkeley. Technical report, Technical Report UCB/EECS-2006-
183, EECS Department, University of California, Berkeley, 2006.
N. Azeemi. Compiler directed battery-aware implementation of mobile applications. In
Emerging Technologies, 2006. ICET ’06. International Conference on, pages 251–256, Nov
2006. doi: 10.1109/ICET.2006.335979.
R. K. Balan, J. Flinn, M. Satyanarayanan, S. Sinnamohideen, and H. Yang. The case for
cybef foraging. In 10th Workshop on ACM SIGOPS European Workshop: beyond the PC,
pages 87–92, 2002.
R. K. Balan, D. Gergle, M. Satyanarayanan, and J. Herbsleb. Simplifying cyber foraging
for mobile devices. In 5th USENIX International Conference on Mobile Systems, Applica-
tions and Services (MobiSys), pages 272–285, 2007.
A. Barisone, F. Bellotti, R. Berta, and A. De Gloria. Jsbricks: a suite of microbenchmarks
for the evaluation of java as a scientific execution environment. Future Generation Com-
puter Systems, 18:293–306, 2001.
R. Baron, O. Lioubashevski, E. Katz, T. Niazov, and I. Willner. Elementary arithmetic
operations by enzymes: A model for metabolic pathway based computing. Angewandte
Chemie International Edition, 45:1572–1576, 2006.
147
L. A. Barroso and U. Holzle. The case for energy-proportional computing. Computer, 40
(12):33–37, Dec 2007. ISSN 0018-9162. doi: 10.1109/MC.2007.443.
R. Barzilay and L. Lee. Learning to paraphrase: an unsupervised approach using
multiple-sequence alignment. In Proceedings of the 2003 Conference of the North American
Chapter of the Association for Computational Linguistics on Human Language Technology-
Volume 1, pages 16–23. Association for Computational Linguistics, 2003.
R. Basmadjian, P. Bouvry, G. Da Costa, L. Gyarmati, D. Kliazovich, S. Lafond, L. Lefevre,
H. De, J.-M. P. Meer, R. Pries, J. Torres, T. Trinh, and S. Khan. Green data centers. Large-
Scale Distributed Systems and Energy Efficiency: A Holistic View, pages 159–196, 2015.
J. Bell and B. Stevens. A survey of known results and research areas for n-queens. Discrete
Mathematics, 309(1):1–31, 2009.
W. Binder. Using bytecode instruction counting as portable cpu consumption metric.
Electronic Notes in Theorical Computer Science, pages 57–77, 2006.
J. Bloch. Effective Java programming language guide. Sun Microsystems, Inc., Mountain
View, CA, USA, 2001. ISBN 0-201-31005-8.
J. Bloch. Effective Java (2Nd Edition) (The Java Series). Prentice Hall PTR, Upper Saddle
River, NJ, USA, 2 edition, 2008. ISBN 0321356683, 9780321356680.
C. Burges, T. Shaked, E. Renshaw, A. Lazier, M. Deeds, N. Hamilton, and G. Hullender.
Learning to rank using gradient descent. In Proceedings of the 22nd international confe-
rence on Machine learning, pages 89–96. ACM, 2005.
A. Carroll and G. Heiser. An analysis of power consumption in a smartphone. In USENIX
annual technical conference, pages 271–285, 2010.
F. H. Carvalho Junior, C. A. Rezende, J. Carvalho Silva, F. J. L. Magalhães, and R. C.
Juaçaba-Neto. Programming Languages: 17th Brazilian Symposium, SBLP 2013, Brasília,
Brazil, October 3 - 4, 2013. Proceedings, chapter On the Performance of Multidimensional
Array Representations in Programming Languages Based on Virtual Execution Machi-
nes, pages 31–45. Springer Berlin Heidelberg, Berlin, Heidelberg, 2013. ISBN 978-3-
642-40922-6. doi: 10.1007/978-3-642-40922-6_3. URL http://dx.doi.org/10.1007/
978-3-642-40922-6_3.
H. Chen, Y. Li, and W. Shi. Fine-grained power management using process-level
profiling. Sustainable Computing: Informatics and Systems, 2(1):33 – 42, 2012. ISSN
2210-5379. doi: http://dx.doi.org/10.1016/j.suscom.2012.01.002. URL http://www.
sciencedirect.com/science/article/pii/S2210537912000030.
148
L. Cheng-Min, L. Jyh-Horng, D. Chyi-Ren, and W. Chang-Ming. Benchmark dalvik and
native code for android system. In Second International Conference on Innovations in Bio-
inspired Computing and Applications, pages 320–323, 2011.
A. S. Christensen, A. Moller, and M. I. Schwartzbach. Precise analysis of string expres-
sions. In 10th International Static Analysis Symposium (SAS), volume 2694, pages 1–18,
2003.
P. Colella. Defining software requirements for scientific computing. Technical report,
DARPA’s High Productivity Computing Systems (HPCS), 2004.
A. Cornish-Bowden. Nomenclature for incompletely specified bases in nucleic acid se-
quences: recommendations 1984. Nucleic acids research, 13(9):3021, 1985.
L. Corral, A. B. Georgiev, A. Sillitti, and G. Succi. A study of energy-aware imple-
mentation techniques: Redistribution of computational jobs in mobile apps. Sus-
tainable Computing: Informatics and Systems, 7:11 – 23, 2015. ISSN 2210-5379. doi:
http://dx.doi.org/10.1016/j.suscom.2014.11.005. URL http://www.sciencedirect.
com/science/article/pii/S2210537914000912.
M. Crasso, C. Mateos, A. Zunino, and M. Campo. SWAM: A logic-based mobile agent
programming language for the Semantic Web. Expert Systems with Applications, 38(3):
1723–1737, 2011. ISSN 0957-4174.
E. Cuervo, A. Balasubramanian, D. Cho, A. Wolman, S. Saroiu, R. Chandra, and P. Bahl.
Maui: Making smartphones last longer with code offload. In 8th international conference
on Mobile systems, applications, and services (ACM MobiSys 10), pages 49–62, 2010.
L. M. de Campos, J. M. Fernández-Luna, and J. F. Huete. Bayesian networks and informa-
tion retrieval: an introduction to the special issue. Information processing & management,
40(5):727–733, 2004.
G. Dhaka and P. Singh. An empirical investigation into code smell elimination sequences
for energy efficient software. In 2016 23rd Asia-Pacific Software Engineering Conference
(APSEC), pages 349–352, Dec 2016. doi: 10.1109/APSEC.2016.057.
M. Dong and L. Zhong. Self-constructive high-rate system energy modeling for battery-
powered mobile systems. In 9th international conference on Mobile systems, applications,
and services, pages 335–348. ACM, 2011.
M. Dong, Y.-S. K. Choi, and L. Zhong. Power-saving color transformation of mobile
graphical user interfaces on oled-based displays. In Proceedings of the 2009 ACM/IEEE
International Symposium on Low Power Electronics and Design, ISLPED ’09, pages 339–
342, New York, NY, USA, 2009. ACM. ISBN 978-1-60558-684-7. doi: 10.1145/1594233.
1594317. URL http://doi.acm.org/10.1145/1594233.1594317.
149
J. Ebert, V. Riediger, and A. Winter. Graph technology in reverse engineering, the tgraph
approach. In 10th Workshop Software Reengineering, 2008.
C. Erbas, S. Sarkeshik, and M. M. Tanik. Different perspectives of the n-queens problem.
In Proceedings of the 1992 ACM annual conference on Communications, pages 99–108. ACM,
1992.
European Commission. Code of conduct on data centres energy efficiency. Technical
report, Institute for Energy, Renewable Energies Unit, 2009. Version 2.0.
N. Fernando, S. W. Loke, and W. Rahayu. Mobile cloud computing: A survey. Future Ge-
neration Computer Systems, 29(1):84 – 106, 2013. ISSN 0167-739X. doi: http://dx.doi.
org/10.1016/j.future.2012.05.023. URL http://www.sciencedirect.com/science/
article/pii/S0167739X12001318. Including Special section: AIRCC-NetCoM 2009
and Special section: Clouds and Service-Oriented Architectures.
J. Flinn, S. Park, and M. Satyanarayanan. Balancing performance, energy, and quality in
pervasive computing. In 22nd International Conference on Distributed Computing Systems,
pages 1–10, 2002.
B. Flipsen, J. Geraedts, A. Reinders, C. Bakker, I. Dafnomilis, and A. Gudadhe. Envi-
ronmental sizing of smartphone batteries. In Electronics Goes Green 2012+ (EGG), 2012,
pages 1–9, 2012.
I. Foster and A. Iamnitchi. Peer-to-Peer System II. 2003.
I. Foster and C. Kesselman. The Grid: Blueprint for a New Computing Infrastructure (2nd
Edition). Morgan Kaufmann, 2003.
M. Fowler. Refactoring: Improving the Design of Existing Code. Addison-Wesley Longman
Publishing Co., Inc., Boston, MA, USA, 1999. ISBN 0-201-48567-2.
N. Friedman, D. Geiger, and M. Goldszmidt. Bayesian network classifiers. Machine lear-
ning, 29(2-3):131–163, 1997.
J. Furthmuller and O. P. Waldhorst. Grid and Cloud Computing: Concepts, Methodologies,
Tools and Applications, chapter Survey on Grid Computing on Mobile Consumer Devi-
ces, page PP. Hershey: IGI Global, 2012.
M. Garey and D. Johnson. Computers and Intractability: A Guide to the Theory of NP- Com-
pleteness. Freeman, 1979.
A. Georges, D. Buytaert, and L. Eeckhout. Statistically rigorous java performance evalua-
tion. SIGPLAN Notices, 42:57–76, Oct. 2007. ISSN 0362-1340.
150
P. Ghosh and S. K. das. Mobility-aware cost-efficiente job scheduling for single-class grid
jobs in a generic mobile grid architecture. Future Generation Computer Systems, 26:1356–
1367, 2010.
Google. Caliper. http://code.google.com/p/caliper/.
M. Gottschalk, M. Josefiok, J. Jelschen, and A. Winter. Removing energy code smells with
reengineering services. In U. Goltz and M. Magnor, editors, Lecture Notes in Informatics,
pages 441–455, 01 2012.
M. Gottschalk, J. Jelschen, A. Winter, et al. Energy-efficient code by refactoring. In 15.
Workshop Software-Reengineering, 2013.
M. Gottschalk, J. Jelschen, and A. Winter. Saving energy on mobile devices by refactoring.
In J. M. Gómez, M. Sonnenschein, U. Vogel, A. Winter, B. Rapp, and N. Giesen, editors,
BIS-Verlag, pages 437–444. BIS-Verlag, 2014. ISBN 978-3-8142-2317-9.
S. Goyal and J. Carter. A lightweight secure cyber foraging infrastructure for resource-
constrained devices. In 6th IEEE Workshop on Mobile Computing Systems and Applications,
pages 186–195, 2004.
A. Greenberg, J. Hamilton, D. A. Maltz, and P. Patel. The cost of a cloud: research pro-
blems in data center networks. ACM SIGCOMM Computer Communication Review, 39
(1):68–73, 2008.
H. Guihot. Renderscript. In Pro Android Apps Performance Optimization, pages 231–263.
Apress, 2012. ISBN 978-1-4302-3999-4. doi: 10.1007/978-1-4302-4000-6_9. URL http:
//dx.doi.org/10.1007/978-1-4302-4000-6_9.
S. R. Gurram and S. Agarwal. Image compression using simple arithmetic operations. In
International Conference on Computational Intelligence and Multimedia Applications, pages
58–62, 2007.
S. Hasan, Z. King, M. Hafiz, M. Sayagh, B. Adams, and A. Hindle. Energy profiles of
java collections classes. In 2016 IEEE/ACM 38th International Conference on Software
Engineering (ICSE), pages 225–236, May 2016. doi: 10.1145/2884781.2884869.
D. Hermelin, D. Rawitz, R. Rizzi, and S. Vialette. The minimum substring cover problem.
Information and Computation/information and Control - IANDC, 206:1303–1312, 2008.
M. Hirsch, J. M. Rodríguez, C. Mateos, and A. Zunino. A two-phase energy-aware
scheduling approach for cpu-intensive jobs in mobile grids. Journal of Grid Compu-
ting, 15(1):55–80, Mar 2017. ISSN 1572-9184. doi: 10.1007/s10723-016-9387-6. URL
https://doi.org/10.1007/s10723-016-9387-6.
151
W. Hofschuster and W. Krämer. C-xsc 2.0 - a c++ library for extended scientific compu-
ting. Lecture notes in computer science, 2991:259–276, 2004.
H. Höpfner and C. Bunse. Towards an energy-consumption based complexity classifi-
cation for resource substitution strategies. In 22. Workshop on Foundations of Databases.
CEUR Workshop Proceeding, volume 581. CEUR-WS. org, 2010.
D. W. Hosmer Jr and S. Lemeshow. Applied logistic regression. John Wiley & Sons, 2004.
D. Huynh, D. Knezevic, J. Peterson, and A. Patera. High-fidelity real-time simulation on
deployed platforms. Computers & Fluids, 43(1):74–81, 2011. ISSN 0045-7930.
A. Jagota. Optimization by reduction to maximum clique. In Neural Networks, 1993., IEEE
International Conference on, pages 1526–1531. IEEE, 1993.
T. Korson and J. D. McGregor. Understanding object-oriented: A unifying paradigm.
Commun. ACM, 33(9):40–60, Sept. 1990. ISSN 0001-0782. doi: 10.1145/83880.84459.
URL http://doi.acm.org/10.1145/83880.84459.
M. D. Kristensen. Scavenger: Transparent development of efficient cyber foraging ap-
plications. In EEE International Conference on Pervasive Computing and Communications
(PerCom), pages 217–226, 2010.
B. Kullbach, B. Kullbach, A. Winter, and A. Winter. Querying as an enabling technology
in software reengineering. In In Proceedings of the 3rd EuroMicro Conference on Software
Maintenance and Reengineering, pages 42–50. IEEE Computer Society, 1999.
S. Lee and J. W. Jeon. Evaluating performance of android platform using native c for
embedded systems. In International Conference on Control Automation and Systems, pages
1160–1163, 2010.
S. Lee, B.-S. Yang, S. Kim, S. Park, S.-M. Moon, K. E. Olu, and E. Altman. Efficient java
exception handling in just-in-time compilation. In ACM Java Grande 2000 Conference,
pages 1463 – 1480, 2000.
C. Li and L. Li. Energy constrained rosource allocation optimization for mobile grids.
Journal of Parallel and Distributed Computing, 70:245–258, 2010a.
C. Li and L. Li. Energy constrained rosource allocation optimization for mobile grids.
Journal of Parallel and Distributed Computing, 70:245–258, 2010b.
D. Li and W. G. J. Halfond. An investigation into energy-saving programming practi-
ces for android smartphone app development. In Proceedings of the 3rd International
Workshop on Green and Sustainable Software, GREENS 2014, pages 46–53, New York,
NY, USA, 2014. ACM. ISBN 978-1-4503-2844-9. doi: 10.1145/2593743.2593750. URL
http://doi.acm.org/10.1145/2593743.2593750.
152
X. Li and J. P. Gallagher. A source-level energy optimization framework for mobile appli-
cations. In 2016 IEEE 16th International Working Conference on Source Code Analysis and
Manipulation (SCAM), pages 31–40, Oct 2016. doi: 10.1109/SCAM.2016.12.
S. W. Loke, K. Napier, A. Alali, N. Fernando, and W. Rahayu. Mobile computations with
surrounding devices: Proximity sensing and multilayered work stealing. ACM Trans.
Embed. Comput. Syst., 14(2):22:1–22:25, Feb. 2015. ISSN 1539-9087. doi: 10.1145/2656214.
URL http://doi.acm.org/10.1145/2656214.
J. Luo, A. E. Savakis, and A. Singhal. A bayesian network-based framework for semantic
image understanding. Pattern Recognition, 38(6):919–934, 2005.
I. Manotas, L. Pollock, and J. Clause. Seeds: A software engineer’s energy-optimization
decision support framework. In Proceedings of the 36th International Conference on Softwa-
re Engineering, ICSE 2014, pages 503–514, New York, NY, USA, 2014. ACM. ISBN 978-
1-4503-2756-5. doi: 10.1145/2568225.2568297. URL http://doi.acm.org/10.1145/
2568225.2568297.
E. Masehian, H. Akbaripour, and N. Mohabbati-Kalejahi. Landscape analysis and effi-
cient metaheuristics for solving the n-queens problem. Computational Optimization and
Applications, 56(3):735–764, 2013.
C. Mateos, A. Zunino, and M. Campo. JGRIM: An approach for easy gridification of
applications. Future Generation Computer Systems, 24(2):99–118, 2008. ISSN 0167-739X.
C. Mateos, A. Zunino, and M. Campo. On the evaluation of gridification effort and run-
time aspects of JGRIM applications. Future Generation Computer Systems, 26(6):797–819,
2010a. ISSN 0167-739X.
C. Mateos, A. Zunino, and M. Campo. An approach for non-intrusively adding malleable
fork/join parallelism into ordinary JavaBean compliant applications. Computer Langua-
ges, Systems & Structures, 36(3):288–315, 2010b. ISSN 1477-8424.
C. Mateos, A. Zunino, and M. Campo. m-JGRIM: A novel middleware for gridifying Java
applications into mobile grid services. Software: Practice and Experience, 40(4):331–362,
2010c. ISSN 0038-0644.
C. Mateos, A. Zunino, M. Hirsch, M. Fernández, and M. Campo. A software tool for
semi-automatic gridification of resource-intensive Java bytecodes and its application
to ray tracing and sequence alignment. Advances in Engineering Software, 42(4):172–186,
2011a. ISSN 0965-9978.
C. Mateos, A. Zunino, R. Trachsel, and M. Campo. A novel mechanism for gridification
of compiled java applications. Computing and Informatics, 30(6):1259–1285, 2011b. ISSN
1335-9150.
153
S. min Park, Y. bae Ko, and J. hoon Kim. Disconnected operation service in mobile grid
computing. In First International Conference on Service Oriented Computing(ICSOC’2003)
in, pages 499–513, 2003.
L. Minas and B. Ellison. Energy Efficiency for Information Technology: How to Reduce Po-
wer Consumption in Servers and Data Centers. Intel Press, 2009. ISBN 1934053201,
9781934053201.
B. Modrek and C. Lee. A genomic view of alternative splicing. Nature genetics, 30(1):
13–19, 2002.
D. Murray, E. Yoneki, J. Crowcroft, and S. Hand. The case for crowd computing. In
In 2nd. ACM SIGCOMM Workshop on Networking, Systems, and Applications on Mobile
Hand-helds, pages 39–44, 2010.
A. Nicolaos, K. Vasileios, A. George, M. Harris, K. Angeliki, and G. Costas. A data locality
methodology for matrix-matrix multiplication algorithm. Journal of Supercomputing, 59:
830–851, 2012.
A. Noureddine, A. Bourdon, R. Rouvoy, and L. Seinturier. A preliminary study of the
impact of software engineering on greenit. In Proceedings of the First International Works-
hop on Green and Sustainable Software, GREENS ’12, pages 21–27, Piscataway, NJ, USA,
2012. IEEE Press. ISBN 978-1-4673-1832-7. URL http://dl.acm.org/citation.cfm?
id=2663779.2663783.
S. Papadimitriou, K. Terzidis, S. Mavroudi, and S. Likothanassis. Exploiting java scientific
libraries with the scala language within the scalalab environment. IET Software, 5:543–
551, 2011.
J. A. Paradiso and T. Starner. Energy scavenging for mobile and wireless electronics. IEEE
Persvasive Computing, 4:18–27, 2005.
C. Pautasso, E. Wilde, and R. Alarcon. REST: Advanced Research Topics and Practical Appli-
cations. Springer, 2014.
R. Perez-Castillo and M. Piattini. Analyzing the harmful effect of god class refactoring
on power consumption. Software, IEEE, 31(3):48–54, May 2014. ISSN 0740-7459. doi:
10.1109/MS.2014.23.
G. Pinto, F. Castor, and Y. D. Liu. Understanding energy behaviors of thread management
constructs. SIGPLAN Not., 49(10):345–360, Oct. 2014. ISSN 0362-1340. doi: 10.1145/
2714064.2660235. URL http://doi.acm.org/10.1145/2714064.2660235.
G. Pinto, F. Soares-Neto, and F. Castor. Refactoring for energy efficiency: A reflection
on the state of the art. In Proceedings of the Fourth International Workshop on Green and
154
Sustainable Software, GREENS ’15, pages 29–35, Piscataway, NJ, USA, 2015. IEEE Press.
URL http://dl.acm.org/citation.cfm?id=2820158.2820165.
P. K. D. Pramanik, P. Choudhury, and A. Saha. Economical supercomputing thru
smartphone crowd computing: An assessment of opportunities, benefits, deterrents,
and applications from india’s perspective. In 2017 4th International Conference on Ad-
vanced Computing and Communication Systems (ICACCS), pages 1–7, Jan 2017. doi:
10.1109/ICACCS.2017.8014613.
G. Procaccianti, H. Fernández, and P. Lago. Empirical evaluation of two best practices for
energy-efficient software development. Journal of Systems and Software, 117:185 – 198,
2016. ISSN 0164-1212. doi: http://dx.doi.org/10.1016/j.jss.2016.02.035. URL http:
//www.sciencedirect.com/science/article/pii/S0164121216000777.
I. Rish. An empirical study of the naive bayes classifier. In IJCAI 2001 workshop on empirical
methods in artificial intelligence, volume 3, pages 41–46. IBM New York, 2001.
A. Rodriguez, C. Mateos, and A. Zunino. Improving scientific application execution on
android mobile devices via code refactorings. Software: Practice and Experience, pages
n/a–n/a, 2016a. ISSN 1097-024X. doi: 10.1002/spe.2419. URL http://dx.doi.org/
10.1002/spe.2419. spe.2419.
A. Rodriguez, C. Mateos, A. Zunino, and M. Longo. An analysis of the effects of bad
smell-driven refactorings in mobile applications on battery usage. In Modern Software
Engineering Methodologies for Mobile and Cloud Environments, pages 155–175. IGI Global,
2016b.
A. V. Rodríguez, C. Mateos, and A. Zunino. Mobile devices-aware refactorings for scien-
tific computational kernels. In 41 JAIIO - AST 2012, pages 61–72, 2012a.
J. M. Rodriguez, A. Zunino, and M. Campo. Mobile grid seas: Simple energy-aware
scheduler. In 39JAIIO - HPC 2010, pages 3341–3354, 2010.
J. M. Rodriguez, C. Mateos, and A. Zunino. Are smartphones really useful for scientific
computing? In Advances in New Technologies, Interactive Interfaces and Communicability,
Lecture Notes in Computer Science, pages 35–44. Springer, 2011a.
J. M. Rodriguez, A. Zunino, and M. Campo. Introducing mobile devices into grid sys-
tems: a survey. Int. J. Web and Grid Services, 7(1):1–40, 2011b.
J. M. Rodríguez, C. Mateos, and A. Zunino. Are smartphones really useful for scienti-
fic computing? In F. Cipolla-Ficarra, K. Veltman, D. Verber, M. Cipolla-Ficarra, and
F. Kammüller, editors, Advances in New Technologies, Interactive Interfaces and Communi-
cability, volume 7547 of Lecture Notes in Computer Science, pages 38–47. Springer Berlin
Heidelberg, 2012b. ISBN 978-3-642-34009-3. doi: 10.1007/978-3-642-34010-9_4.
155
J. M. Rodriguez, C. Mateos, and A. Zunino. Energy-efficient job stealing for cpu-intensive
processing in mobile devices. Computing, 96(2):87–117, 2014.
C. Sahin, F. Cayci, I. L. M. Gutiérrez, J. Clause, F. Kiamilev, L. Pollock, and K. Winbladh.
Initial explorations on design pattern energy usage. In Green and Sustainable Software
(GREENS), 2012 First International Workshop on, pages 55–61, June 2012. doi: 10.1109/
GREENS.2012.6224257.
P. San Segundo. New decision rules for exact search in n-queens. Journal of Global Opti-
mization, 51(3):497–514, 2011.
L. Sangchul and J. J. Wook. Evaluating performance of android platform using native c
for embedded systems. In International Conference on Control, Automation and Systems,
pages 1160–1163, 2010.
M. Sharifi, S. Kafaie, and O. Kashefi. A survey and taxonomy of cyber foraging of mobile
devices. IEEE, 14:1232–1243, 2011.
S. Shivle, H. Siegel, A. A. Maciejewski, P. Sugavanam, T. Banka, R. Castain, K. Chindam,
S. Dussinger, P. Pichumani, P. Satyasekaran, W. Saylor, D. Sendek, J. Sousa, J. Srid-
haram, and J. Velazco. Static allocation of resources to comminicating subtasks in a
heterogeneous ad hoc environment. Journal of Parallel and Distributed Computing, 66:
600–611, 2006.
J. Sinschek, A. Sewe, and M. Mezini. Vm performance evaluation with functional mo-
dels: an optimist’s outlook. In Proceedings of the Third Workshop on Virtual Machines and
Intermediate Languages, pages 6:1–6:2, New York, NY, USA, 2009. ACM. ISBN 978-1-
60558-874-2.
T. F. Smith and M. S. Waterman. Identification of common molecular subsequences. Jour-
nal of molecular biology, 147(1):195–197, 1981.
Y. Y. Su and J. Flinn. Slingshot: Deploying stateful services in wireless hotspots. In 3rd
International Conference on Mobile Systems, Applications, and Services, pages 79–92, 2005.
G. Suryanarayana, G. Samarthyam, and T. Sharma. Refactoring for software design
smells: Managing technical debt. ACM SIGSOFT Software Engineering Notes, 40(6):36,
2015. doi: 10.1145/2830719.2830739. URL http://doi.acm.org/10.1145/2830719.
2830739.
G. L. Taboada, S. Ramos, R. R. Exposito, J. Tourino, and R. Doallo. Java in the high
performance computing arena: Research, practice and experience. Science of Computer
Programming, vv:pp, 2011.
156
N. Thiagarajan, G. Aggarwal, A. Nicoara, D. Boneh, and J. P. Singh. Who killed my
battery?: analyzing mobile browser energy consumption. In 21st international conference
on World Wide Web, pages 41–50. ACM, 2012.
A. R. Tonini, M. Beckmann, J. C. de Mattos, and L. B. de Brisolara. Evaluating android
best practices for performance, 2012.
P. M. Vaidya. An algorithm for linear programming which requires o(((m + n)n2 + (m +
n)1,5n)l) arithmetic operations. Mathematical Programming, 47:175–201, 1990.
R. V. van Nieuwpoort, G. Wrzesinska, C. J. Jacobs, and H. E. Bal. Satin: A high-level and
efficient grid programming model. ACM Transactions on Programming Language and
Systems, 32(3):1–39, 2010. ISSN 0164-0925. doi: 10.1145/1709093.1709096.
R. V. Van Nieuwpoort, G. Wrzesinska, C. J. H. Jacobs, and H. E. Bal. Satin: A high-level
and efficient grid programming model. ACM Trans. Program. Lang. Syst., 32(3):9:1–9:39,
Mar. 2010. ISSN 0164-0925. doi: 10.1145/1709093.1709096. URL http://doi.acm.org/
10.1145/1709093.1709096.
T. Verbelen, P. Simoens, F. D. Turck, and B. Dhoedt. Aiolos: Middleware for improving
mobile application performance through cyber foraging. Journal of Systems and Software,
85:2629–2639, 2012.
C.-Y. Yang, Y. jui Wu, and S. Liao. O2render: An opencl-to-renderscript translator for por-
ting across various gpus or cpus. In Embedded Systems for Real-time Multimedia (ESTI-
Media), 2012 IEEE 10th Symposium on, pages 67–74, Oct 2012. doi: 10.1109/ESTIMedia.
2012.6507031.
J. Zhang. Comparative study of several intelligent algorithms for knapsack problem.
Procedia Environmental Sciences, 11:163–168, 2011.
J. Zhang, J. Lee, and P. K. McKinley. Optimizing the java piped i/o stream library for per-
formance. In International Workshop on Languages and Compilers for Parallel Computing,
pages 233–248. Springer, 2002.
L. Zhang, M. S. Gordon, R. P. Dick, Z. M. Mao, P. Dinda, and L. Yang. Adel: An automatic
detector of energy leaks for smartphone applications. In CODES+ISSS. ACM, 2012a.
Y. Zhang, G. Huang, X. Liu, W. Zhang, H. Mei, and S. Yang. Refactoring android java
code for on-demand computation offloading. In OOPSLA, pages 233–247, 2012b.
157