FAQ
I'm making a server for a game, and I currently have an array of entities
created on the main thread, looks like this
var entities = make(map[string]*Entity)
So my issue now is that I have to loop through every entity and call a
function called entity.update() which will do stuff like update their
health, energy, and position values. I'm also having to call a couple other
update functions which gets pretty laggy. Could I put these functions on
another goroutine? They aren't adding or removing elements from the array,
just editing the elements' values.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Roberto Zanotto at Apr 2, 2016 at 8:21 pm
    Just make sure that two different goroutines don't edit the same Entity at
    the same time.
    Run your code with "go run -race whatever.go" to enable the race detector.
    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com wrote:

    I'm making a server for a game, and I currently have an array of entities
    created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call a
    function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Zacharyholland at Apr 2, 2016 at 8:29 pm
    So what if one goroutine is editing the entities and one is just grabbing
    the data (to send to other players), would that be okay?

    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same Entity at
    the same time.
    Run your code with "go run -race whatever.go" to enable the race detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of entities
    created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call a
    function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Roberto Zanotto at Apr 2, 2016 at 11:00 pm
    It is not ok to read some memory location (grabbing the data) while another
    goroutine is writing to the same memory location (editing the entities).
    Also, it is not ok if two goroutines simultaneously write to the same
    memory location.
    These are called "data races" and are bad, because, for example, the result
    of reading some memory while another thread is modifying it
    is undefined.
    The race detector is a tool that detects this kind of bugs. You turn it on
    by doing go run, build or test with the -race flag.
    By the way, it is ok if multiple goroutines read from the same memory
    location, if no one is modifying the data.

    When using multiple goroutines you typically have two options:
    1) using shared data structures (your Entity map) and synchronize access
    with mutexes.
    2) avoid shared data structures and have the goroutines communicate with
    channels.
    Of course you can mix those things.

    Note that these are issues that arise in any language with multithreaded
    programming, not just Go.
    Go has been designed with concurrency in mind and has better tools than,
    for example, Java or C,
    but concurrent programming is not trivial and you should know what you are
    doing.
    Look for tutorials on the matter.

    In your case, it would be ok, for example, if you could split your set of
    entities in multiple subsets and
    assign each subset to a different goroutine. The goroutines would work in
    parallel, but each one would mind it's own business
    (not mess with data belonging to the others).
    On Saturday, April 2, 2016 at 10:29:24 PM UTC+2, zachary...@gmail.com wrote:

    So what if one goroutine is editing the entities and one is just grabbing
    the data (to send to other players), would that be okay?

    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same Entity
    at the same time.
    Run your code with "go run -race whatever.go" to enable the race detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of
    entities created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call a
    function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Zacharyholland at Apr 3, 2016 at 8:29 am
    I'm just recapping here to get stuff straight in my head. Right now the way
    I have it set up is that one goroutine loops through and updates the
    entities, possibly removing ones that should be removed. Another goroutine
    will just loop through and send it's data to other players. So the issues
    your pointing out are that it's editing the same memory at the same time.

    But how would I fix this?

    I tried using channels in the sense that I created a channel called funcChan
    var funcChan = make(chan func())
    And anything that edits the entities array I added to the channel
    funcChan <- sendData //loops through and sends each entity's data to every
    player
    and then in main I loop through the channel and call each function
    for (alive) {
    var my_recvd_value func()
    my_recvd_value = <- funcChan
    my_recvd_value()
    }
    But this basically makes using goroutines pointless if most of the stuff is
    just going to happen on the main thread.
    This is the only way I could think of using channels to solve this problem.
    Is there a better way to do this?

    I'm also not sure how I could implement something like your idea of having
    a goroutine manage certain sections of the entities array, because no
    matter what I do, I need at least one function that will loop through them
    all and send their data to all the players:(

    On Saturday, April 2, 2016 at 4:00:46 PM UTC-7, Roberto Zanotto wrote:

    It is not ok to read some memory location (grabbing the data) while
    another goroutine is writing to the same memory location (editing the
    entities).
    Also, it is not ok if two goroutines simultaneously write to the same
    memory location.
    These are called "data races" and are bad, because, for example, the
    result of reading some memory while another thread is modifying it
    is undefined.
    The race detector is a tool that detects this kind of bugs. You turn it on
    by doing go run, build or test with the -race flag.
    By the way, it is ok if multiple goroutines read from the same memory
    location, if no one is modifying the data.

    When using multiple goroutines you typically have two options:
    1) using shared data structures (your Entity map) and synchronize access
    with mutexes.
    2) avoid shared data structures and have the goroutines communicate with
    channels.
    Of course you can mix those things.

    Note that these are issues that arise in any language with multithreaded
    programming, not just Go.
    Go has been designed with concurrency in mind and has better tools than,
    for example, Java or C,
    but concurrent programming is not trivial and you should know what you are
    doing.
    Look for tutorials on the matter.

    In your case, it would be ok, for example, if you could split your set of
    entities in multiple subsets and
    assign each subset to a different goroutine. The goroutines would work in
    parallel, but each one would mind it's own business
    (not mess with data belonging to the others).

    On Saturday, April 2, 2016 at 10:29:24 PM UTC+2, zachary...@gmail.com
    wrote:
    So what if one goroutine is editing the entities and one is just grabbing
    the data (to send to other players), would that be okay?

    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same Entity
    at the same time.
    Run your code with "go run -race whatever.go" to enable the race
    detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of
    entities created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call a
    function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Bakul Shah at Apr 3, 2016 at 9:31 am

    On Sun, 03 Apr 2016 01:29:35 PDT zacharyholland@gmail.com wrote:

    I'm just recapping here to get stuff straight in my head. Right now the way
    I have it set up is that one goroutine loops through and updates the
    entities, possibly removing ones that should be removed. Another goroutine
    will just loop through and send it's data to other players. So the issues
    your pointing out are that it's editing the same memory at the same time.

    But how would I fix this?

    I tried using channels in the sense that I created a channel called funcChan
    var funcChan = make(chan func())
    And anything that edits the entities array I added to the channel
    funcChan <- sendData //loops through and sends each entity's data to every
    player
    and then in main I loop through the channel and call each function
    for (alive) {
    var my_recvd_value func()
    my_recvd_value = <- funcChan
    my_recvd_value()
    }
    But this basically makes using goroutines pointless if most of the stuff is
    just going to happen on the main thread.
    This is the only way I could think of using channels to solve this problem.
    Is there a better way to do this?

    I'm also not sure how I could implement something like your idea of having
    a goroutine manage certain sections of the entities array, because no
    matter what I do, I need at least one function that will loop through them
    all and send their data to all the players:(
    Can't you use something like the following?

    // pull off an entity from the in chan, process it and push it on the out chan
    func update(in, out chan *Entity) {
      for {
       e := <- in
       e.update()
       out <- e
      }
    }

    func updateAll(out, in chan* Entity, entities map[string]*Entity) {
      for _, e := range entities {
       out <- e
      }
      // wait till equal number of items are received
      for i := len(entities); i > 0; i-- {
       <- in
      }
    }

    func main() {
      ...
      in := make(chan *Entity, 100)
      out := make(chan *Entity, 100)

      // start up a few update goroutines
      for i := 0; i < N; i++ {
       go update(in, out)
      }

      // example: update all entities every 100ms
      ticker := time.Tick(100 * time.Millsecond)
      for now := range ticker {
       updateAll(in, out, entities)
      }
    }

    Multiple goroutines read from the in chan but only one
    goroutine will get an entity to work on. The key point is to
    have only one goroutine access/update an entity at any given
    point in time. You can achieve this using mutexes or channels.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Zacharyholland at Apr 3, 2016 at 7:25 pm
    Wow thank you so much for this sample code it's super helpful!! I'm trying
    to understand it and this part is confusing me...
      for i := len(entities); i > 0; i-- {
              <- in
      }
    What exactly does <-in do? I thought that popped out an object from the
    channel, but it looks like you are popping an object but not doing anything
    with it?

    On Sunday, April 3, 2016 at 2:31:58 AM UTC-7, Bakul Shah wrote:

    On Sun, 03 Apr 2016 01:29:35 PDT zachary...@gmail.com <javascript:>
    wrote:
    I'm just recapping here to get stuff straight in my head. Right now the way
    I have it set up is that one goroutine loops through and updates the
    entities, possibly removing ones that should be removed. Another goroutine
    will just loop through and send it's data to other players. So the issues
    your pointing out are that it's editing the same memory at the same time.
    But how would I fix this?

    I tried using channels in the sense that I created a channel called funcChan
    var funcChan = make(chan func())
    And anything that edits the entities array I added to the channel
    funcChan <- sendData //loops through and sends each entity's data to every
    player
    and then in main I loop through the channel and call each function
    for (alive) {
    var my_recvd_value func()
    my_recvd_value = <- funcChan
    my_recvd_value()
    }
    But this basically makes using goroutines pointless if most of the stuff is
    just going to happen on the main thread.
    This is the only way I could think of using channels to solve this problem.
    Is there a better way to do this?

    I'm also not sure how I could implement something like your idea of having
    a goroutine manage certain sections of the entities array, because no
    matter what I do, I need at least one function that will loop through them
    all and send their data to all the players:(
    Can't you use something like the following?

    // pull off an entity from the in chan, process it and push it on the out
    chan
    func update(in, out chan *Entity) {
    for {
    e := <- in
    e.update()
    out <- e
    }
    }

    func updateAll(out, in chan* Entity, entities map[string]*Entity) {
    for _, e := range entities {
    out <- e
    }
    // wait till equal number of items are received
    for i := len(entities); i > 0; i-- {
    <- in
    }
    }

    func main() {
    ...
    in := make(chan *Entity, 100)
    out := make(chan *Entity, 100)

    // start up a few update goroutines
    for i := 0; i < N; i++ {
    go update(in, out)
    }

    // example: update all entities every 100ms
    ticker := time.Tick(100 * time.Millsecond)
    for now := range ticker {
    updateAll(in, out, entities)
    }
    }

    Multiple goroutines read from the in chan but only one
    goroutine will get an entity to work on. The key point is to
    have only one goroutine access/update an entity at any given
    point in time. You can achieve this using mutexes or channels.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Bakul Shah at Apr 3, 2016 at 8:32 pm

    On Sun, 03 Apr 2016 12:25:03 PDT zacharyholland@gmail.com wrote:

    Wow thank you so much for this sample code it's super helpful!! I'm trying
    to understand it and this part is confusing me...
    for i := len(entities); i > 0; i-- {
    <- in
    }
    What exactly does <-in do? I thought that popped out an object from the
    channel, but it looks like you are popping an object but not doing anything
    with it?
    updateAll just wants to check that all the entities were
    processed so the actual received value is not useful and
    thrown away. This is just some sample code to give you an
    idea.

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Tim K at Apr 3, 2016 at 12:47 am
    This is a good article to go through, though it may feel a bit scientific:
    https://golang.org/ref/mem

    Pay particular attention to "Happens Before", that is the key to
    understanding data races.

    On Saturday, April 2, 2016 at 1:29:24 PM UTC-7, zachary...@gmail.com wrote:

    So what if one goroutine is editing the entities and one is just grabbing
    the data (to send to other players), would that be okay?

    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same Entity
    at the same time.
    Run your code with "go run -race whatever.go" to enable the race detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of
    entities created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call a
    function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Sugu Sougoumarane at Apr 3, 2016 at 1:05 am
    Performing CPU-bound operations typically happens in 10s of nanoseconds,
    maybe 100s. This means that you can perform something like 10M operations
    in 1s.
    OTOH, trying to prove that your lock-free program is not racy can get very
    difficult, probably unmaintainable over time.

    Are you trying to update memory at this scale, or is something else in your
    code time-consuming?

    If it's the former (you're truly CPU-bound), I'd recommend adding a mutex
    to Entity and using that to update members.
    For the latter, you should have a single lock for the entire map, perform
    your slow computation first, and obtain the global lock just for setting
    the necessary values.

    On Saturday, April 2, 2016 at 5:47:14 PM UTC-7, Tim K wrote:

    This is a good article to go through, though it may feel a bit scientific:
    https://golang.org/ref/mem

    Pay particular attention to "Happens Before", that is the key to
    understanding data races.


    On Saturday, April 2, 2016 at 1:29:24 PM UTC-7, zachary...@gmail.com
    wrote:
    So what if one goroutine is editing the entities and one is just grabbing
    the data (to send to other players), would that be okay?

    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same Entity
    at the same time.
    Run your code with "go run -race whatever.go" to enable the race
    detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of
    entities created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call a
    function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Zacharyholland at Apr 3, 2016 at 8:38 am
    I think everything just adds up. At first everything was on goroutines
    which was fast but crashed a ton because I don't know how to sync
    everything. When I started adding functions back onto the main thread (via
    the channel method I posted earlier) it slowed down a bit when I added the
    "send" and "update" functions (which both loop through all the entities,
    updating and sending info), and then slowed down a ton when I added the
    physics ticker onto the main thread (which just calls physics.step) So I
    guess the physics ticker takes the most amount of time to be called.
    On Saturday, April 2, 2016 at 6:05:30 PM UTC-7, Sugu Sougoumarane wrote:

    Performing CPU-bound operations typically happens in 10s of nanoseconds,
    maybe 100s. This means that you can perform something like 10M operations
    in 1s.
    OTOH, trying to prove that your lock-free program is not racy can get very
    difficult, probably unmaintainable over time.

    Are you trying to update memory at this scale, or is something else in
    your code time-consuming?

    If it's the former (you're truly CPU-bound), I'd recommend adding a mutex
    to Entity and using that to update members.
    For the latter, you should have a single lock for the entire map, perform
    your slow computation first, and obtain the global lock just for setting
    the necessary values.

    On Saturday, April 2, 2016 at 5:47:14 PM UTC-7, Tim K wrote:

    This is a good article to go through, though it may feel a bit scientific:
    https://golang.org/ref/mem

    Pay particular attention to "Happens Before", that is the key to
    understanding data races.


    On Saturday, April 2, 2016 at 1:29:24 PM UTC-7, zachary...@gmail.com
    wrote:
    So what if one goroutine is editing the entities and one is just
    grabbing the data (to send to other players), would that be okay?

    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same Entity
    at the same time.
    Run your code with "go run -race whatever.go" to enable the race
    detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of
    entities created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call a
    function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Roberto Zanotto at Apr 3, 2016 at 11:56 am
    It's already a good thing if you identified the bottleneck. Do you
    implement your own physics or are you using a dedicated library?
    On Sunday, April 3, 2016 at 10:38:26 AM UTC+2, zachary...@gmail.com wrote:

    I think everything just adds up. At first everything was on goroutines
    which was fast but crashed a ton because I don't know how to sync
    everything. When I started adding functions back onto the main thread (via
    the channel method I posted earlier) it slowed down a bit when I added the
    "send" and "update" functions (which both loop through all the entities,
    updating and sending info), and then slowed down a ton when I added the
    physics ticker onto the main thread (which just calls physics.step) So I
    guess the physics ticker takes the most amount of time to be called.
    On Saturday, April 2, 2016 at 6:05:30 PM UTC-7, Sugu Sougoumarane wrote:

    Performing CPU-bound operations typically happens in 10s of nanoseconds,
    maybe 100s. This means that you can perform something like 10M operations
    in 1s.
    OTOH, trying to prove that your lock-free program is not racy can get
    very difficult, probably unmaintainable over time.

    Are you trying to update memory at this scale, or is something else in
    your code time-consuming?

    If it's the former (you're truly CPU-bound), I'd recommend adding a mutex
    to Entity and using that to update members.
    For the latter, you should have a single lock for the entire map, perform
    your slow computation first, and obtain the global lock just for setting
    the necessary values.

    On Saturday, April 2, 2016 at 5:47:14 PM UTC-7, Tim K wrote:

    This is a good article to go through, though it may feel a bit
    scientific:
    https://golang.org/ref/mem

    Pay particular attention to "Happens Before", that is the key to
    understanding data races.


    On Saturday, April 2, 2016 at 1:29:24 PM UTC-7, zachary...@gmail.com
    wrote:
    So what if one goroutine is editing the entities and one is just
    grabbing the data (to send to other players), would that be okay?

    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same
    Entity at the same time.
    Run your code with "go run -race whatever.go" to enable the race
    detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of
    entities created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call
    a function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Zacharyholland at Apr 3, 2016 at 7:16 pm
    I'm using Vova616's Chipmunk port <https://github.com/vova616/chipmunk>
    On Sunday, April 3, 2016 at 4:56:49 AM UTC-7, Roberto Zanotto wrote:

    It's already a good thing if you identified the bottleneck. Do you
    implement your own physics or are you using a dedicated library?
    On Sunday, April 3, 2016 at 10:38:26 AM UTC+2, zachary...@gmail.com wrote:

    I think everything just adds up. At first everything was on goroutines
    which was fast but crashed a ton because I don't know how to sync
    everything. When I started adding functions back onto the main thread (via
    the channel method I posted earlier) it slowed down a bit when I added the
    "send" and "update" functions (which both loop through all the entities,
    updating and sending info), and then slowed down a ton when I added the
    physics ticker onto the main thread (which just calls physics.step) So I
    guess the physics ticker takes the most amount of time to be called.
    On Saturday, April 2, 2016 at 6:05:30 PM UTC-7, Sugu Sougoumarane wrote:

    Performing CPU-bound operations typically happens in 10s of nanoseconds,
    maybe 100s. This means that you can perform something like 10M operations
    in 1s.
    OTOH, trying to prove that your lock-free program is not racy can get
    very difficult, probably unmaintainable over time.

    Are you trying to update memory at this scale, or is something else in
    your code time-consuming?

    If it's the former (you're truly CPU-bound), I'd recommend adding a
    mutex to Entity and using that to update members.
    For the latter, you should have a single lock for the entire map,
    perform your slow computation first, and obtain the global lock just for
    setting the necessary values.

    On Saturday, April 2, 2016 at 5:47:14 PM UTC-7, Tim K wrote:

    This is a good article to go through, though it may feel a bit
    scientific:
    https://golang.org/ref/mem

    Pay particular attention to "Happens Before", that is the key to
    understanding data races.


    On Saturday, April 2, 2016 at 1:29:24 PM UTC-7, zachary...@gmail.com
    wrote:
    So what if one goroutine is editing the entities and one is just
    grabbing the data (to send to other players), would that be okay?

    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same
    Entity at the same time.
    Run your code with "go run -race whatever.go" to enable the race
    detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of
    entities created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call
    a function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Roberto Zanotto at Apr 4, 2016 at 6:48 am
    The physics step needs to read and update all entities at once I suppose,
    so either chipmunk gives you some way of parallelizing the work, or there's
    noting you can do about it.

    About the "update" function, it depends on what you are doing there. Does
    each entity have to interact with every other? Are you using an n^2
    algorithm?

    About the "send" function, it should be possible to parallelize it easily.
    I mean, _after_ the data has been updated, you can have as many goroutines
    as you want reading the data concurrently and sending it over the network.

    Also, it may help to use a map[string]Entity instead of a
    map[string]*Entity, or even a plain array, so that the memory you are
    working on is contiguous and you pay less cache faults.
    If you want performance, go for a data-oriented design instead of an
    object-oriented design.
    See, for example, https://www.youtube.com/watch?v=rX0ItVEVjHc
    On Sunday, April 3, 2016 at 10:38:26 AM UTC+2, Zac Diericx wrote:

    I think everything just adds up. At first everything was on goroutines
    which was fast but crashed a ton because I don't know how to sync
    everything. When I started adding functions back onto the main thread (via
    the channel method I posted earlier) it slowed down a bit when I added the
    "send" and "update" functions (which both loop through all the entities,
    updating and sending info), and then slowed down a ton when I added the
    physics ticker onto the main thread (which just calls physics.step) So I
    guess the physics ticker takes the most amount of time to be called.
    On Saturday, April 2, 2016 at 6:05:30 PM UTC-7, Sugu Sougoumarane wrote:

    Performing CPU-bound operations typically happens in 10s of nanoseconds,
    maybe 100s. This means that you can perform something like 10M operations
    in 1s.
    OTOH, trying to prove that your lock-free program is not racy can get
    very difficult, probably unmaintainable over time.

    Are you trying to update memory at this scale, or is something else in
    your code time-consuming?

    If it's the former (you're truly CPU-bound), I'd recommend adding a mutex
    to Entity and using that to update members.
    For the latter, you should have a single lock for the entire map, perform
    your slow computation first, and obtain the global lock just for setting
    the necessary values.

    On Saturday, April 2, 2016 at 5:47:14 PM UTC-7, Tim K wrote:

    This is a good article to go through, though it may feel a bit
    scientific:
    https://golang.org/ref/mem

    Pay particular attention to "Happens Before", that is the key to
    understanding data races.


    On Saturday, April 2, 2016 at 1:29:24 PM UTC-7, zachary...@gmail.com
    wrote:
    So what if one goroutine is editing the entities and one is just
    grabbing the data (to send to other players), would that be okay?

    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same
    Entity at the same time.
    Run your code with "go run -race whatever.go" to enable the race
    detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of
    entities created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call
    a function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Zac Diericx at Apr 6, 2016 at 11:08 pm
    Alright I think I figured out the problem, thanks to everyone's help her!!
    Here is my model now:
    var playerInput = make(chan PlayerDataObject, 100)
    var serverOutput = make(chan PlayerDataObject, 100)
    var entityIn = make(chan *Entity, 100)
    var entityOut = make(chan *Entity, 100)

    for {
    processServerInput() //loops through player input channel and processes info
    physics.stepPhysics() //steps the physics
    updateEntities() //loops through entityIn/Out channels processing entities
    using Bakul Shah's method
    processServerOutput() //creates all of the packets and puts them in the
    server output channel
    sendServerOutput() //sends all of the server output
    }

    This way everything happens in order and the slices aren't every being
    accessed simultaneously:)

    On Sunday, April 3, 2016 at 11:48:39 PM UTC-7, Roberto Zanotto wrote:

    The physics step needs to read and update all entities at once I suppose,
    so either chipmunk gives you some way of parallelizing the work, or there's
    noting you can do about it.

    About the "update" function, it depends on what you are doing there. Does
    each entity have to interact with every other? Are you using an n^2
    algorithm?

    About the "send" function, it should be possible to parallelize it easily.
    I mean, _after_ the data has been updated, you can have as many goroutines
    as you want reading the data concurrently and sending it over the network.

    Also, it may help to use a map[string]Entity instead of a
    map[string]*Entity, or even a plain array, so that the memory you are
    working on is contiguous and you pay less cache faults.
    If you want performance, go for a data-oriented design instead of an
    object-oriented design.
    See, for example, https://www.youtube.com/watch?v=rX0ItVEVjHc
    On Sunday, April 3, 2016 at 10:38:26 AM UTC+2, Zac Diericx wrote:

    I think everything just adds up. At first everything was on goroutines
    which was fast but crashed a ton because I don't know how to sync
    everything. When I started adding functions back onto the main thread (via
    the channel method I posted earlier) it slowed down a bit when I added the
    "send" and "update" functions (which both loop through all the entities,
    updating and sending info), and then slowed down a ton when I added the
    physics ticker onto the main thread (which just calls physics.step) So I
    guess the physics ticker takes the most amount of time to be called.
    On Saturday, April 2, 2016 at 6:05:30 PM UTC-7, Sugu Sougoumarane wrote:

    Performing CPU-bound operations typically happens in 10s of nanoseconds,
    maybe 100s. This means that you can perform something like 10M operations
    in 1s.
    OTOH, trying to prove that your lock-free program is not racy can get
    very difficult, probably unmaintainable over time.

    Are you trying to update memory at this scale, or is something else in
    your code time-consuming?

    If it's the former (you're truly CPU-bound), I'd recommend adding a
    mutex to Entity and using that to update members.
    For the latter, you should have a single lock for the entire map,
    perform your slow computation first, and obtain the global lock just for
    setting the necessary values.

    On Saturday, April 2, 2016 at 5:47:14 PM UTC-7, Tim K wrote:

    This is a good article to go through, though it may feel a bit
    scientific:
    https://golang.org/ref/mem

    Pay particular attention to "Happens Before", that is the key to
    understanding data races.


    On Saturday, April 2, 2016 at 1:29:24 PM UTC-7, zachary...@gmail.com
    wrote:
    So what if one goroutine is editing the entities and one is just
    grabbing the data (to send to other players), would that be okay?

    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same
    Entity at the same time.
    Run your code with "go run -race whatever.go" to enable the race
    detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of
    entities created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call
    a function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Andreas Nilsson at Apr 6, 2016 at 9:28 pm
    Just wanted to add that you could do that, using a sync.RWMutex to protect
    the data; or even using atomic ops. But I'd save that as a last resort.
    Sharing data between threads is always a last resort and Golang has
    excellent tools to cut problems other ways. It's not always obvious how
    though. What generally works best for me is moulding these kinds of
    problems into jobs and stuffing jobs into channels/work queues, possibly
    with a feedback loop to know when the job is finished. That way you can at
    least get a guarantee that no two threads start working on the same job, no
    matter how many queue processors you add. Using that fact to your advantage
    and selecting the most suitable jobs to maximize concurrency is more art
    than science. Good luck.

    Den lördag 2 april 2016 kl. 22:29:24 UTC+2 skrev Zac Diericx:
    So what if one goroutine is editing the entities and one is just grabbing
    the data (to send to other players), would that be okay?
    th
    And what is the race detector?
    On Saturday, April 2, 2016 at 1:20:59 PM UTC-7, Roberto Zanotto wrote:

    Just make sure that two different goroutines don't edit the same Entity
    at the same time.
    Run your code with "go run -race whatever.go" to enable the race detector.

    On Saturday, April 2, 2016 at 10:11:14 PM UTC+2, zachary...@gmail.com
    wrote:
    I'm making a server for a game, and I currently have an array of
    entities created on the main thread, looks like this
    var entities = make(map[string]*Entity)
    So my issue now is that I have to loop through every entity and call a
    function called entity.update() which will do stuff like update their
    health, energy, and position values. I'm also having to call a couple other
    update functions which gets pretty laggy. Could I put these functions on
    another goroutine? They aren't adding or removing elements from the array,
    just editing the elements' values.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedApr 2, '16 at 8:10p
activeApr 6, '16 at 11:08p
posts16
users6
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase