[Java] Meten van socket transfersnelheid

Pagina: 1
Acties:

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Dag beste mede-tweakers,

Ik heb een component die dienst doet als een soort proxy: data van een InputStream inlezen en doorsluizen naar een andere outputstream. Nu zou ik graag meten hoeveel tijd het doorsturen van een file naar de client inneemt. Ik heb hiervoor het volgende stukje code geschreven:

code:
1
2
3
4
5
6
7
8
9
10
11
        // While more data -> forward data
        InputStream in = conn.getInputStream();
        OutputStream out = response.getOutputStream();
        
        byte buffer[] = new byte[1024];
        int len;
        startTime = System.currentTimeMillis();
        while ((len = in.read(buffer)) != -1)
            out.write(buffer, 0, len);
        out.close();
        stopTime = System.currentTimeMillis();


Dit werkt echter NIET . Het verschil tussen de start en stop tijd is meestal 0 ms ...
Enkel bij grotere bestanden krijg ik een zinnige timing. De meeste bestanden zijn echter klein.

Lang leve buffering en zo, maar hier wil ik dus echt de tijd weten tussen het versturen van het eerste datapakket en het ontvangen van de laatste ACK .
Is dit wel mogelijk in Java? Zo ja, hoe?

  • LAN
  • Registratie: Oktober 2000
  • Niet online

LAN

Wat is je opstelling? Zijn daar 2 pc's bij betrokken? Of doe je alles op 1 pc?

Hoe klein zijn die bestanden?
Wellicht gaat het zo snel dat meten in milliseconden weinig zin heeft, je kunt dan nog meten in nanoseconden (System.nanoTime() java 1.5 +).

Het hangt ook nog af van je platform in hoe kleine tijdseenheden je kunt meten. Er zit een aardig verschil in de resolutie tussen Windows, Linux, Solaris en Mac OSX.

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
2 PC's inderdaad. De bestanden zijn typische enkele KiB's .

Ik vermoed echter dat het feit dat er 0 ms gemeten wordt eerder komt omdat de echte doorstuurtijd niet gemeten wordt, maar dat de data gewoon in een buffer gesmeten wordt en dan in de achtergrond doorgestuurd wordt, en de write() call meteen returnt?
Sowieso moet de RTT toch minstens enkele tientallen ms zijn, de doorstuurtijd misschien iets minder, maar een resolutie van 1 ms zou toch voldoende moeten zijn?

  • Gerco
  • Registratie: Mei 2000
  • Laatst online: 16-11 19:52

Gerco

Professional Newbie

System.currentTimeMillis() heeft een resolutie van bijna 20ms (op Windows XP), probeer eens in nanoseconden te meten en kijk dan of je wat zinnigs terugkrijgt.

- "Als ik zou willen dat je het begreep, legde ik het wel beter uit!" | All number systems are base 10!


Verwijderd

DieterVDW schreef op vrijdag 06 juni 2008 @ 23:55:
2 PC's inderdaad. De bestanden zijn typische enkele KiB's .

Ik vermoed echter dat het feit dat er 0 ms gemeten wordt eerder komt omdat de echte doorstuurtijd niet gemeten wordt, maar dat de data gewoon in een buffer gesmeten wordt en dan in de achtergrond doorgestuurd wordt, en de write() call meteen returnt?
Sowieso moet de RTT toch minstens enkele tientallen ms zijn, de doorstuurtijd misschien iets minder, maar een resolutie van 1 ms zou toch voldoende moeten zijn?
Afhankelijk van het operating system en de versie daarvan waar de JVM op draait kan System.currentTimeMillis() een resolutie van rond de 50 milliseconden hebben (oude Win 9X versies). Op Windows XP is de resolutie meestal gelimiteerd tot ongeveer 16 miliseconden. Op Mac OS X en recente Linux kernels is de resolutie van currentTimeMillis() meestal rond één milliseconde.

Wat dit concreet betekent is dat op Windows XP de tijd die tussen twee currentTimeMillis() calls verstrijkt ten minste 16 ms dient te bedragen opdat je verschillende waarden van deze methode zou terugkrijgen.

Voor sommige applicaties is dit voldoende, maar om games te maken en voor networking op LAN-snelheden is een timer benodigd met een hogere granulariteit. Sinds JDK 1.5 is System.nanoTime() beschikbaar, die een verschil tussen twee calls in nanoseconden uitdrukt. Deze heeft op elke JVM implementatie die ik al ben tegengekomen een veel hogere resolutie. Je moet enkel niet vergeten te delen door 1000000.

Indien je geen Java 5 kan/mag/wil gebruiken, zul je je toevlucht moeten nemen tot third-party timers die via native code een meer accurate timer van het operating system aanroepen dan de timer van System.currentTimeMillis(). Java3D heeft zo'n timer, het Java Media Framework ook. Het is echter aan te raden om gewoon JDK 1.5 of beter te gebruiken.

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
No problem, we zitten al op JDK 1.6.

Ik veronderstel dat System.nanoTime() het probleem dan grotendeels zal oplossen.

Rest nog de vraag: hoe nauwkeurig is dit?
Klopt die tijd wel als ik voor en na de write() call meet?
Of meet ik hierbij toch alleen maar de tijd nodig om de data in de outgoing buffer te stoppen?

  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

Gooi wireshark op die PC en kijk naar de pakketjes op de netwerk IF

ASSUME makes an ASS out of U and ME

Pagina: 1