martes, 4 de julio de 2017

Optimización y Buenas Prácticas en Java

  • http://albertoromeu.com/optimizar-codigo-java-android/




  1. Evitar concatenaciones de Strings, utilizar StringBuffer o StringBuilder para tal caso. La concatenación de Strings produce cada vez un nuevo objeto y por tanto, mayor consumo de memoria y mayor recolección de basura.
  2. La encriptación y conexiones https tienen peor rendimiento.
  3. Crear métodos con el menor número de parámetros posible. Esta es de primero de SOLID.
  4. Si se van a realizar operaciones complejas como, senos, cosenos u otras operaciones complicadas de coma flotante y se sabe de antemano cuál va a ser el resultado, es conveniente pre-calcular estos valores y utilizarlos como constantes.
  5. Soportar el trabajo off-line siempre que sea posible persistiendo la información en el almacenamiento del dispositivo.
  6. Sacar fuera de los bucles las constantes y creación de nuevos objetos
  7. Siempre que vayamos a acceder a la misma posición de un array varias veces, es mejor guardar esa posición en una variable local y así evitar el acceso repetido al índice del array.
  8. Delegar operaciones demasiado complejas en portales y acceder a los resultados a través de servicios web o conexiones de red.
  9. Utilizar buffers para leer datos a través de la red y leer los datos en porciones en lugar de byte a byte que es más lento.
  10. Reutilizar y hacer pool de objetos siempre que sea posible para evitar crear nuevas instancias.
  11. Liberar recursos tan pronto como sea posible, como conexiones de red, a streams o a ficheros. Normalmente, se suele liberar este tipo de recursos dentro de la cláusula finally para asegurarnos de que los recursos se liberan aún cuando se produzca alguna excepción.
  12. Referenciar a null instancias de objetos que ya no se van a usar, para que el recolector de basura libere memoria.
  13. Instanciación perezosa de objetos.
  14. Los métodos sincronizados son los más lentos, a continuación los métodos de interfaz, los métodos de instancia, los métodos finales y por último los métodos estáticos son los más rápidos. Hay que tener en cuenta esta clasificación para evitar siempre que sea posible la sincronización e interfaces.
  15. Evitar en cualquier caso sincronización dentro de bucles.
  16. Usar variables es más eficiente que arrays. Los arrays son más eficientes que Vector o HashTable y en cualquier caso, arrays unidimensionales siempre mejor que bidimensionales. Tener en cuenta también que hay que inicializar la clase Vector y HashTable con un tamaño que se ajuste a nuestras necesidades.
  17. El acceso a los atributos de una clase es más rápido que encapsular con getter y setter.
  18. El acceso a variables locales es más rápido que a atributos de la clase. Siempre que sea posible asignar atributos de una clase a una variable local si se va a hacer referencia a ella varias veces dentro de un método o bucle.
  19. Contar hacia atrás es más rápido en los bucles.
  20. Usar operadores como x+=1 en vez de x = x+1 ya que generan menos byte code.
  21. Utilizar desplazamiento de bits en vez de la multiplicación o división si es posible. Por ejemplo, x >> 2 es equivalente a x / 4 y x << 10 es equivalente a x * 1024, 1 << 20 es equivalente a Math.pow(2, 20).
  22. Cuando sea posible evitar bucles ya que evitaremos toda la sobrecarga de control de flujo en cada iteración. Por ejemplo, si tenemos una operación que se va a realizar 5 veces, en vez de utilizar un bucle podemos realizar las 5 operaciones secuencialmente.
  23. Normalmente cuesta menos comparar un número a cero, así, siempre que sea posible en un bucle utilizar como guarda una comparación a cero.
  24. Usar tipos escalares en lugar de objetos Java siempre que sea posible, por ejemplo, int en lugar de Integer.
  25. Usar excepciones únicamente cuando sea necesario ya que cada excepción lanza un nuevo objeto.

  • ???

  1. Sustituir concatenación de Strings por StringBuffer
  2. Usar “new” sólo cuando sea necesario
  3. Evitar la creación de objetos temporales innecesarios
  4. Trazas de depuración
  5. Inicialización del sistema de trazas
  6. Evitar el uso de System.out y System.err en código de producción
  7. Siempre que sea posible, inicializar las colecciones con el tamaño adecuado
  8. Evitar las llamadas a métodos dentro de las condiciones de bucles

  • http://developing.frogtek.org/2010/09/10/10-mandamientos-java/

  1. Si tenemos un método estático , no debería poder acceder a variables que no están pensadas para llamarse de forma estática
  2. Si tenemos una variable estática, no deberíamos poder escribirla desde un método perteneciente a un objeto instanciado
  3. No dejar vacíos if-else / switch
  4. No repetir contenido en if-else / switch
  5. Verificar que todos los métodos privados son invocados en algún momento
  6. No usar nombres cortos para variables, a excepción de las variables de iteración
  7. Verificar la visibilidad de las variables
  8. Documentar (javadoc)
  9. Evitar duplicidad de literales

  • https://www.securecoding.cert.org/confluence/display/java/ERR04-J.+Do+not+complete+abruptly+from+a+finally+block

  1. xxx
  2. xxx

