Java-Gaming.org Hi !
Featured games (91)
games approved by the League of Dukes
Games in Showcase (803)
Games in Android Showcase (237)
games submitted by our members
Games in WIP (867)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Kryonet sendToTCP/UDP Optimization?  (Read 4429 times)
0 Members and 1 Guest are viewing this topic.
Offline Iversonblc

Junior Devvie


Medals: 1
Exp: 3 years



« Posted 2014-12-09 07:05:20 »

I was looking at some of the code in https://github.com/EsotericSoftware/kryonet/blob/master/src/com/esotericsoftware/kryonet/Server.java and noticed the functions (which are seemingly called quite frequently) iterate through the entire list of connections.. in O(n) time instead of O(1) time by indexing with connectionID.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
public void sendToTCP (int connectionID, Object object) {
      Connection[] connections = this.connections;
      for (int i = 0, n = connections.length; i < n; i++) {
         Connection connection = connections[i];
         if (connection.id == connectionID) {
            connection.sendTCP(object);
            break;
         }
      }
}

public void sendToUDP (int connectionID, Object object) {
      Connection[] connections = this.connections;
      for (int i = 0, n = connections.length; i < n; i++) {
         Connection connection = connections[i];
         if (connection.id == connectionID) {
            connection.sendUDP(object);
            break;
         }
      }
}


Why is that?
Offline Andre Lopes
« Reply #1 - Posted 2014-12-09 13:57:59 »

I was looking at some of the code in https://github.com/EsotericSoftware/kryonet/blob/master/src/com/esotericsoftware/kryonet/Server.java and noticed the functions (which are seemingly called quite frequently) iterate through the entire list of connections.. in O(n) time instead of O(1) time by indexing with connectionID.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
public void sendToTCP (int connectionID, Object object) {
      Connection[] connections = this.connections;
      for (int i = 0, n = connections.length; i < n; i++) {
         Connection connection = connections[i];
         if (connection.id == connectionID) {
            connection.sendTCP(object);
            break;
         }
      }
}

public void sendToUDP (int connectionID, Object object) {
      Connection[] connections = this.connections;
      for (int i = 0, n = connections.length; i < n; i++) {
         Connection connection = connections[i];
         if (connection.id == connectionID) {
            connection.sendUDP(object);
            break;
         }
      }
}


Why is that?

I suppose that the ConnectionID could be changed or resetted by some other function?
If not, i guess it would be a good idea.

Better to investigate a bit further or wait someone with more experience on kryonet to reply.


+1 For noticing that
Offline trollwarrior1
« Reply #2 - Posted 2014-12-09 14:09:12 »

The only faster way would be to use a HashMap or an array (array is not really practical).

List was probably used for convenience in some other place of the code.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline basil_

« JGO Bitwise Duke »


Medals: 418
Exp: 13 years



« Reply #3 - Posted 2014-12-09 14:22:33 »

java.util.HashMap would be faster with lots of connections, but then still pretty slow.

i guess, they didn't bother to implement another int2object map and went the simple path.

Offline Nate

« JGO Bitwise Duke »


Medals: 167
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #4 - Posted 2014-12-09 16:20:24 »

How many loop iterations is enough to make one array lookup and one int comparison in each iteration slow enough to warrant using a map? Is that number greater than the number of connections your server might ever have?

Offline theagentd
« Reply #5 - Posted 2014-12-09 16:34:54 »

Is there a reason why send***() takes in the connection ID instead of a Connection object?

Myomyomyo.
Offline BurntPizza

« JGO Bitwise Duke »


Medals: 486
Exp: 7 years



« Reply #6 - Posted 2014-12-09 17:05:50 »

How many loop iterations is enough to make one array lookup and one int comparison in each iteration slow enough to warrant using a map? Is that number greater than the number of connections your server might ever have?

Quick and dirty JMH bench says about 20 assuming the average is that the item is found in the middle of the array:

size = 8
Benchmark              Mode  Samples    Score  Score error   Units
o.s.LoopBench.loop    thrpt       10  238.392        4.639  ops/us
o.s.LoopBench.map     thrpt       10  171.006        3.299  ops/us

size = 16
Benchmark              Mode  Samples    Score  Score error   Units
o.s.LoopBench.loop    thrpt       10  180.809        2.018  ops/us
o.s.LoopBench.map     thrpt       10  171.538        2.048  ops/us

size = 64
Benchmark              Mode  Samples    Score  Score error   Units
o.s.LoopBench.loop    thrpt       10   56.051        1.301  ops/us
o.s.LoopBench.map     thrpt       10  171.549        3.525  ops/us

