Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (475)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (530)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1] 2 3
  ignore  |  Print  
  Review my thread pattern?  (Read 8544 times)
0 Members and 1 Guest are viewing this topic.
Offline Conner_

Senior Newbie




~ Java Game Dev ~


« Posted 2011-09-05 20:22:20 »

I'm currently building an implementation of the Notchian Minecraft server and I wanted to run my thread pattern past you guys Tongue

1  
2  
3  
4  
5  
1. Entity updating thread pool, # of threads is number of processors; this loops through all connected entities and updates them...updates are placed in a queue every tick and emptied at the end, runs at 50ms
2. File I/O single thread, saves all world(s) and players to file, can be queued by the server GUI to execute an unexpected save, runs at 3 minutes
3. Server socket mgmt. single thread, selects all currently selectable channels and sends them to appropriate method: accept, read, or write, runs at 600ms
4. Server packet flow mgmt. single thread, grabs all upstream packet requests in its queue and processes them, followed by sending all downstream packets in the queue to appropriate clients, it does this by polling every Session object's instance for its queue, runs at 50ms
5. World update single thread, contributes to packet flow queue by consuming Task objects that can be converted into downstream packets, updates world time, runs at 50ms


Unfortunately, most threads must run at 50ms because that is how Minecraft is built to work (time has to be updated every 50ms, and there's no use in dedicating one thread to updating a long for the sake of not having two other threads run at the same tick). I would much prefer something like 10/20ms, because my machine is quite incredible and is comfortable with pretty much anything Smiley

I'm asking you guys to tell me what you think of this thread pattern for a game like Minecraft...will it encounter a problem, will it perform slowly, etc.

Thanks  Grin

Find me on GitHub: connergdavis
My current project is called Obsidian Framework and is a private Minecraft server application used to play Multiplayer.
Offline counterp

Senior Member


Medals: 11



« Reply #1 - Posted 2011-09-09 05:53:45 »

how does it make sense to multi thread the player updating but single thread your IO (reading/writing of packets, adding to queue, that part)

unless I misinterpreted
Offline Conner_

Senior Newbie




~ Java Game Dev ~


« Reply #2 - Posted 2011-09-09 17:04:20 »

how does it make sense to multi thread the player updating but single thread your IO (reading/writing of packets, adding to queue, that part)

unless I misinterpreted

I haven't had time to think about file I/O ops yet...now that I think about it, I don't think it would be that easy to execute a lot of I/O operations on one thread.

Looking at how I've mixed my pattern up a bit (I run using Netty networking framework now, so its threads are accounted for) I'm now looking at something like this (not including Netty) :

Entity updating ~ Number of threads equals number returned from Runtime#availableProcessors()
File I/O ~ Number of threads equals number returned from Runtime#availableProcessors() OR I might do that number / 2, depends on which works better
World updating ~ One thread per running world, this works fine because Minecraft servers often have multiple worlds running, and the amount of tasks executed here is small

On my beta MC server, I will be running one world for a while until I feel it necessary to test more than one, which means I'll be running 9 non-networking threads on my 2-core hyperthreading processor @ 2.93 GHz. If it can run a CraftBukkit server with 25 people just fine (~20% CPU) it can run mine Wink


ALSO

Not relevant to my current situation, but..

You said it would be bad for networking packet I/O, but I've seen (and talked to the people who've made) gaming servers that run Networking I/O operations on one thread each. As long as that thread is dedicated to a specific operation, and you do all you can to make it do as little as possible while still doing its job, you can easily get it done.

Find me on GitHub: connergdavis
My current project is called Obsidian Framework and is a private Minecraft server application used to play Multiplayer.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11


Game Engineer


« Reply #3 - Posted 2011-09-09 23:30:44 »

how does it make sense to multi thread the player updating but single thread your IO (reading/writing of packets, adding to queue, that part)

unless I misinterpreted
The disk can only do one thing at a time, multithrading IO doesn't make sense. At least as far as I know.

See my work:
OTC Software
Online Riven
« League of Dukes »

JGO Overlord


Medals: 742
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #4 - Posted 2011-09-10 00:12:49 »

It's even worse, if you're doing multi-threaded (heavy) file I/O on a HDD (mechanical seeks) you'll ruin your performance, you can easily lose factor 25x or so, when one file is near the center and the other is near the edge of a disk.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline theagentd
« Reply #5 - Posted 2011-09-10 10:55:35 »

It's even worse, if you're doing multi-threaded (heavy) file I/O on a HDD (mechanical seeks) you'll ruin your performance, you can easily lose factor 25x or so, when one file is near the center and the other is near the edge of a disk.
That doesn't sound right. If you multi-thread your file requests, you could improve performance many times on both mechanical HDs and SSDs. Sure, if you're just reading large files, reading 32 of them at the same time is gonna reduce performance on mechanical drive, but reading 32 4kb files at the same time may increase performance a lot due to how a mechanical hard drive reads files in the order they are encountered when seeking, not in the order they were requested. It all depends on the file size of the files you're reading. If you have many small files, multiple threads are going to have better performance.

Even if you are reading larger files, using 2 or more threads might be a good idea, as that might remove the HD - CPU sync that happens when reading:
CPU requests file -> CPU idles -> HD seeks and finds file -> HD sends file data to CPU -> HD idles -> CPU starts processing file...
It's the same reason you queue up OpenGL commands and not wait for a command to complete, right? I might be off on this last part...  Grin

Myomyomyo.
Online Riven
« League of Dukes »

JGO Overlord


Medals: 742
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #6 - Posted 2011-09-10 14:44:06 »

Nice theory, sadly it isn't true.

Just do a benchmark.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline theagentd
« Reply #7 - Posted 2011-09-10 16:38:33 »

From http://en.wikipedia.org/wiki/IOPS:
Quote
Some HDDs will improve in performance as the number of outstanding IO's (i.e. queue depth) increases. This is usually the result of more advanced controller logic on the drive performing command queuing and reordering commonly called either Tagged Command Queuing (TCQ) or Native Command Queuing (NCQ). Most commodity SATA drives either cannot do this, or their implementation is so poor that no performance benefit can be seen.[citation needed] Enterprise class SATA drives, such as the Western Digital Raptor and Seagate Barracuda NL will improve by nearly 100% with deep queues.[5] High-end SCSI drives more commonly found in servers, generally show much greater improvement, with the Seagate Savvio exceeding 400 IOPS—more than doubling its performance.[citation needed]

I don't really know what to make of it. Definitely need a benchmark. Sadly Tom's Hardware has only been doing SSD benchmarks for the last year. -.-

Myomyomyo.
Offline counterp

Senior Member


Medals: 11



« Reply #8 - Posted 2011-09-10 19:10:21 »

how does it make sense to multi thread the player updating but single thread your IO (reading/writing of packets, adding to queue, that part)

unless I misinterpreted
The disk can only do one thing at a time, multithrading IO doesn't make sense. At least as far as I know.

"reading/writing of packets, adding to queue, that part"

once again, it doesn't make sense to multithread game logic and single thread the packets reading/writing and adding to queue

should be the other way around

@Conner_

keep the file handler single threaded

and I'm not sure what you mean by "You said it would be bad for networking packet I/O"

do you mean I said it's bad to single thread it?

it is not as good to have single threaded as multithreaded, but you might not necessarily need to multithread since I don't think minecraft gets a lot of players per server anyways (Huh) i was mostly just pointing out that you had the concepts reversed. game logic should be single threaded, something like reading/writing from a network and adding to different queues can run in parallel
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11


Game Engineer


« Reply #9 - Posted 2011-09-10 19:20:42 »

Even for small files, it doesn't make sense to force the disk to seek all over the place when it can just write contiguous blocks of memory one after the other.

See my work:
OTC Software
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline counterp

Senior Member


Medals: 11



« Reply #10 - Posted 2011-09-10 19:39:06 »

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.CountDownLatch;


public class Main {

   public static final int count = 1000;
   public static final int fileSize = 65536;
   public static CountDownLatch latch;
   public static final Queue<byte[]> queue = new LinkedList<byte[]>();

