Figuremoslo entre todos: FlushBuffer/Caminata

Tomih.-

MinisteriumAO
Investigando muchos temas sobre como mejorar el servidor a lo largo de estos días, me tope con un tema: el FlushBuffer del AO en un post que publicó Lorwik hace aproximadamente 6 meses.


La teoría que tenía, es que el ping aumentaba cada vez que el usuario caminaba, discutiendo con ciertos usuarios le dieron por causa al sistema de caminata, como también al flushbuffer.

Esto no es solamente en 13.x, ya que la duda de él surgió en un AO 12.x. Tampoco depende del host: ya que corriendo el servidor en localhost el problema es el mismo.

En las siguientes imágenes podemos ver esto.


¿Porqué un flushbuffer?
El AO ejecuta en el MainLoop del cliente la función de FlushBuffer.
El AO ejecuta en el GameTimer (cada 40 ms por usuario), la función del FlushBuffer.

La idea es que quien quiera de sus causas por lo que esto puede ser así juntos, lo solucionamos entre todos.
Desde ya muchisimas gracias
 
Última edición:

Lorwik

Destructor Lvl 4
Ex-Staff
A ver, os cuento un poco mis observaciones...

Esto lo descubri en AODrag, el cual se basa en una 0.12.3. En un principio crei que era un bug provocado por alguna de mis modificaciones, pero estuve probando en otras versiones de AO y parece ser que pasa en todas (tambien probe en GSZAO).
Si juegas desde localhost y/o solo no vas a notarlo. Si tienes el server hosteado en alguna maquina que no pertenezca a tu red local, vas a notar como el ping sube cuando empiezas a caminar. Si estas parado realizando cualquier otra accion, el ping se mantiene estable.
El problema no es el ping obviamente, el problema son sus efectos, ya que genera lag.

Pude ver este problema en un servidor online, con muchos usuarios, y no solo yo me pude dar cuenta, tambien varios usuarios que se quejaban por este efecto, y es muy muy raro. Hay 2 tipos de casos y lo voy a explicar con un ejemplo:

Estoy parado en el muelle nix, y en ese momento hay varios usuarios parados, caminando de una lado a otro (lo tipico). Y me puede pasar que...

- Puedo ver a la gente a saltitos, es decir, no voy a ver que tengan una caminata seguida y fluida, simplemente los voy a ver a saltitos. Y cuando mando /ping, sin yo hacer absolutamente nada, el ping me sube.

- Puedo ver a la gente normal o medio normal, alguno puede dar un saltito de vez en cuando.

Estuve mirando bastante esto y discutiendolo con mas gente, y es cierto que pueden ser varias cosas lo que podria causar este problema, como lo que comento Tomih. Tambien pense cuando descubri este problema que podria ser el sistema de areas, ya que habia aumentado el screen y recalculado este sistema. Y discutiendo con mas gente sobre esto, llegamos a la conclusion de que podria ser el como esta programado el sistema de caminata.
Probe a crear un buffer exclusivamente para la caminata (tengo que decir que no tengo mucha experiencia tocando los buffer y no se si lo hice 100% bien) y parece que el problema se resolvio, pero si pulsaba la "L" para corregir la posicion, era como si solo hubiese avanzado unos pocos tiles, como si en vez de avanzar 20 tiles, hubiese avanzado 10.

Lo unico que se es que parece ser que es un problema que afecta a todas las versiones y a casi todos los servidores. Y digo casi por que en IAO este problema no existe, aunque se sabe que ellos son "especiales" xD.
 

Dr. GoDKeR

El Rey y el As
Miembro del equipo
Administrador
Developer
Moderador de RRPP
Moderador de AO
Moderador de Tecnología
Moderador de Entretenimiento
Moderador de Diseño
Especialista de RRPP
Especialista de Entretenimiento
Especialista de Tecnología
Especialista de Argentum
Especialista de Diseño
El GameTimer tiene un flushbuffer a los mensajes encolados, si uno envia un paquete con el EnviarDatosASlot, eso lo envia directo al socket del cliente en específico. Y CREO que la caminata se va por ahí (mismo caso cuando se envia con el SendData).

