dilluns, 27 d’octubre de 2014

Jasime TDD en javascript

Em vaig decidir provar el jasmine. La veritat què 2.0 mola per què no depen d'altra biblioteca (ajuda molt) i s'arranca des d'una web (més fàcil no pot ser), ens el baixem i mirem (editem) l'arxiu SpecRuner.html. Ahí haurem d'incloure els tests i els nostres arxius .js:


Per exemple, podem veure el generador de questionaris que on estic treballant ara (https://github.com/fercavi/jsquest). Els tests es poden agrupar, el grup haurà de rebre un nom i es fa amb la funció describe:

describe("Generar html per a preguntes individuals", function() {
  test1
  test2
...
});

cada test es realitzarà amb la funció it:
it("Generar una pregunta de resposta llarga", function() {
  cos del test
});

el cos del test deurà de tindre unes condicions, definides amb la funció  expect, per exemple: expect(obj1).toEqual(obj2)
(caldria mirar la documentació per veure totes les comparacions, anem a veure un test sencer:

describe("Generar html per a preguntes individuals", function() {
  var item;

  it("Generar una pregunta de resposta llarga", function() {
    item = new ItemRespostaLlarga("De quin color era el cavall blanc de Santiago",666,false);
    item.generarPregunta();
    expect(item.html).toEqual("<form name='f666' ><p id=666 obligatoria='false' >De quin color era el cavall blanc de Santiago<br/><textarea cols=80 rows=6 name=pregunta666></textarea></p></form>");
  });
});

Per exemple l'arxiu complet tindria este aspecte:


Recordem que al github tenim tots els arxius del projecte.
Quan vaig publicar l'article se'm va oblidar posar una captura de que passa quan obrim l'SpecRunner.html:




dimarts, 14 d’octubre de 2014

Codin laic a pro: C#.net


Ara vaig a veure com instal·lar C# (i poder programar en ell clar). Com les versions  que venen al repositori són velles, anem a instal·lar les noves versions via codi i compilar. Primer necessitem el Mono nou (Mono és una implementació lliure de .Net de microsoft):

Compilant, no funciona


sudo apt-get install git autoconf libtool automake build-essential mono-devel gettext
git clone https://github.com/mono/mono

Normalmetn sol haver un ./configure, però en aquest cas només trobem un script, anem a executar-lo:
./autogen.sh

Entre altres coses, es posarà a abaixar dependències. Compilem:
make get-monolite-latest
make EXTERNAL_MCS=${PWD}/mcs/class/lib/monolite/Basic.exe

I així és compilarà sense tindre cap versió de mono instalada, ara instal·lem:
make install

Després necessitarem instal·lar gtk-sharp, però com a pas previ ens demana els gtk-devel:
sudo apt-get install libgtk-3-dev  gnome-sharp libglade2-dev libglade2.0-cil-dev 

Una vegada instal·lada l'última versió de Mono (3.10 en estos moments), anem a fer el mateix amb monodevelop:
git clone git://github.com/mono/monodevelop.git
cd monodevelop
./configure

i una vegada configurat, compilem:
make
I després de 15000 intents no funciona, per tant obtem per afegir els repositoris d'algú que haja pogut.

Via fàcil


sudo apt-add-repository ppa:ermshiperete/monodevelop
Refresquem el synaptic, i si busquem monodevelop tenim el 5 ja, i el podem instal·lar. S'instal·la en la carpeta /opt, i per executar-lo tenim un launcher:
/opt/monodevelop/bin/monodevelop-launcher.sh


dilluns, 13 d’octubre de 2014

Codin laic a pro: javascript

Bo, anem a veure com programar en mode  pro ;) Els pros, ara gasten javascript (a mi no me mireu, jo li tinc mania). Però anem a veure com s'instal·la el node.js i un editor (també pro) anomenat atom (que no és més que una copia del sublime text ). Primer hem d'habilitar el repositori d'ubuntu:
Aplicacions->Administració de Lliurex->Lliurex Apt i marquem ubuntu. Accepten i es posarà a actualitzar els repositoris:
Ara instal·lem el node.js:

sudo apt-get install nodejs

Ara anem a la web d'atom (https://atom.io/) i amb tanta mala sort que no hi ha paquets per a linux en 32 bits. Ens diu que ens l'abaixem (https://github.com/atom/atom, podem abaixar-lo com a zip si no tenim el github, de tota manera ens el demanarà per instal·lar), i anem a instal·lar-lo:
1. abaixar
2. Descomprimir (unzip atom-master-zip)
3.cd atom-master
4.Instal·lació d'altres paquets de dependències:
sudo apt-get install build-essential git libgnome-keyring-dev fakeroot
5.executem l'ordre build dins de /script, a mi em dona el següent error:
cd script
./build
node v0.10 is required to build Atom, node 0.6.12 is installed, per tant, haurem d'actualitzar node.js:
sudo apt-get update
sudo apt-get upgrade
I després de mitja hora actualitzant, vegem que continua donant el mateix problema;
provem açò (https://rtcamp.com/tutorials/nodejs/node-js-npm-install-ubuntu/):
sudo apt-get install python-software-properties
sudo apt-add-repository ppa:chris-lea/node.js
sudo apt-get update
sudo synaptic (i marquem les actualitzacions de node.js) 
 
Ara si intentem .build no ens dona cap problema, encara que tarda una estoneta (a un i7, a un c2d del treball va ser una sort que era hora d'esmorzar); una vegada haja acabat, podem fer tres coses:
a) Instal·lar:
sudo ./grunt install 
b) Crear un paquet:
sudo ./grunt mkdeb 
c) executar des d'ahí:
cd ..
./atom.sh
 
Ara ja tenim un editor per a programar en mode pro, ara anem a provar-ho:creem amb el node un nou arxiu (prova.js):



i ara ja podrem executar el programa:

 Ala ja som pro i programem en node.js ;)

