Bueno, ya tengo el ejemplo que demuestra consumo excesivo de memoria...
Para probarlo, usar una herramienta tipo SoapUI para hacer peticiones masivas...
Despues, tenemos la llamada;
http://127.0.0.1:1092/xml_mini el cual nos devuelve un XML usando la libreria MiniXML
http://127.0.0.1:1092/xml_doc el cual nos devuelve un XML usando la clase TXMLDocument
Resultados de las pruebas de estres;
MINIXML--> Empiezo con 2 Megas de RAM, 7 hilos simultanios -+ 100.000 peticiones --> Se queda el programa con un consumo de memoria de 4.7 MB
TXMLDoc-->Empiezo con 2 Megas de RAM, 7 hilos simultanios -+ 100.000 peticiones --> Se queda el programa con un consumo de memoria de
80.6 MB!!!!!
Este es el XML que se retorna en los 2 casos
<SetConceptoHotelPMSRS CODIGOHOT="">
<CONCEPTO PAX="1"/>
<CONCEPTO PAX="2"/>
<CONCEPTO PAX="3"/>
<CONCEPTO PAX="4"/>
<CONCEPTO PAX="5"/>
<CONCEPTO PAX="6"/>
<CONCEPTO PAX="7"/>
<CONCEPTO PAX="8"/>
<CONCEPTO PAX="9"/>
<CONCEPTO PAX="10"/>
</SetConceptoHotelPMSRS>
Dejo el codigo fuente, para a ver si alguien puede corroborar esto;
- Code: Select all Expand view RUN
#
# $Id: hbmk.hbm
#
hbssl.hbc
hbhttpd.hbc
hbblink.hbc
hbwin.hbc
hbmxml.hbc
-lxhb -lgtwin -lgtwvg -lgtgui -lhbwin -lhbmisc -lhbxpp -lhbct
-ic:\programacion\harbour3\contrib\xhb
-oserver.exe
-w0
-es1
-mt
test.prg
- Code: Select all Expand view RUN
// t:\harbour3\bin\hbmk2
#include "hbthread.ch"
#include "Hblog.ch"
#include "hbdll.ch"
STATIC s_hMutex
STATIC s_lLog4Harbour := .T.
MEMVAR get, post, server
FUNCTION HB_GTSYS()
REQUEST HB_GT_WVT_DEFAULT
RETURN NIL
/*---------------------------------------------------------------------------------------------*/
/* Entrada al servidor WEB */
/*---------------------------------------------------------------------------------------------*/
#include "fileio.ch"
FUNCTION Main( cParam1, cParam2 )
LOCAL lMutex
LOCAL n := 0
Local lCreateThread := hb_mtvm()
if lCreateThread
run_web()
endif
hb_MemoWrit( ".uhttpd.stop", "" ) // ESTO PARA el servidor WEB
RETURN
#require "hbssl"
#require "hbhttpd"
/*---------------------------------------------------------------------------------------------*/
procedure run_web( )
LOCAL oServer
LOCAL oLogAccess
LOCAL oLogError
LOCAL nPort := 1092
IF hb_argCheck( "stop" )
hb_MemoWrit( ".uhttpd.stop", "" )
RETURN
ELSE
FErase( ".uhttpd.stop" )
ENDIF
oLogAccess := UHttpdLog():New( hb_dirBase() +"web_access.log" )
IF ! oLogAccess:Add( "" )
oLogAccess:Close()
RETURN
ENDIF
oLogError := UHttpdLog():New( hb_dirBase() +"web_error.log" )
IF ! oLogError:Add( "" )
oLogError:Close()
oLogAccess:Close()
RETURN
ENDIF
oServer := UHttpdNew()
IF ! oServer:Run( { ;
"FirewallFilter" => "", ;
"LogAccess" => {| m | oLogAccess:Add( CStr( m )+ hb_eol() ) }, ;
"LogError" => {| m | oLogError:Add( Cstr( m )+ hb_eol() ) }, ;
"Trace" => {| ... | QOut( ... ) }, ;
"Port" => nPort, ;
"Idle" => {| o | iif( hb_FileExists( ".uhttpd.stop" ), ( FErase( ".uhttpd.stop" ), o:Stop() ), NIL ) }, ;
"SSL" => .F.,;
"Mount" => { ;
"/info" => {|| informarcion() }, ;
"/xml_mini" => {|| play_xml() }, ;
"/xml_doc" => {|| play_doc() }, ;
"/" => {|| UWrite( "Hello!" ) } } } )
oLogError:Close()
oLogAccess:Close()
ErrorLevel( 1 )
RETURN
ENDIF
oLogError:Close()
oLogAccess:Close()
RETURN
/*
Devuelve información del Entorno
*/
static function informarcion()
UWrite( '<h2>Version Test : '+ "df_Version" +'</h2>' )
return UProcInfo()
// --------------------------------------------------------------------------------//
// Usando MiniXML apenas se nota consumo de memoria.
// --------------------------------------------------------------------------------//
function play_xml()
local xml, cStr := space( 100000 ), data, htree, x
xml := mxmlNewXML("1.0")
data = mxmlNewElement(xml, "SetConceptoHotelPMSRS")
mxmlElementSetAttr( data, "CODIGOHOT", "" )
for x := 1 to 10
hTree = mxmlNewElement( data, "CONCEPTO" )
mxmlElementSetAttr( htree, "PAX", alltrim( Cstr( x ) ) )
next
mxmlSaveString( xml , @cStr )
mxmlDelete( xml )
UAddHeader( "Content-Type", "text/xml;charset=utf-8" )
return UWrite( cStr )
// --------------------------------------------------------------------------------//
// Usando TXMLDOC grave problema de memoria
// --------------------------------------------------------------------------------//
#include "hbclass.ch"
#include "hbxml.ch"
function play_doc( )
Local oTarifas
Local cEncoding := "ISO-8859-1"
oTarifas := Twebtarifas():New()
for x := 1 to 10
oTarifas:Append( X )
next
UAddHeader( "Content-Type", "text/xml;charset=utf-8" )
UWrite( oTarifas:WriteXML() )
RETURN nil
// --------------------------------------------------------------------------------//
// --------------------------------------------------------------------------------//
CLASS TGeneric
DATA CodigoHot INIT ""
DATA IDUSER INIT "0"
DATA oDoc
DATA lUTF8 INIT .F.
ENDCLASS
// --------------------------------------------------------------------------------//
// --------------------------------------------------------------------------------//
CLASS Twebtarifas from TGeneric
DATA aTarifas
DATA Operacion INIT "SetConceptoHotelPMSRS"
METHOD New() CONSTRUCTOR
METHOD WriteXML()
METHOD Append( cCodigo, cDescripcion )
METHOD CreateXML()
ENDCLASS
// --------------------------------------------------------------------------------//
METHOD New( ) CLASS Twebtarifas
::aTarifas := {}
RETURN Self
METHOD CreateXML( ) CLASS Twebtarifas
Local oNode, oNodeP, oRes
cEncoding := "UTF-8"
::oDoc := TXmlDocument():New() // Creacion del documento respuesta....
::oDoc:oRoot:AddBelow( TxmlNode():New( HBXML_TYPE_PI,'xml' , , 'version="1.0" encoding="'+ cEncoding +'" ' ) )
RETURN ::oDoc:oRoot
// --------------------------------------------------------------------------------//
METHOD WriteXML() CLASS Twebtarifas
Local oNode, oNodeP, oNodeConcepto, aTarifa
oNode := ::CreateXML()
oNodeP := TxmlNode():New( HBXML_TYPE_TAG, ::Operacion )
oNodeP:SetAttribute( "CODIGOHOT", ::CodigoHot )
oNodeP:SetAttribute( "IDUSER", ::IdUser )
oNode:AddBelow( oNodeP )
if !empty( ::aTarifas )
for each aTarifa in ::aTarifas
oNodeConcepto := TxmlNode():New( HBXML_TYPE_TAG, "CONCEPTO" )
oNodeConcepto:SetAttribute( "PAX", UHtmlEncode( aTarifa[1] ) )
oNodeP:AddBelow( oNodeConcepto )
next
endif
RETURN ::oDoc:ToString()
METHOD Append( nPax ) CLASS Twebtarifas
AADD( ::aTarifas, { alltrim( Cstr( nPax ) ) } )
RETURN NIL