Optimisation sur lecture de Socket

Questions à propos du scripting. Hors Shader, GUI, Audio et Mobile.
zugsoft
Messages : 386
Inscription : 26 Juin 2014 23:43
Localisation : Swiss
Contact :

Optimisation sur lecture de Socket

Message par zugsoft » 27 Jan 2015 17:42

Salut tout le monde,

Je suis en train de finaliser mon jeu FPS multijoueur sur Unity.
Il utilise un moteur multijoueur que j'avais créé pour un jeu de FPS en XNA(C#) pour WindowsPhone7 et 8 coté client Mobile et en C coté serveur Linux.
Je jongle entre des paquets envoyés par Socket UDP et TCP en fonctione de l'importance des donnés.
J'ajuste la vitesse d'emission en fonction de la vitesse de reponse du serveur pour ne pas perdre trop de paquet.

Le temps de réponse entre le moment ou j'envoi ma position et le moment ou je recois les informations sur le serveurs sont de 43 a 53ms en Wifi et 71 a 83ms en 3G.


J'ai pu utiliser mon moteur XNA ecrit en C# sur Unity en moins de 5minutes, mais je voudrai améliorer certains points.

1/ Optimisation des data envoyés du joueur , StringBuilder?
Actuellement j'envoi un gros String qui concatene toutes les informations sur le joueur, sa position, rotation, action demandé, numero acquittement.... , j'ai vu qu'il etait mieux d'utiliser StringBuilder que de faire une concatenation.
Avez vous remarqué une grosse différence entre la concatenation et StringBuilder?

2 / Compactage des données
J'envoi environ un paquet de 1800octets depuis mon serveur lorsqu'il y a 8 joueurs, celui ci contient principalement des chiffres, je voulais donc travailler sur 4 bits au lieu de 8 pour fabriquer mon propre paquet, mais comment faire?
J'imagine que lorsque j'envoi "1;1;1" pour traduire ma position en x=1,y=1 et z=1 , le paquet transmis doit etre d'une taille de 5octets, et en hexa 313b313b31.
En employant mon propre format je pourrai n'utiliser que 3octets en codant sur 4bits.
Quelqu'un sait comment travailler avec une socket en binaire ou en hexa?

3/ Lecture des données sur le client Mobile
Pour chaque paquet recu je split le gros String avec plusieurs caracteres pour recuperer les informations de tous les joeurs, ca genere donc des dizaines de tableau de String plusieurs fois par secondes.
Avez vous une idée plus efficace?


Je tenais a dire que j'etais entierement satisfait du resultat, mais pour mon prochain jeu de RTS ou il y aura 400 unités cela risque de vite monter a 90koctets par paquets, j'ai peur des temps de reponses.
Moon RTS

Avatar de l’utilisateur
ZJP
Messages : 5748
Inscription : 15 Déc 2009 06:00

Re: Optimisation sur lecture de Socket

Message par ZJP » 27 Jan 2015 18:36

a) StringBuilder, Concaténation = Nid à GC :mrgreen: Personnellement j'utilise un tableau de "Float". Pas d'Entiers ni de Bools. Ils sont (très) peu nombreux par rapport aux réels. ;)
b) Envoyer uniquement les infos qui ont changées.
c) Vu la puissance des CPUs il peut être intéressant de compacter (zip) les données avant l’envoi et les "dezziper" à la réception. (Le plus simple dans ton cas, vu que cela fonctionne (déjà) correctement)
d) Utiliser (dans certains cas) du bezier/Spline pour les déplacement des unités. Seulement 3 positions (départ, centrale, arrivée) envoyés au départ, puis l'indice de "position/temps" qui varie de 0.0 a 1.0. A utiliser aussi pour du prédictif. Je m'en sert pour l"IA aérienne et les "patterns" de vol >> Split, Immelman, Tonneaux. Bref...
...

zugsoft
Messages : 386
Inscription : 26 Juin 2014 23:43
Localisation : Swiss
Contact :

Re: Optimisation sur lecture de Socket

Message par zugsoft » 27 Jan 2015 21:22

a/
Merci pour tes réponses, mais comment tu fais pour envoyer un tableau a un socket ? ca demande un tableau de byte.

Je fais comme ca :
byte[] payload = Encoding.UTF8.GetBytes(data);
socketEventArg.SetBuffer(payload, 0, payload.Length);
Moon RTS

Avatar de l’utilisateur
ZJP
Messages : 5748
Inscription : 15 Déc 2009 06:00

Re: Optimisation sur lecture de Socket

Message par ZJP » 27 Jan 2015 23:25

menfou a écrit :a/
Merci pour tes réponses, mais comment tu fais pour envoyer un tableau a un socket ? ca demande un tableau de byte.

Je fais comme ca :
byte[] payload = Encoding.UTF8.GetBytes(data);
socketEventArg.SetBuffer(payload, 0, payload.Length);
C'est équivalent à cela en effet. La chaine (data) est transformée en tableau puis envoyée. float[] >> byte[]

zugsoft
Messages : 386
Inscription : 26 Juin 2014 23:43
Localisation : Swiss
Contact :