divendres, 10 d’octubre de 2014

Jocs de Blizzard

No he pogut solucionar el problema amb el dragon age, hui he intentat jugar als jocs de blizzard i ara comptaré com ho he fet. Primer de tot, instal·lar wine 1.7. La versió que tinc instal·lada és la 1.7.18 i ho he fet funcionar. La versió que m'ha instal·lat per defecte és la 1.6 i amb eixa petava el Battle.Net.
La putada és que abans funcionava perfectament els jocs, però des que al launcher han afegit Battle.net fa les coses molt complicades; de moment puc jugar a 11 -20 fps. (deuria de jugar al màxim possible ;)):

Veurem si puc optimitzar-ho o algo

10 minuts després

Després de diversos intents he aconseguit fixar l'API a OpenGL (sempre em tornava a DirectX 9, inclus posant l'D3D11). Tal i com he llegit ací:
http://geebzor.com/tech/linux/wow-ubuntu-14-04-trusty/

Obric l'arxiu WTF/Config.wtf i afegisc o modifique:
SET gxAPI "OpenGL"

Amb això ja em trau +60 fps i tot al màxim.
PS:Obric el jocs amb wine wow.exe per a no traure el launcher de Battle.net

dijous, 9 d’octubre de 2014

Dragon age: Origins en Lliurex

Aprogitant que Origin regala el dragon age per un període breu de temps, m'he proposat veure si funciona en Lliurex:
https://www.origin.com/es-es/store/buy/dragon-age-1/pc-download/base-game/standard-edition

Vegem que primer ens haurem de registrar. Des d'ahí podrem comprar el dragon age (si ho fem ja és de bades) i abaixar un client tipus steam.  L'arranquem amb el wine i vegem que instal·la, actualitza...
I vegem que ens demana usuari:


Una vegada posem correctament l'usuari i password ens ix la nostra biblioteca de jocs, des d'on podem seleccionar quins volem descarregar/instal·lar si no els tenim:
De moment he posat a descarregar el Dragon Age, però és prou tard i ja és tard, demà provaré si funciona ;)

Val, acaba de donar-me error de descàrrega i pel que he llegit pareix que no es puga instal·lar en Linux. Aarrg


10 minuts més tard

Prove en PlayOnLinux, li pose el títol i després d'un parell d'assistents, descàrregues... Em demana des d'on vull instal·lar, provarem des de Steam Store a veure si el l'abaixa. Per començar, m'instal·la l'Steam (per sort ja tinc usuari):