   public static void main(String[] args) throws InterruptedException {
      Random random = new Random();
      for (int i = 0; i < count; i++) {
         byte[] data = new byte[fileSize];
         random.nextBytes(data);
         queue.add(data);
      }

      long start = System.nanoTime();
      test2();
      long end = System.nanoTime();
      System.out.println((end - start) / 1000000D);
   }

   public static final void test1() throws InterruptedException {
      latch = new CountDownLatch(2);
      new Worker().start();
      new Worker().start();
      latch.await();
   }

   public static final void test2() throws InterruptedException {
      latch = new CountDownLatch(1);
      new Worker().start();
      latch.await();
   }

   static class Worker extends Thread {

      @Override
      public void run() {
         int num = -1;
         byte[] data = null;
         while (true) {
            synchronized (queue) {
               if (queue.isEmpty()) {
                  latch.countDown();
                  break;
               }
               num = queue.size();
               data = queue.poll();
            }
            try {
               BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(String.valueOf(num)));
               out.write(data);
               out.close();
            } catch (IOException e) {
               e.printStackTrace();
            }
         }
      }

   }

}


run test 1 then run test 2 (separate instances of JVM).

EDIT: sometimes faster, sometimes slower, the fastest result of test 1 is faster than the fastest result of test 2
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11


Game Engineer


« Reply #11 - Posted 2011-09-10 20:12:31 »

If it's "sometimes faster, sometimes slower" that's generally a surefire sign that there is something wrong with the benchmark.  Undecided

See my work:
OTC Software
Offline counterp

Senior Member


Medals: 11



« Reply #12 - Posted 2011-09-10 20:51:14 »

depends on my current disk use, not my fault  Stare generally speaking though, if you take the fastest from each, in that case multi threaded was faster
Offline theagentd
« Reply #13 - Posted 2011-09-10 21:17:43 »