Re: Optimisation sur lecture de Socket

Message par zugsoft » 28 Jan 2015 12:15

Mon ancien code fonctionne très bien mis a part que meme un socket asynchrone bloque le Thread principal de Unity, j'ai du mettre mes 2 objets TCP et UDP dans 2 Threads séparés.
Je suis passé a 130bytes par joueur, soit 26kbytes pour 200 unités qui bougent en même temps sur mon rts.

Je vais faire une version de mon jeu de FPS avec 10 joueurs pour voir si j'obtiens un Ping de 60ms maxi.
Moon RTS

zugsoft
Messages : 386
Inscription : 26 Juin 2014 23:43
Localisation : Swiss
Contact :

Re: Optimisation sur lecture de Socket

Message par zugsoft » 28 Jan 2015 12:23

ZJP a écrit :
menfou a écrit :a/
Merci pour tes réponses, mais comment tu fais pour envoyer un tableau a un socket ? ca demande un tableau de byte.

Je fais comme ca :
byte[] payload = Encoding.UTF8.GetBytes(data);
socketEventArg.SetBuffer(payload, 0, payload.Length);
C'est équivalent à cela en effet. La chaine (data) est transformée en tableau puis envoyée. float[] >> byte[]
Mais coté serveur tu fais comment pour traiter ton tableau de bytes dans lequel tu as que des floats?
Moi j'ai un séparateur entre chaque valeur, je split et je recupere la position x,y,z....
Moon RTS

Avatar de l’utilisateur
ZJP
Messages : 5748
Inscription : 15 Déc 2009 06:00

Re: Optimisation sur lecture de Socket

Message par ZJP » 28 Jan 2015 17:49

Mon cas n'est pas directement applicable à ton processus vu que tout à été pensé dès le départ pour un échange de "float[]". De plus, j'utilise une libraire externe (TNET en ce moment, BOLT plus tard). Reste sur ta méthode et améliore là.

Cela dit, pour répondre à ta question...

zugsoft
Messages : 386
Inscription : 26 Juin 2014 23:43
Localisation : Swiss
Contact :

Re: Optimisation sur lecture de Socket

Message par zugsoft » 30 Jan 2015 09:22

J'ai codé mon serveur de Socket en C il y a plus d'un an, et je n'ai rien a redire, il fait bien son boulot :mrgreen:
Par contre, je me rends compte que c'est difficile a faire evoluer quand on a pas mis son nez dedans depuis un moment, je l'ai donc re-ecris en Java, et en terme de performance c'est pareil, une legere augmentation en memoire pour le Java.
La ou c'est interessant, c'est la simplicité du Java, j'ai pu améliorer en meme temps mon code et j'arrive parfois a 33ms en temps de reponse entre mon téléphone et mon serveur en UDP.
Je n'utilise que de l'UDP maintenant, meme pour les paquets super important ou je re-itere tant que j'ai pas un acquitement.
Moon RTS

Avatar de l’utilisateur
ZJP
Messages : 5748
Inscription : 15 Déc 2009 06:00

Re: Optimisation sur lecture de Socket

Message par ZJP » 30 Jan 2015 16:36

33ms. Jettes un œil dans ce cas au "zip/dézip" de tes données. Tu vas surement gagner du temps.

zugsoft
Messages : 386
Inscription : 26 Juin 2014 23:43
Localisation : Swiss
Contact :

Re: Optimisation sur lecture de Socket

Message par zugsoft » 11 Fév 2015 20:00

Salut,

Je ne vois comment il est possible de communiquer plus vite avec des données compactées en UDP entre mon telephone et mon serveur dedié, qu'un PING entre mon PC et mon serveur dédié.

Meme si je reste perplex sur le gain que va apporter un compactage de données, j'ai attaqué les modifications sur mon serveur et sur Unity.
J'ai donc mis en place gzip sur mon serveur et sur Unity, tout fonctionne bien sur PC, mais biensur Gzip ne fonctionne pas sur WindowsPhone car GzipStream n'existe pas dans Mono pour WindowsPhone :evil:

J'ai donc passé 3jours a developper un programme en C# basé sur l'algo de Huffman, et le meme programme en Java pour mon serveur, ainsi que des methodes de transformations binaire vers Bytes , Byte vers binaire.
Le paquet échangé passe de 660octets pour 8 joueurs a 400octets, par contre le temps de reponses est beaucoup moins stable et le temps CPU du telephone et du serveur sont en hausse.
Apres avoir simuler des centaines de joueurs, je m'apercois que le serveur passe trop de temps a compacter les données au détriment de répondre rapidement aux clients, je dois donc mettre en place le traitement du compactage par Thread pour chaque client.

Pour l'instant je n'ai donc pas vu d'améliorations sur le temps de réponse, mais plutot un temps de reponse moyen en hausse.
Le gros point positif c'est que j'ai beaucoup appris en 3 jours, et que ca peut etre tres utile par la suite pour crypter des données.

Je retourne coder mes Threads :mrgreen:
Moon RTS

Répondre

Revenir vers « Scripting »