viernes, 8 de agosto de 2014

Truco para LOGs

Me está siendo muy útil la creación de estos 2 ficheros de proceso por lotes:

1. Para realizar copias de seguridad diarias de un directorio usando WinRAR

@echo off
setlocal
mkdir workarea\backups
set yy=%date:~-4,4%
set mm=%date:~-7,2%
set dd=%date:~-10,2%
set hh=%time:~0,2%
if "%hh:~0,1%" equ " " set hh=0%hh:~1,1%
set mi=%time:~3,2%
set ss=%time:~6,2%
set logfile=C:\workarea\backups\LOG_%yy%%mm%%dd%_%hh%%mi%%ss%.log
set logerrorfile=C:\workarea\backups\LOG_%yy%%mm%%dd%_%hh%%mi%%ss%_ERROR.log
set rarfile=C:\workarea\backups\BACKUP_%yy%%mm%%dd%_%hh%%mi%%ss%.rar
set origin=C:\workarea\starteam\neos\impl\workspace_Juno
rar a -r -y  -ilog%logerrorfile% -log=%logfile% %rarfile% %origin%

2. Para ejecutar un proceso Maven

@echo off
setlocal
mkdir _logs
set yy=%date:~-4,4%
set mm=%date:~-7,2%
set dd=%date:~-10,2%
set hh=%time:~0,2%
if "%hh:~0,1%" equ " " set hh=0%hh:~1,1%
set mi=%time:~3,2%
set ss=%time:~6,2%
set logfile=LOG_%yy%%mm%%dd%_%hh%%mi%%ss%.log
mvn -f pom-parcial.xml clean install > _logs\%logfile%

La pecularidad de ambos scripts es que permiten salvar los nombres de los ficheros creados sin el espacio de la hora que existe por defecto en los sistemas Windows, entre las 01:00h y las 09:59h.

Dejo pendiente la tarea similar para el periodo de tiempo 00:00h y las 00:59h, dado que es una situación en la que no me he hallado.

jueves, 22 de marzo de 2012

Backup

En cierta ocasión tuve que desarrollar un sistema sencillo para hacer copias de seguridad de todas las bases de datos no-de sistema para cierta instancia.

Éste es el script que desarrollé, de nombre backup.sql:

DECLARE @name VARCHAR(50) -- database name 
DECLARE @path VARCHAR(256) -- path for backup files 
DECLARE @fileName VARCHAR(256) -- filename for backup 
DECLARE @fileDate VARCHAR(20) -- used for file name

SET @path = 'C:\COPIAS_SEGURIDAD\' 
SELECT @fileDate = convert(varchar, getdate(), 102)+'_'+ replace(convert(varchar, getdate(),14),':','.')
DECLARE db_cursor CURSOR FOR 
SELECT name
FROM master.dbo.sysdatabases
WHERE name NOT IN ('master','model','msdb','tempdb') 

OPEN db_cursor  
FETCH NEXT FROM db_cursor INTO @name  

WHILE @@FETCH_STATUS = 0  
BEGIN  
       SET @fileName = @path + @name + '_' + @fileDate + '.BAK' 
       BACKUP DATABASE @name TO DISK = @fileName 

       FETCH NEXT FROM db_cursor INTO @name  
END  

CLOSE db_cursor  
DEALLOCATE db_cursor


Para que pudiera funcionar tanto para instalaciones express como superiores, tenía que ser independiente del SQL Agent, por lo que escribí el siguiente fichero BACKUP.bat

sqlcmd -E -i "backup.sql" -S nombrerequipo\nombreinstancia

el cual sería ejecutado periódicamente por el sistema de Tareas Automatizadas del equipo.

miércoles, 21 de marzo de 2012

Perfomance Monitor + SQL Profiler

El otro día estaba leyendo un magnífico artículo sobre cómo correlacionar el monitor de Actividad de Windows (Perfomance Monitor o perfmon), junto con SQL Server Profiler, y he intentado crear un pequeño script que active ambas aplicaciones de forma simultánea.

En primer lugar, nos centramos en el Perfomance Monitor, en el cual hemos creado nuestro recopilador de datos (Data Collector Set) al que hemos llamado XData.

Ejecutando un START.bat de contenido

logman "XData" start 

podemos comenzar a recopilar datos.

Un segundo script STOP.bat de contenido

logman "XData" stop

finalizará dicha ejecución.

Si acudimos a la ruta en la que está almacenada la información capturada, podemos ver que ha funcionado correctamente al crearse un archivo de extensión BLG.


Ahora bien, este recopilador de datos se puede exportar en formato XML, ¿como importarlo para poder usarlo en otro equipo? Mediante un tercer script llamado IMPORT.bat y de contenido

logman import XData -s . -xml "C:\rutaexportacion\plantilla_XData.xml"


Un segundo paso es el SQL Server Profiler, en el cual ya hemos creado previamente la plantilla (extensión TDF) deseada.

Para arrancar el Profiler, podemos editar START.bat y añadir la siguiente línea.

C:\rutaprofiler\PROFILER.EXE /S nombreservidor\nombreinstancia /E /T "XData" /O "C:\rutaTrace\fileTrace.trc" /R /Z 32

¿Y cómo parar el seguimiento creado mediante STOP.bat? Aparentemente, no existe forma mediante la combinación COMMANDLINE+GUI de poder parar esa traza cuando deseemos.

Así pues, unido a que en ciertos entornos la carga de usar GUI puede afectar al rendimiento del equipo y, por tanto, a los resultados obtenidos por la traza, tendremos que descargar usar el GUI y usar otro método para hacer una correlación que nos permita pararla con tan sólo "darle a un botón".

Para diseñar esa alternativa, seguiremos algunas de las indicaciones comentadas en este artículo de SqlServerCentral.

Démosle a ese START.bat y dejemos que se cree la traza, la paramos enseguida y exportamos la definición de la traza File | Export | Script Trace Definition | For SQL 2005 & 2008. Ello nos genera un script de extensión SQL, y que llamaremos XDataStartTrace.sql, que sigue este esquema.

/****************************************************/
/* Created by: SQL Server 2008 R2 Profiler          */
/* Date: 21/03/2012  00:00:00         */
/****************************************************/
-- Create a Queue
declare @rc int
declare @TraceID int
declare @maxfilesize bigint
declare @DateTime datetime


set @DateTime = '2012-03-21 00:00:00.000'
set @maxfilesize = 32


-- Please replace the text InsertFileNameHere, with an appropriate
-- filename prefixed by a path, e.g., c:\MyFolder\MyTrace. The .trc extension
-- will be appended to the filename automatically. If you are writing from
-- remote server to local drive, please use UNC path and make sure server has
-- write access to your network share