size = 1024
Benchmark              Mode  Samples    Score  Score error   Units
o.s.LoopBench.loop    thrpt       10    4.067        0.088  ops/us
o.s.LoopBench.map     thrpt       10  170.738        2.863  ops/us


EDIT: correction, it turns out the map impl ramps up to ~230 to break even at about 10
EDIT2: this is also jdk8; jdk7 etc. hashmaps are a bit slower, but not much.
Offline ags1

JGO Kernel


Medals: 367
Projects: 7


Make code not war!


« Reply #7 - Posted 2014-12-09 17:18:46 »

I think with the delays inherent in networking, this kind of optimization will make no difference.

Offline theagentd
« Reply #8 - Posted 2014-12-09 18:09:39 »

I think with the delays inherent in networking, this kind of optimization will make no difference.
For a game server, it is relevant. The server may also be running other CPU intensive tasks, like game logic, physics, etc. It's a simple optimization with a noticeable improvement for larger game servers.

How many loop iterations is enough to make one array lookup and one int comparison in each iteration slow enough to warrant using a map? Is that number greater than the number of connections your server might ever have?

Quick and dirty JMH bench says about 20 assuming the average is that the item is found in the middle of the array:

size = 8
Benchmark              Mode  Samples    Score  Score error   Units
o.s.LoopBench.loop    thrpt       10  238.392        4.639  ops/us
o.s.LoopBench.map     thrpt       10  171.006        3.299  ops/us

size = 16
Benchmark              Mode  Samples    Score  Score error   Units
o.s.LoopBench.loop    thrpt       10  180.809        2.018  ops/us
o.s.LoopBench.map     thrpt       10  171.538        2.048  ops/us

size = 64
Benchmark              Mode  Samples    Score  Score error   Units
o.s.LoopBench.loop    thrpt       10   56.051        1.301  ops/us
o.s.LoopBench.map     thrpt       10  171.549        3.525  ops/us

size = 1024
Benchmark              Mode  Samples    Score  Score error   Units
o.s.LoopBench.loop    thrpt       10    4.067        0.088  ops/us
o.s.LoopBench.map     thrpt       10  170.738        2.863  ops/us

Again, why does the send method take in an ID instead of a raw Connection object? Connection doesn't seem to be some kind of internal object, as its returned by the listener and there's a getter to get all connections. If the only way to get a connection ID is to get it from a Connection object, what's the point? Just add an overloaded version of all those functions that take in a Connection object instead. The sender probably holds its Connection object anyway.

Myomyomyo.
Offline basil_

« JGO Bitwise Duke »


Medals: 418
Exp: 13 years



« Reply #9 - Posted 2014-12-09 19:07:36 »

thats why we have key-attachments. somebody was just lazy Smiley
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Nate

« JGO Bitwise Duke »


Medals: 167
Projects: 4
Exp: 14 years


Esoteric Software


« Reply #10 - Posted 2014-12-10 17:02:34 »

For a game server, it is relevant.
Premature optimization is premature. True it's a lib and it's nice to be as efficient as possible, but in reality the optimization is extremely unlikely to ever make a difference.

Pages: [1]
  ignore  |  Print  
 
 

 
Riven (397 views)
2019-09-04 15:33:17

hadezbladez (5280 views)
2018-11-16 13:46:03

hadezbladez (2204 views)
2018-11-16 13:41:33

hadezbladez (5544 views)
2018-11-16 13:35:35

hadezbladez (1150 views)
2018-11-16 13:32:03

EgonOlsen (4584 views)
2018-06-10 19:43:48

EgonOlsen (5462 views)
2018-06-10 19:43:44

EgonOlsen (3119 views)
2018-06-10 19:43:20

DesertCoockie (4015 views)
2018-05-13 18:23:11

nelsongames (4708 views)
2018-04-24 18:15:36
A NON-ideal modular configuration for Eclipse with JavaFX
by philfrei
2019-12-19 19:35:12

Java Gaming Resources
by philfrei
2019-05-14 16:15:13

Deployment and Packaging
by philfrei
2019-05-08 15:15:36

Deployment and Packaging
by philfrei
2019-05-08 15:13:34

Deployment and Packaging
by philfrei
2019-02-17 20:25:53

Deployment and Packaging
by mudlee
2018-08-22 18:09:50

Java Gaming Resources
by gouessej
2018-08-22 08:19:41

Deployment and Packaging
by gouessej
2018-08-22 08:04:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!