Si no fuese el caso, saquen los timers, metan un loop, hagan diferentes chequeos de ticks y meten ahi el code de los timers, y al final del loop, FlushBuffer
 

Tomih.-

MinisteriumAO
El GameTimer tiene un flushbuffer a los mensajes encolados, si uno envia un paquete con el EnviarDatosASlot, eso lo envia directo al socket del cliente en específico. Y CREO que la caminata se va por ahí (mismo caso cuando se envia con el SendData).

Si no fuese el caso, saquen los timers, metan un loop, hagan diferentes chequeos de ticks y meten ahi el code de los timers, y al final del loop, FlushBuffer
Si, la caminata se va por ahí, tenes razón
Código:
If Not isAdminInvi Then _
                Call SendData(SendTarget.ToPCAreaButIndex, UserIndex, PrepareMessageCharacterMove(UserList(UserIndex).Char.CharIndex, nPos.X, nPos.Y))
 

Dr. GoDKeR

El Rey y el As
Miembro del equipo
Administrador
Developer
Moderador de RRPP
Moderador de AO
Moderador de Tecnología
Moderador de Entretenimiento
Moderador de Diseño
Especialista de RRPP
Especialista de Entretenimiento
Especialista de Tecnología
Especialista de Argentum
Especialista de Diseño
Por las dudas, chequeá el senddata, no me acuerdo bien, pero creo que internamente hace un EnviarDatosASlot
 

Tomih.-

MinisteriumAO
Por las dudas, chequeá el senddata, no me acuerdo bien, pero creo que internamente hace un EnviarDatosASlot
Si no me equivoco tenes razon, no lo tengo a mano pero estoy casi seguro que es asi. De todas formas, manda a todos menos al index (a vos mismo). Por eso, porque daria lag cuando caminas solo y tiras /PING?
 

Dr. GoDKeR

El Rey y el As
Miembro del equipo
Administrador
Developer
Moderador de RRPP
Moderador de AO
Moderador de Tecnología
Moderador de Entretenimiento
Moderador de Diseño
Especialista de RRPP
Especialista de Entretenimiento
Especialista de Tecnología
Especialista de Argentum
Especialista de Diseño
Esta para el orto hecho, osea, la idea es buena, la aplicacion esta maso maso.
 

Lorwik

Destructor Lvl 4
Ex-Staff
Ese aporte me da miedo, y tengo el presentimiento que si lo implementas te va a explotar todo xD.
 

Tomih.-

MinisteriumAO
Es todo culpa de microsoft. Maldita sociedad capitalista

Enviado desde mi SM-G355M mediante Tapatalk
Jajjajajajajajaja

ON:Che tratemos de no irnos de tema, no tienen ninguna otra idea?

El servidor lo que hace cuando le llega el movimiento del usuario es revisar la posición, si medita, si necesita un cambio de área y updatea la posición acá.

Código:
oldUserIndex = MapData(.Pos.map, .Pos.X, .Pos.Y).UserIndex
             
                ' Si no hay intercambio de pos con nadie
                If oldUserIndex = UserIndex Then
                    MapData(.Pos.map, .Pos.X, .Pos.Y).UserIndex = 0
                End If
             
                .Pos = nPos
                .Char.heading = nHeading
                MapData(.Pos.map, .Pos.X, .Pos.Y).UserIndex = UserIndex
                             
                Call DoTileEvents(UserIndex, .Pos.map, .Pos.X, .Pos.Y)

                Call ModAreas.CheckUpdateNeededUser(UserIndex, nHeading)
 

Lucho~

Usuario Bendecido
Ese aporte me da miedo, y tengo el presentimiento que si lo implementas te va a explotar todo xD.
No creo que te explote todo, proba, si no funciona se vuelve atras.