exec @rc = sp_trace_create @TraceID output, 0, N'InsertFileNameHere', @maxfilesize, @Datetime
if (@rc != 0) goto error


-- Client side File and Table cannot be scripted


-- Set the events
declare @on bit
set @on = 1
exec sp_trace_setevent @TraceID, 122, 1, @on
--[blablabla]
exec sp_trace_setevent @TraceID, 13, 12, @on


-- Set the Filters
declare @intfilter int
declare @bigintfilter bigint


exec sp_trace_setfilter @TraceID, 10, 0, 7, N'SQL Server Profiler - 110f7c77-8a36-4269-b10c-e321672274f3'
-- Set the trace status to start
exec sp_trace_setstatus @TraceID, 1


-- display trace id for future references
select TraceID=@TraceID
goto finish


error: 
select ErrorCode=@rc


finish: 
go

Y que tenemos que editar, tal y como en el mismo script se sugiere.

/****************************************************/
/* Created by: SQL Server 2008 R2 Profiler          */
/* Date: 21/03/2012  00:00:00         */
/****************************************************/
-- Create a Queue
declare @rc int
declare @TraceID int
declare @maxfilesize bigint
declare @options integer -- suma de las opciones de comportamiento deseadas
declare @nameOutFile nvarchar(255) --nombre archivo sin extensión


set @options = 6
set @maxfilesize = 32
set @nameOutFile  ='XDataTrace_' + convert(varchar, getdate(), 102)+'_'+ replace(convert(varchar, getdate(),14),':','.')


exec @rc = sp_trace_create @TraceID output, @options , @nameOutFile, @maxfilesize, NULL
if (@rc != 0) goto error


-- Client side File and Table cannot be scripted


-- Set the events
declare @on bit
set @on = 1
exec sp_trace_setevent @TraceID, 122, 1, @on
--[blablabla]
exec sp_trace_setevent @TraceID, 13, 12, @on


-- Set the Filters
declare @intfilter int
declare @bigintfilter bigint


exec sp_trace_setfilter @TraceID, 10, 0, 7, N'SQL Server Profiler - 110f7c77-8a36-4269-b10c-e321672274f3'
-- Set the trace status to start
exec sp_trace_setstatus @TraceID, 1


-- display trace id for future references
select TraceID=@TraceID
goto finish


error: 
select ErrorCode=@rc


finish: 
go

Así, para arrancar este script, tenemos que editar el archivo START.bat de la siguiente forma

logman "XData" start 
sqlcmd -E -i "XDataStartTrace.sql" -S nombreservidor\nombreinstancia


Para pararlo, necesitaremos un script XDataStopTrace.sql de contenido

declare @TraceID INT
select @TraceID = TraceID
from :: fn_trace_getinfo(0)
where CAST([value] as nvarchar(255)) like '%XDataTrace%'


if @TraceID IS NOT NULL
begin
print 'Closing Trace ID ' + cast(@TraceID as varchar(5))
exec sp_trace_setstatus @TraceID, 0
exec sp_trace_setstatus @TraceID, 2
end

el cual es llamado desde STOP.bat, cuyo contenido es

logman "XData" stop 
sqlcmd -E -i "XDataStopTrace.sql" -S nombreservidor\nombreinstancia

Vamos a probar si esto funciona...
  1. Creamos el colector de datos mediante IMPORT.bat.
  2. Ejecutamos START.bat
  3. A través del Management Studio creamos un script, con contenido

    declare @I INT
    set@I = 0 
    print '@I= ' + cast(@I as nvarchar)
    while @I < 100000000
    begin
    insert into myTabla(col2) values (cast(GETDATE() as nvarchar))
    set @I = @I + 1
    end
  4. Lo dejamos correr medio minuto, y paramos mediante STOP.bat
  5. Abrimos Profiler y cargamos la traza creada (archivos de extensión TRC).
Como vemos en esta imagen, todo parece haber funcionado correctamente.