• Publicidad

Performance en servicio web simple

¿Apenas comienzas con Perl? En este foro podrás encontrar y hacer preguntas básicas de Perl con respuestas aptas a tu nivel.

Performance en servicio web simple

Notapor Fernando » 2011-05-26 19:21 @848

¿Qué tal, gente?

Los molesto nuevamente con una consulta.

A partir de sus consejos, en un tema anterior (performance-perl-vs-mysql-en-busquedas-t6081.html) llegué al siguiente código: es un servicio web donde al que se le pasa como parámetro un dominio/sitio y te devuelve la categoría a la que pertenece el mismo.

El servicio web consta 3 archivos: Ws.pm, ws.cgi y ws_cliente.pl (desde donde se realizan las consultas).

El archivo Ws.pm
Sintáxis: [ Descargar ] [ Ocultar ]
  1. #!/usr/bin/perl 
  2. # Nombre: Ws.pm 
  3.  
  4. use IO::File; 
  5. use strict; 
  6. use warnings; 
  7.  
  8. package Ws; 
  9.  
  10. open(LISTA, "</categorias/lista.dominios") or die "Error al abrir archivo: $!"; 
  11.  
  12. my @lineas = <LISTA>; 
  13. my %hash_table; 
  14.  
  15. for my $linea ( @lineas ) { 
  16.  my @campos = split /,/, $linea; 
  17.  $hash_table{$campos[0]} = "$campos[1]"; 
  18.  
  19. sub ws { 
  20.   my @args = @_; 
  21.   return $hash_table{$args[1]}; 
  22. 1; 


El archivo "/categorias/lista.dominios" que menciono en el código anterior tiene el siguiente formato:
Sintáxis: [ Descargar ] [ Ocultar ]
  1. [...] 
  2. clarin.com,noticias 
  3. lacapital.com.ar,noticias 
  4. blogger.com,blogs 
  5. solojuegos.com,juegos 
  6. [...] 



El archivo ws.cgi
Sintáxis: [ Descargar ] [ Ocultar ]
  1. #!/usr/bin/perl -w 
  2. # Nombre: ws.cgi 
  3. # Web Service - Devuelve la categoría a la que pertenece un dominio dado 
  4.  
  5. use Ws; 
  6. use SOAP::Transport::HTTP; 
  7.  
  8. SOAP::Transport::HTTP::CGI 
  9. ->dispatch_to('Ws') 
  10. ->handle; 



Y finalmente el cliente desde donde hago las consultas: ws_cliente.pl
Sintáxis: [ Descargar ] [ Ocultar ]
  1. #!/usr/bin/perl –w 
  2. # Nombre: ws_cliente.pl 
  3. # Uso: 
  4. #  ws_cliente.pl <dominio> 
  5. ################################################### 
  6. use SOAP::Lite; #+trace => 'debug'; 
  7. $HOST  = "http://localhost/cgi-bin/ws.cgi"; 
  8. $NS   = "urn:Ws"; 
  9. $PHRASE = shift; # lee de la línea de comandos 
  10. my $soap = SOAP::Lite 
  11.  ->readable(1) 
  12.  ->uri($NS) 
  13.  ->proxy($HOST); 
  14. my $som = $soap->ws( 
  15.    SOAP::Data->name("categorias" => "$PHRASE")); 
  16. print "La categoria del sitio es: ".$som->result."\n"; 
  17. 1; 



Entonces, yo hago una consulta simple:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. $ ws_cliente.pl clarin.com
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


y me devuelve:

Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. La categoría del sitio es: noticias
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4



El servicio web funciona. Pero tengo dos problemas:

1. cada consulta que realizo me tira el CPU al 98-99%;
2. cada consulta que realizo tarda aprox. 3-4 segundos, lo cual es mucho ya que la tabla de hash armada (en Ws.pm) tiene apenas 700 mil registros.

¿Qué estoy haciendo mal? ¿Cómo lo puedo mejorar?

¡¡Muchas gracias de antemano!!

Saludos. Fernando.-
Fernando
Perlero nuevo
Perlero nuevo
 
Mensajes: 15
Registrado: 2011-04-16 08:10 @382

Publicidad

Re: Performance en servicio web simple

Notapor explorer » 2011-05-27 02:39 @152

En el anterior hilo, se comentó que, lo ideal, es que el proceso ws.cgi debería quedar residente, porque sino, el proceso de lectura de los dominios/categoría se repite en cada petición (ws.cgi carga ws.pm).

Se podría aumentar las prestaciones, pasando el fichero dominios/categoría a una base de datos sencilla, como sqlite o dbm, o incluso hacer un programa previo que lea y crea el hash y lo guarde en disco con Data::Dumper, de manera que el ws.pm solo tiene que leerlo y evaluarlo (ver bioinfo: Guardar en un archivo los contenidos de variable), o usando un módulo como Storable.

De momento, si no puedes poner el proceso de forma residente, lo que sí puedes hacer es cambiar la forma de trabajar de ws.pm.
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. # Nombre: Ws.pm
  3.      
  4. package Ws;
  5.  
  6. sub ws {
  7.     my ($self, $dominio_a_buscar) = @_;
  8.  
  9.     open(LISTA, "</categorias/lista.dominios") or die "Error al abrir archivo: $!";
  10.  
  11.     while(<LISTA>) {
  12.         my ($dominio, $categoria) = split /,/;
  13.  
  14.         if ($dominio eq $dominio_a_buscar) {
  15.             chomp  $categoria;
  16.             return $categoria;
  17.          }
  18.     }
  19.     return;
  20. }
  21.  
  22. 1;      
  23.  
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Es decir, leemos el fichero línea a línea, y si encontramos lo que buscamos, devolvemos la $categoria y terminamos de buscar. Con esto, ya reducimos el tiempo de búsqueda a la mitad (de media).

Pero la eficiencia máxima sería que la información no fuera necesario leerla en cada invocación: hacer que el proceso sea residente, quedando el hash permanente en memoria.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14486
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Performance en servicio web simple

Notapor Fernando » 2011-05-27 13:53 @620

¡Hola explorer!

Gracias por la ayuda.

Sí, en el hilo anterior me comentabas que se podría utilizar CGI::Fast para crear una sola vez la tabla de hash y mantenerla en memoria. Pensé que al invocar el Ws.pm desde el ws.cgi estaba haciendo algo similar. Obviamente estaba equivocado.

Está bien, la idea entonces es dejar la tabla persistente. A mi me interesa que sea un servicio web de consultas. ¿Cómo quedaría la estructura? ¿Sería simplemente UN archivo .cgi (ws.cgi por ejemplo, SIN Ws.pm) haciendo uso de CGI::Fast y SOAP::Transport?

Estuve leyendo la documentación de CGI::Fast la cual dice claramente que existe una carga inicial (en mi caso sería el armado de la tabla de hash) y luego el programa se mantiene persistente en memoria atendiendo las llamadas, pero no me termina de quedar en claro si además tengo que utilizar SOAP para hacerlo WebService o simplemente con FCGI alcanza.

Por otro lado, te consulto: al hacerlo servicio web con SOAP y/o FCGI, ¿tengo igualmente que utilizar un fork() para cada consulta (espero varias consultas por segundo) o el mismo SOAP/FCGI lo manejan internamente a este tipo de cosas?

Muchas gracias. ¡Saludos!
Fernando
Perlero nuevo
Perlero nuevo
 
Mensajes: 15
Registrado: 2011-04-16 08:10 @382


Volver a Básico

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron