mayo
31

Generar fechas al azar con PHP

Posted In: PHP, Programación by Mauro Zadunaisky

A veces sucede que debemos llenar una tabla con cientos de miles de registros para probar el rendimiento de una aplicación, de modo que no tengamos sorpresas el día de mañana cuando la base de datos crezca mucho. Por lo general los registros se llenan con información al azar y para eso hemos creado una función que genera fechas al azar dentro de un rango establecido.

	function random_date($from = 0, $to = null) {
		if (!$to) {
			$to = date('U');
		}
		if (!ctype_digit($from)) {
			$from = strtotime($from);
		}
		if (!ctype_digit($to)) {
			$to = strtotime($to);
		}
		return date('Y-m-d h:i:s', rand($from, $to));
	}
marzo
28

Minimizar consultas SQL repetidas en CakePHP

Posted In: CakePHP by Mauro Zadunaisky

Trabajando en optimización de performance de una aplicación CakePHP noté que una consulta SQL se estaba ejecutando más de una vez, siempre igual y devolviendo el mismo resultado.

El método del modelo que generaba la consulta era más o menos así

/**
 * Determina si un producto está habilitado
 *
 * @param int $id Id del producto en base de datos
 * @return boolean
 * @access public
 */
public function isEnabled($id) {
	$product = $this->find('first', array(
		'conditions' => array('Product.id' => $id),
		'fields' => array('enabled')
	));
	if (empty($product)) {
		$out = false;
	} else {
		$out = !empty($product['Product']['enabled']);
	}
	return $out;
}

En algunos casos, al momento de llamar a isEnabled ya teníamos disponible el array con los datos del producto porque habíamos ejecutado un find previamente, así que el método se podría reescribir pasándole el array con todos los datos en vez del id, y con eso ya nos ahorraríamos consultas SQL repetidas

/**
 * Determina si un producto está habilitado
 *
 * @param array $product Array del producto retornado por un find()
 * @return boolean
 * @access public
 */
public function isEnabled($product) {
	return !empty($product['Product']['enabled']);
}

Sin embargo, esto hizo fallar algunos casos de testing porque en otros lugares de la aplicación el método necesitaba recibir el id el producto y todavía no se había leído el producto desde base de datos como para pasar el array.

La refactorización final quedó así:

/**
 * Determina si un producto está habilitado
 *
 * @param mixed $product Array del producto retornado por un find() o id del producto
 * @return boolean
 * @access public
 */
public function isEnabled($product) {
	if (!is_array($product) or empty($product['Product']['enabled'])) {
		$product = $this->find('first', array(
			'conditions' => array('Product.id' => $product),
			'fields' => array('enabled')
		));
	}
	if (empty($product)) {
		$out = false;
	} else {
		$out = !empty($product['Product']['enabled']);
	}
	return $out;
}
marzo
24

Tenemos el siguiente array

$r = array(
	0 => 'verde',
	1 => 'azul',
	2 => 'verde',
	3 => 'verde',
	4 => 'amarillo',
);

Y queremos eliminar los elementos duplicados, para lo cual tenemos dos opciones

1. array_values + array_unique

$r = array_values(array_unique($r));

2. array_keys + array_flip

$r = array_keys(array_flip($r));

¿Cuál es mejor?

Desde el punto de vista de legibilidad del código ambas opciones son válidas, ya que el comportamiento de cada una de las funciones utilizadas es bastante simple de comprender y se pueden consultar en el manual de PHP. Por lo tanto, lo único que puede determinar la conveniencia de una opción por sobre la otra es el tiempo de ejecución de cada una.

Para determinarlo, hemos realizado un benchmark. Estos son los resultados:

Opción 1 (array_values + array_unique)

-> Testing http://localhost/experimental/array_unique/1.php

Total Requests made: 1000
Total Time elapsed: 14.009807348251 (seconds)

Requests/Second: 71.379 req/sec
Average request time: 0.014 seconds
Standard deviation of average request time: 0.002
Longest/shortest request: 0.017 sec/0.004 sec

Opción 2 (array_keys + array_flip )

-> Testing http://localhost/experimental/array_unique/2.php

Total Requests made: 1000
Total Time elapsed: 13.918713331223 (seconds)

Requests/Second: 71.846 req/sec
Average request time: 0.014 seconds
Standard deviation of average request time: 0.003
Longest/shortest request: 0.017 sec/0.004 sec

Conclusión

La diferencia entre una opción y otra es prácticamente despreciable, así que la conclusión es que da lo mismo usar cualquiera.

Otra idea que podemos rescatar de esto es que realizar comparaciones entre funciones nativas de PHP realmente es un desperdicio de tiempo porque casi nunca se lograrán resultados significativos. Las verdaderas mejoras en la performance de una aplicación o website se consiguen atacando aquellas partes del código que mayores recursos consumen, como por ejemplo: consultas a base de datos, llamados excesivos a funciones recursivas, consumo de webservices, mala gestión de caché, etc.

octubre
8

Libro “Desarrollo web profesional”

Posted In: Libros by Mauro Zadunaisky

_desarrollo-web-profesional

Desarrollo Web profesional es un libro que intenta reunir en una sola obra muchos temas relacionados al desarrollo web de la actualidad, y lo consigue con bastante éxito. Resulta complicado escribir una revisión del libro en su conjunto, ya que en él se encuentran temas variados, que van desde cuestiones básicas de XHTML, CSS y Javascript, hasta herramientas avanzadas como Firebug y Web Developer, pasando por teoría de los archivos de imágenes, funcionamiento de HTPP, configuración de .htaccess y algo de SEO. Parece más un compendio de artículos sueltos que un libro, si bien todos los capítulos resultan muy interesantes y útiles.
Read More