-1

Since go is a concurrency program language and use channel(I use it almost all my code) or something else to synchronous goroutine.

And I also knew that go use a scheduler to schedule goroutine which means you should call scheduler(channel action, runtime.goSche or something else) in each goroutine and guarantee it would be executed.

Above is all my current limited on go and I use them to design my code.

But I also find it would occurred code blocking in my code. And it is hard to find where cause the block(even use GDB).

Was I miss something?

What else could possible cause the block?

And what things I should make attention?

[EDIT]: OK, since the code of my project is little big. I decide not show standard go code, just the general idea of the part that may possibly cause the code-blocking. Here are some code pieces of file transmit module in my project:

func(c *client)listenRead() {
    for {
        _ := websocket.JSON.Receive(c.ws, &package)
        switch package.Op {
        case fileUpld:
            c.fileMan.store <- package.Body
        case fileDownld:
            c.fileMan.downld <- package.Body
        case c.xxx:
            ...
        default:
            // bad package.
        }
    }
}

A client listening and receive message through websocket from another client and then forward the package according to package's Op field to different handler, e.g.,fileManager shows below.

func(fm *fileManager) fileRouter() {
    for {
        select {
            case fs := <-fm.fileUpld:
                if window < filesize {
                    f.Write(fs.content) // client A write to file
                    window += fs.contSize
                } else {
                    f.close()           // close file
                }
            case fd := fm.downld:
                go fm.downldFile(fd)
        }
    }
}

A fileManger can receive file pieces and store to server when the chan fileUpld get data that send from client. And it can download file when it receive the request from a client, and it will generate a goroutine to do the job, which shows below:

func(fm *fileManager) downldFile(fd) {
    f := getFile(fd)                     // get the file that client A write
    b := make([]byte, SeqLength)
    for {
        if convergence < window {
            f.Read(b)

            // wrap 'b' to package 'p', for send

            fm.server.send <- p   // send to client B
        } else if window < fileSize {
            runtime.Goshed()
        } else {
            // download done.
            fm.done <- xx
            return
        }
    }
}

The major idea of my file transmit module is client A want to send a file to client B, and don't want to wait for the acceptance from client B, which means it will store to server first and client B will get the file later by download from server. But it could be possible that client B download the file while client A uploading a file. So there needs a synchronous between upload and download.

I use three variable to implement this: window, convergence, filesize. When client A uploading(write) file, window will increase it's value that the bytes it writes. And when client B download(read) the file, convergence will increase the bytes that it reads. Write happens only window < filesize while read happens only convergence < window. Just like:

+-----------+---------------+--------------+
|############||||||||||||||||              |
+-----------+---------------+--------------+
            ^               ^              ^
            |               |              |
       convergence        window        filesize

I knew this would cause data-race, but it also guarantee that read won't read the content that write has not write yet.(BTW:I don't have a solution using channel to implement it.)

The code-blocking occurs when I try to upload and download the same time(I slow the client A to achieve it). But it have no problem when I set GOMAXPROCS to 2.

xsuii
  • 317
  • 4
  • 11
  • 2
    If you have a code sample that demonstrates the issue you're talking about, it will be much easier to understand what you're asking. If you can get the sample to run on play.golang.org, even better. – Tyler Oct 28 '13 at 01:01
  • 1
    @MatrixForg : I've re-edit and add the code sample. Hope it more clear to you. – xsuii Oct 29 '13 at 15:51

1 Answers1

0

You should consider a Garbage Collector that will pause your entire program, so called "stop the world". On large applications with big memory consumption GC could "stop the world" up to 10 seconds, but it's the worst case. Here is a nice answer about GC in Go: What kind of Garbage Collection does Go use?

Community
  • 1
  • 1
Kavu
  • 7,886
  • 3
  • 34
  • 39
  • Thanks for your answer, this is something new to me. But actually sometimes it would more longer than 10 seconds, and my application is not a larger one which may not cause by big memory consumption. I would like to know something structural consideration of the code. – xsuii Oct 27 '13 at 09:51