De todas formas, creo que en un 99% de los servidores esta este problema y es jodido de arreglar, por la cual casi nadie lo pudo arreglar.
 

Lorwik

Destructor Lvl 4
Ex-Staff
Es como si cuando caminaras estuvieras enviando muchisimos paquetes a una frecuencia muy alta y la "autopista" se colapsara. Quizas se deberia de revisar la cantidad de paquetes que se envia al caminar, ya que esto pasa cuando caminamos o cuando alguien camina, no se...
 

Dr. GoDKeR

El Rey y el As
Miembro del equipo
Administrador
Developer
Moderador de RRPP
Moderador de AO
Moderador de Tecnología
Moderador de Entretenimiento
Moderador de Diseño
Especialista de RRPP
Especialista de Entretenimiento
Especialista de Tecnología
Especialista de Argentum
Especialista de Diseño
Con poner un indicador que muestre ctos bytes se envian/reciben deberia bastar, aunque dudo que venga por ahi, y lo que puso tomih es comun en versiones anteriores al binario (11.5). Si en 11.5 pasa y en fenix no, por ejemplo, seria problema (seguramente) del modAreas.

Edit: Además, los ms no necesariamente es un problema de paquetes, es posible que el servidor se ponga lento al procesar algo, por lo que el tiempo de respeusta es mayor.
 

Tomih.-

MinisteriumAO
Con poner un indicador que muestre ctos bytes se envian/reciben deberia bastar, aunque dudo que venga por ahi, y lo que puso tomih es comun en versiones anteriores al binario (11.5). Si en 11.5 pasa y en fenix no, por ejemplo, seria problema (seguramente) del modAreas.

Edit: Además, los ms no necesariamente es un problema de paquetes, es posible que el servidor se ponga lento al procesar algo, por lo que el tiempo de respeusta es mayor.
Lo que no me cierra es que por ejemplo, en el mod areas no hace nada si el personaje no cambia de area
Código:
Public Sub CheckUpdateNeededUser(ByVal UserIndex As Integer, ByVal Head As Byte, Optional ByVal ButIndex As Boolean = False)
'**************************************************************
'Author: Lucio N. Tourrilhes (DuNga)
'Last Modify Date: 28/10/2010
'Es la función clave del sistema de areas... Es llamada al mover un user
'15/07/2009: ZaMa - Now it doesn't send an invisible admin char info
'28/10/2010: ZaMa - Now it doesn't send a saling char invisible message.
'**************************************************************
    If UserList(UserIndex).AreasInfo.AreaID = AreasInfo(UserList(UserIndex).Pos.X, UserList(UserIndex).Pos.Y) Then Exit Sub
Quizas el MoveToLegalPos no esta muy bien hecho.

Yo lo reescribi apenas, lo deje asi
Código:
Function MoveToLegalPos(NewPos As WorldPos, Optional ByVal PuedeAgua As Boolean = False, Optional ByVal PuedeTierra As Boolean = True) As Boolean
'***************************************************
'Autor: ZaMa
'Last Modification: 13/07/2009
'Checks if the position is Legal, but considers that if there's a casper, it's a legal movement.
'13/07/2009: ZaMa - Now it's also legal move where an invisible admin is.
'***************************************************

Dim MoveUserIndex As Integer
Dim MoveNPCIndex As Integer
Dim IsDeadChar As Boolean
Dim IsAdminInvisible As Boolean


'¿Es un mapa valido?
If (NewPos.map <= 0 Or NewPos.map > NumMaps) Or _
   (NewPos.X < MinXBorder Or NewPos.X > MaxXBorder Or NewPos.Y < MinYBorder Or NewPos.Y > MaxYBorder) Then
        MoveToLegalPos = False