TheAgentD - Riven: 0.000001 - 0!!!! Marginal semi-unconfirmable victory! (I'm making up words! =D)

Myomyomyo.
Online Riven
« League of Dukes »

JGO Overlord


Medals: 742
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #14 - Posted 2011-09-10 22:03:59 »

I will provide a benchmark later (in a few days).

There is a lot that can go wrong in file-benchmarks, like the OS caching the files in RAM.

I'm mainly talking about large file I/O though, as with tiny files, you're moving the head in the HDD all over the place anyway.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline theagentd
« Reply #15 - Posted 2011-09-10 22:30:14 »

Yes, large files would indeed not benefit from multi-threading.
Just a small off topic question: Are you going to sue? http://na.leagueoflegends.com/news/new-champion-approaches-riven-exile

Myomyomyo.
Offline counterp

Senior Member


Medals: 11



« Reply #16 - Posted 2011-09-11 01:02:17 »

btw, overall it's probably better to have a single thread (just giving an example where multi threaded was -slightly- faster), and we don't know how big conner's files are
Offline Conner_

Senior Newbie




~ Java Game Dev ~


« Reply #17 - Posted 2011-09-13 03:30:57 »

Only things being written to or read from are Minecraft save files (small data region files and one ~2mb level save) and player saves. Player saves can't go above like 8kb, depends on the amount of items they have in their inventory.

Find me on GitHub: connergdavis
My current project is called Obsidian Framework and is a private Minecraft server application used to play Multiplayer.
Offline counterp

Senior Member


Medals: 11



« Reply #18 - Posted 2011-09-13 20:46:30 »

Now that I think about it, you will always have performance gain from multithreading your file i/o but the question is, is it necessary (probably not lol, unless you're constantly saving/loading files, like a huge webserver might do)

Even for small files, it doesn't make sense to force the disk to seek all over the place when it can just write contiguous blocks of memory one after the other.

reading from hdd is synchronous so that won't happen, requests to it are queued
Online Riven
« League of Dukes »

JGO Overlord


Medals: 742
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #19 - Posted 2011-09-13 21:45:16 »

Now that I think about it, you will always have performance gain from multithreading your file i/o

...

reading from hdd is synchronous so that won't happen, requests to it are queued

It doesn't matter how you 'reason' your way out, it's simply much faster to write large amounts of contiguous bytes, one file at a time.

A HDD doesn't work like your average I/O queue, where the throughput is constant. The more time the (mechanical) head is moving (due to seeking), the more throughput you lose.

If you write a big file, the head hardly moves.
If you write two a big files, the head moves back and forth on each write (lets assume every 4K).


Every seek takes about 5-10ms, which limits your seeks to 100-200 per second (IOPS).
100 * 4K = 400K / sec
200 * 4K = 800K / sec
This is worst-case scenario, mind you, but the more files you concurrently read/write, the more likely it becomes that you reach that dreadful performance.


This is also why copying a directory-structure with lots of tiny files has such horrible performance: every dozen reads are followed by a seek and the writes are also all over the place...

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline counterp

Senior Member


Medals: 11



« Reply #20 - Posted 2011-09-13 22:53:10 »

What the heck are you on about? What does multithreading file writing have to do with the hdd seeking? "It doesn't matter how you 'reason' your way out", the benchmark shows multithreaded is faster.
Offline Conner_

Senior Newbie




~ Java Game Dev ~


« Reply #21 - Posted 2011-09-14 00:40:53 »

Now that I think about it, you will always have performance gain from multithreading your file i/o

...

reading from hdd is synchronous so that won't happen, requests to it are queued

It doesn't matter how you 'reason' your way out, it's simply much faster to write large amounts of contiguous bytes, one file at a time.

A HDD doesn't work like your average I/O queue, where the throughput is constant. The more time the (mechanical) head is moving (due to seeking), the more throughput you lose.

If you write a big file, the head hardly moves.
If you write two a big files, the head moves back and forth on each write (lets assume every 4K).


Every seek takes about 5-10ms, which limits your seeks to 100-200 per second (IOPS).
100 * 4K = 400K / sec
200 * 4K = 800K / sec
This is worst-case scenario, mind you, but the more files you concurrently read/write, the more likely it becomes that you reach that dreadful performance.


This is also why copying a directory-structure with lots of tiny files has such horrible performance: every dozen reads are followed by a seek and the writes are also all over the place...

I think you're thinking too much into it Smiley If the benchmark says that dedicating more than one thread to file I/O operations executes an operation faster than on a single thread, it's fair to assume that you should probably dedicated more than one  Wink

Find me on GitHub: connergdavis
My current project is called Obsidian Framework and is a private Minecraft server application used to play Multiplayer.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11


Game Engineer


« Reply #22 - Posted 2011-09-14 00:44:50 »

What the heck are you on about? What does multithreading file writing have to do with the hdd seeking? "It doesn't matter how you 'reason' your way out", the benchmark shows multithreaded is faster.
Uh oh. You're going to be reamed. Sorry. Don't question Riven on technical knowledge. I've learned that lesson quite a few times.  Cry

See my work:
OTC Software
Offline counterp

Senior Member


Medals: 11



« Reply #23 - Posted 2011-09-14 01:42:52 »

What the heck are you on about? What does multithreading file writing have to do with the hdd seeking? "It doesn't matter how you 'reason' your way out", the benchmark shows multithreaded is faster.
Uh oh. You're going to be reamed. Sorry. Don't question Riven on technical knowledge. I've learned that lesson quite a few times.  Cry

I guess it's a good thing I'm right then, I don't wanna be reamed  persecutioncomplex

I think he's under the misconception that you can concurrently read things from a hdd (that would potentially be obscenely inefficient, because of the reasons he stated) in which case his theory would be correct.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11


Game Engineer


« Reply #24 - Posted 2011-09-14 05:01:43 »

What the heck are you on about? What does multithreading file writing have to do with the hdd seeking? "It doesn't matter how you 'reason' your way out", the benchmark shows multithreaded is faster.
Uh oh. You're going to be reamed. Sorry. Don't question Riven on technical knowledge. I've learned that lesson quite a few times.  Cry

I guess it's a good thing I'm right then, I don't wanna be reamed  persecutioncomplex

I think he's under the misconception that you can concurrently read things from a hdd (that would potentially be obscenely inefficient, because of the reasons he stated) in which case his theory would be correct.

I could see multi-threaded seeking being about the same speed as single-threaded, but I could never see it being faster.

See my work:
OTC Software
Offline counterp

Senior Member


Medals: 11



« Reply #25 - Posted 2011-09-14 05:04:33 »

Do you know what the difference is between requesting to write files from two threads is as opposed to requesting to write a file from one thread?

(the actual process that is happening after you send a request to write a file)

actually there is no difference, which is why you guys are wrong.

if anything the difference is, with multi threading you add 2 requests to the queue one after the other (potentially) and the first request is fulfilled then the second request is filled.

in single threading, you add one request to the queue, it is fulfilled, then you add the next request to the queue and it is fulfilled.

if externals application are hogging the hdd, then there should really be no speed difference (if they are, multithreaded will be faster, depending on what other applications are doing)

so in an ideal environment where only your application is using the hdd, in terms of file writing speed, there is no ~noticeable difference

the actual speed comes from other things not directly related to writing files (for example, things like creating FileOutputStream objects can be done concurrently)

this is the truth, this was supported by my benchmarks

i don't see why you keep holding on to the idea that when you multithread file writing, the disk is writing each file at the same time and therefore seeking a lot... that's not true. you only seek once per file
Online Riven
« League of Dukes »

JGO Overlord


Medals: 742
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #26 - Posted 2011-09-14 18:04:55 »

...
No, it's a question of physics and velocity. Hard drives are not flash memory, they have a spinning disk which revs up and if you seek in the opposite direction it must stop and spin the other way. Physics.
Hihi, HDDs have a constant speed. If you seek back, you simply have to wait for slightly less than a single revolution.


@counterp
You're hilariously misinformed. Why don't you read up on how harddisks actually work? Lots of interesting stuff.

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline sproingie

JGO Kernel


Medals: 201



« Reply #27 - Posted 2011-09-14 19:01:09 »

If you all think the operating system translates your InputStream reads directly into disk seeks, you need to brush up on the evolution of operating systems from the DOS days.  Modern operating systems have buffer caches and IO schedulers that go all the way down to understanding disk geometry.

The main problem with using threads willy nilly is the amount of memory they take up, since they each have to haul a stack along with them.  All the other claims being thrown around are meaningless unless they can be backed up with actual data.  Benchmarks aren't perfect, but I'll take them over anecdote any day.

Besides, if you want performance, you really should be using nio, and that's an async design that doesn't lend itself to thread-per-stream anyway.
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11


Game Engineer


« Reply #28 - Posted 2011-09-14 19:30:05 »

...
No, it's a question of physics and velocity. Hard drives are not flash memory, they have a spinning disk which revs up and if you seek in the opposite direction it must stop and spin the other way. Physics.
Hihi, HDDs have a constant speed. If you seek back, you simply have to wait for slightly less than a single revolution.


@counterp
You're hilariously misinformed. Why don't you read up on how harddisks actually work? Lots of interesting stuff.
Yes, I will stop talking now, because I'm getting caught in the trap of saying things I don't fully understand.

Gotta stop doing that.

See my work:
OTC Software
Offline counterp

Senior Member


Medals: 11



« Reply #29 - Posted 2011-09-14 21:26:56 »

@counterp
You're hilariously misinformed. Why don't you read up on how harddisks actually work? Lots of interesting stuff.

rofl, point out the part where I was wrong, please.
Pages: [1] 2 3
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

ctomni231 (34 views)
2014-07-18 06:55:21

Zero Volt (30 views)
2014-07-17 23:47:54

danieldean (25 views)
2014-07-17 23:41:23

MustardPeter (27 views)
2014-07-16 23:30:00

Cero (42 views)
2014-07-16 00:42:17

Riven (44 views)
2014-07-14 18:02:53

OpenGLShaders (33 views)
2014-07-14 16:23:47

Riven (34 views)
2014-07-14 11:51:35

quew8 (30 views)
2014-07-13 13:57:52

SHC (66 views)
2014-07-12 17:50:04
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
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!