Quan instal·lem ens demana actualitzar (per que no t'abaixes res actualitzat mai?). Després d'instal·lar-se, tenim l'steam instal·lat però pensava que s'abaixaria el joc o algo. No l'has de comprar tu i no he pogut posar el codi qu eme donen a Origin en l'Steam.


Però qui sap igual hi ha alguna manera d'aprofitar el serial obtés amb origin ;) Però amb l'Steam, es veu que no.

Drivers ATI

Bo, per defecte, en teoria es podria instal·lar automàticament els drivers des de la finestreta de controladors restrictius, però a mi m'ha donat un error, per tant he anat a la pàgina web i m'he abaixat els drivers:

els he descomprimit (unzip nomarxiu.zip) i anem a executar l'script que ens apareix com a superusuari, i ens apareixerà un assistent:


Quan acaba, ens demana reiniciar i en teoria ja estaria, però no va ser tan fàcil. A mi almenys em donava un error. He hagut de esborrar tots els paquets (pareix ser que a l'intentar amb els controladors restrictius deixava paquets a mitges i feia conflicte amb l'instal·lador de la web). He hagut d'executar:
sudo sh /usr/share/ati/fglrx-uninstall.sh 
sudo apt-get remove --purge fglrx fglrx_* fglrx-amdcccle* fglrx-dev*
 
he tornat a reiniciar, a instal·lar i ara si que m'ha anat bé, Aplicacions->Ferramentes del Sistema->Preferències->Amd Catalyst Control Center:

 Provem el glxgears i obtenim 6000fps no està mal, no?

Comencem

Arranquem amb la versió 14.04 de lliurex. De moment pareix que vaja bé en un alienware m17x r4 :
intel i7 3610QM
8GB de RAM
disc dur SSD
 ATI HD7970

Veurem quins resultats va donant:


dimecres, 8 d’octubre de 2014

Primer mal de cap en javascript, l'abast de les variables

Per sort o per desgràcia vaig decidir provar javascript (en part per què volia veure com funcionava jasmine per fer tests, hauré de fer un altre post amb això).
Aneu a veure el meu mal de cap, imaginem aquest codi:

function recorrecvector2(){
  for(i=0;i<vector2.length;i++){
      //fer algo amb el vector2
     }
  }

for(i=0;i<Vector.length;i++){
  recorrecvecto2();
}


Així a simple vista pot resultat correcte, però, però, però... resulta que en Js al no haver declaració de tipus, les variables "comencen el seu abast" quan són declarades i no són "substituïdes" a no ser que posem var. Si ens fixem amb l'index i dels bucles, és la mateixa variable. tant en el bucle de fora com en la funcio recorrecvector2. Els resultats són esotèrics ;). Amb una declaració estricta de tipus això no passaria, però javascript (ni en general cap llenguatge d'scripting) solen tindre eixe tipus de declaració. Després de dos dies calfant-me el cap, amb alerts per totes bandes, simplement posar un var davant de la primera i en cada bucle for se soluciona:

function recorrecvector2(){
  for(var i=0;i<vector2.length;i++){
      //fer algo amb el vector2
     }
  }

for(var i=0;i<Vector.length;i++){
  recorrecvecto2();
}

dimecres, 1 d’octubre de 2014

PHP vs Node.js: rendiment en concurrència

Bo, doncs per motius laborals i familiars he estat un poc absent (del bloc), però ja aprofitant unes proves que he fet al treball, vaig a mostrar els resultats obtesos.
En principi, com sempre li he tingut mania al javascript, pensava que seria més lent que el php, però pareix ser que l'asincronisme fa que en determinades coses vaja molt més ràpid. La prova consisteix en recorrer un parell de taules enormes (400k registres) i fer alguns càlculs. He fet les proves amb el benchmarking de apache (ab), anem a veure el codi, he obviat les consultes per simplificar:

PHP

$sql='';
$preguntesResult =  mysql_query($sql) or die('Consulta fallidaA: ' . mysql_error());

$sqlrespostes= ''
$respostesResult =  mysql_query($sqlrespostes) or die('Consulta fallidaB: ' . mysql_error());
while($line = mysql_fetch_array($preguntesResult, MYSQL_ASSOC)){
  $preguntes[]= $line;
}
foreach ($preguntes as $pregunta) {

}
$cadena = "";
while($line = mysql_fetch_array($respostesResult, MYSQL_ASSOC)){
  $respostes[] = $line;

  foreach($preguntes as $pregunta){
      $cadena .= $pregunta["id"] . ":" . $line["pregunta"] . "\n";
      //echo $cadena;
  }
}
file_put_contents("volcat1.php.txt",$cadena,FILE_APPEND);
foreach($preguntes as $pregunta){
  //
}