Else
    With MapData(NewPos.map, NewPos.X, NewPos.Y)
        MoveUserIndex = .UserIndex
        MoveNPCIndex = .NpcIndex
       
        If MoveUserIndex > 0 Then
            IsDeadChar = (UserList(MoveUserIndex).flags.Muerto = 1)
            IsAdminInvisible = (UserList(MoveUserIndex).flags.AdminInvisible = 1)
        Else
            IsDeadChar = False
            IsAdminInvisible = False
        End If
       
        If PuedeAgua Then
            If PuedeTierra Then
                MoveToLegalPos = (.Blocked <> 1) And _
                (MoveUserIndex = 0 Or IsDeadChar Or IsAdminInvisible) And _
                (MoveNPCIndex = 0)
            Else
                MoveToLegalPos = (.Blocked <> 1) And _
                (MoveUserIndex = 0 Or IsDeadChar Or IsAdminInvisible) And _
                (MoveNPCIndex = 0) And _
                (HayAgua(NewPos.map, NewPos.X, NewPos.Y))
            End If
        ElseIf PuedeTierra Then
            MoveToLegalPos = (.Blocked <> 1) And _
            (MoveUserIndex = 0 Or IsDeadChar Or IsAdminInvisible) And _
            (MoveNPCIndex = 0) And _
            (Not HayAgua(NewPos.map, NewPos.X, NewPos.Y))
        Else
            MoveToLegalPos = False
        End If
       
    End With
End If

End Function

Saludos
 

Dr. GoDKeR

El Rey y el As
Miembro del equipo
Administrador
Developer
Moderador de RRPP
Moderador de AO
Moderador de Tecnología
Moderador de Entretenimiento
Moderador de Diseño
Especialista de RRPP
Especialista de Entretenimiento
Especialista de Tecnología
Especialista de Argentum
Especialista de Diseño
Igual, por las dudas, prueben de ver la cantidad de paquetes que entran/salen.
 

Tomih.-

MinisteriumAO
Igual, por las dudas, prueben de ver la cantidad de paquetes que entran/salen.
Ya hice las pruebas. Moviendome constantemente, solo tres tiles para arriba y bajar de vuelta de forma constante genera un ingreso constante al servidor de 16 bytes.
Por otro lado, el servidor, devuelve al cliente el monto de 90 bytes....
Saludos!

Edit: la estoy flasheando, si me quedo me muevo en circulo exacto de 1x1 el envio y la recepción es igual, eso si, cuando entro en un area el sv me manda 100 bytes aprox.
 

Lorwik

Destructor Lvl 4
Ex-Staff
Ya habia barajado la posibilidad de que las areas puedan estar provocando el problema o tuviera algo que ver. Quizas quitando el sistema de areas completamente y probando... si encuentro un rato pruebo y os cuento.

PD: En 0.9.9z nunca probe, es una de esas versiones que ni me molesto en mirar. xD
 

Tomih.-

MinisteriumAO
Ya habia barajado la posibilidad de que las areas puedan estar provocando el problema o tuviera algo que ver. Quizas quitando el sistema de areas completamente y probando... si encuentro un rato pruebo y os cuento.

PD: En 0.9.9z nunca probe, es una de esas versiones que ni me molesto en mirar. xD
Para mi tambien va por el lado de que el paquete de caminata se manda cada 54 ms, entonces para tres pasos, por ahi tardaste segundo y medio por lo cual mandaste un poquito mas de 25 paquetes.. Ya se que son simples bytes, y por ahi como vos dijiste no se nota en local host pero por ahi cuando vamos a otra escala de conexion afecta un poco mas.
Cuando pegas mandas un solo paquete, cuando meditas tambien, pero cuando mantenes la tecla de caminar mandas uno cada 54ms...

Código:
    'Control movement interval (this enforces the 1 step loss when meditating / resting client-side)
    If GetTickCount - LastMovement > 56 Then
        LastMovement = GetTickCount
    Else
        Exit Sub
    End If
 
Arriba