Node.js


var mysql = require('mysql');
var http = require('http');

function doProcess(req, res) {
  var connection = mysql.createConnection({
  });
  connection.connect();
  respostes = [];
  preguntes = [];
  sql = ';
  connection.query(sql, function(err, rows, fields) {
    if (err) throw err;
    for (i = 0; i < rows.length; i++) {
      preguntes[i] = rows[i];
    }
    for (i = 0; i < preguntes.length; i++) {

    }
    for (i = 0; i < preguntes.length; i++) {

    }
  });
  sql2 = '';
  cadena = "";
  connection.query(sql2, function(err, rows, fields) {
    if (err) throw err;
    for (i = 0; i < rows.length; i++) {
      respostes[i] = rows[i];
      for (j = 0; j < preguntes.length; j++) {        
        cadena += preguntes[j]["id"] + ":" + respostes[i]["pregunta"] + "\n";        
      }
    }
      res.writeHead(200, {
        'Content-Type': 'text/html'
      });
      res.write('Acabat');
      res.end();
    }
  });

  connection.end();
}
server = http.createServer(doProcess);
server.listen(8080);


Els resultats em van sorprender, executats a aquesta màquina:
CPU: Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz
RAM: 4GB 
a un lliurex 14.04 Pime, anem a fer 10000 peticions amb una concurrència de 10 simulant les peticions que anaven a fer.

Provem el benchmark php:

ab -r -n 10000 -c 10 http://localhost/benchmark1.php

i el resultat:

Server Software: Apache/2.4.10
Server Hostname: localhost
Server Port: 80

Document Path: /benchmark1.php
Document Length: 6 bytes

Concurrency Level: 10
Time taken for tests: 5123.183 seconds
Complete requests: 10000
Failed requests: 0
Total transferred: 2080000 bytes
HTML transferred: 60000 bytes
Requests per second: 1.95 [#/sec] (mean)
Time per request: 5123.183 [ms] (mean)
Time per request: 512.318 [ms] (mean, across all concurrent requests)
Transfer rate: 0.40 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 936 5123 1472.6 5331 9829
Waiting: 936 5119 1471.5 5325 9829
Total: 936 5123 1472.6 5331 9829

Percentage of the requests served within a certain time (ms)
50% 5331
66% 5901
75% 6233
80% 6392
90% 6864
95% 7272
98% 7737
99% 8073
 100% 9829 (longest request)  


És a dir, 1,42 hores en fer el test, una mitjana de 5s per petició. Ara provem el codi en node:

ab -r -n 10000 -c 10 http://localhost/:8080

i el resultat:

Server Software:        Apache/2.4.10
Server Hostname:        localhost
Server Port:            80

Document Path:          /:8080
Document Length:        278 bytes

Concurrency Level:      1000
Time taken for tests:   59.963 seconds
Complete requests:      100000
Failed requests:        698
   (Connect: 0, Receive: 206, Length: 286, Exceptions: 206)
Non-2xx responses:      99714
Total transferred:      45669012 bytes
HTML transferred:       27720492 bytes
Requests per second:    1667.70 [#/sec] (mean)
Time per request:       599.630 [ms] (mean)
Time per request:       0.600 [ms] (mean, across all concurrent requests)
Transfer rate:          743.77 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0   18 255.1      1    7016
Processing:     3  156 2055.9      9   52491
Waiting:        0  103 1720.5      8   39935
Total:          5  174 2103.1     10   52491

Percentage of the requests served within a certain time (ms)
  50%     10
  66%     10
  75%     11
  80%     11
  90%     13
  95%     16
  98%     22
  99%   1190
 100%  52491 (longest request)


Sorprenentment, i després d'esperar més d'una hora i mitja a l'enterior test, este tarda quasi un minut per a resoldre el mateix problema. Després d'un dia revisant el codi per que pareix que hi haja un error, per mi i per altra gent, i vegent i comparatnt resultats, vegem que node.js guanya en el seu terreny, és a dir, múltiples peticions concurrents. Ja que node no es bloqueja en cap cas, i en php cada petició a la base de dades és bloquejant.
Vol dir que sempre va millor node.js? Doncs supose que no, però en este cas, absolutament sí, com s'ha demostrat.