Skip to content

Instantly share code, notes, and snippets.

@carlisia
Created October 30, 2015 18:15
Show Gist options
  • Save carlisia/b89aab5401b178753467 to your computer and use it in GitHub Desktop.
Save carlisia/b89aab5401b178753467 to your computer and use it in GitHub Desktop.
William Kennedy at SD Gophers October Meetup - Transcript by @francismakes
The MIT License (MIT)
Copyright (c) 2015 Francis Batac
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

william-kennedy.md

At the end of the day, how many of you have done multi-threaed programming before? Java? I don't care for Java. Alright cool. Let's talk about what I think concurrency really is. It took me al ong time to understand this. It took me about three years. There's something that Russ Cox wrote one time. Concurrency is about managing alot of things at once; parallelism is easy to understand... you're already running different paths t the same time and it's easy to think about. But when you think about managing things at once, what does that really mean? It took me along time to figure that out... now the essence of concurrency in go is to build GoRoutines and channels.

What is a GoRoutine...

we call using the keyword go.

It gets scheduled to run independeny of the code running in the systems. Prior to 1.5

What's the idea here? The single logical processor?

We think about concurrency ... whow does the operating system work?

You can run stop and run... t happens in the kernel. there is a cost to this, isn't there?

EVeryitime a thread has to be swapped, what is the cost? context switching!

We've learned really quickly from a multi-threading tandpoint that to have more cores than active makes the operating system do more. If we're doing multithreaded concurrecny... let's not have any more active threads than necessary at any given time, but let's keep it simple.

The idea is that we run one thread per core.

What does Go say?

=> Leverage the operating system, but manage the concurrency a ltitle better.

Let's set it up to be like this.

Let's take our functions and methods and turn them into GoRoutines. And we'll make sure that they run independent.

These GoRoutines and the path of execution now is to be scheduled on this one thread. LEt's keep this thread so busy that the OS has very little need to keep swapping it on and off and let's leverage all the time we can get.

Go operates on User Mode, as a pre-emptive scheduler.

What the scheduler does in User mode... says the following

go routine makes a system call make sawap channel operation, op to swap garvage collection: op to swap

two go routines playing ping pong sending things back and forth

I've got one thread that's running both GoRoutines. Run more of our code at the same amount of time. Go Scheduler is brillaint! Let's maximize the use of this one thread and we'll manage in user mode for when they switch in passive mode and execution. If we're the core thing on this OS, we're going to get serviced.

moving on from the Scheduler level...

we have to deal with the issues of multi-threaded programming.

How many of you have used atomic functions? Fastest synchronization concept that we have.

Performance matters.

With Go, we can write clean code and readable code.

Not being clever.

We don't really focus on performance until we're ready to, but performance matters.

What's the next level of sync? Mutex.

Slower than atomic functions but if we have multiple statements that have to be serialized, we have to do it!

I've seen way too much code that's over-engineered with channels!

Lots more of mutexes and atomic functions than channels. Channel is just another tool.

I only use channels if I can think of people as a workflow.

If I cannot think of channels as a person, then I don't use it at all.

Let's go back to this idea of managing concurrency.

I think alot of people miss the boat on managing concurrency thing.

There's two types of channels: unbuffered and buffered channels.

If someone uses buffered channels, there's only extreme cases for where it's okay. Beyond that you should be using unbuffered channels for everything. When I see literal numbers, I ask questions. What does it mean???

Unbufferred channels: Look at this synchronous typed queue!~ Then I wrote alot of codeabout this idea being a queue.

When there's a queue, you're doing something wrong.

The code I was writing got very complex very quickly.

I'm doing something wrong but I had no idea what it was.

I reached out to the community and I got my answer: I'm thinking about the channel as a queue. Channel IS NOT A QUEUE! GET THAT OUT OF YOUR HEAD IMMEDIATELY. THEY PROVIDE A GUARANTEE OF AN EXCHANGE OF REPSPONSIBILITY. THAT IS WHAT THEY PROVIDE.

Unbuffered channel works like this: I have this piece of data and I bring it over here. I want to give it to him! This is not IO. We send and receive on channels! I got this piece of data and now I am stuck. Why? Because unbuffered channels provide 100% guarantee that a piece of data has moved!

Now we're stuck right here. Now after that, we can now move on!

Who was responsible? I was. Now, he is! Now, I'm stuck. I cannot move. I have to pull it out of your hand because receive happens first. The levels of responsibility have changed between me to him..

Story.

Freely Italian wife...

Priority Inheritance

Children > Family > Cats > Dog > Bill

Bill this has to get to Ed's wife. Ed's wife gets THIS envelope tonight. She iterates: Bill, this letter, ahs to get to Ed's wife. Really? Like seriously? just give me the letter and I'll make it happen. I put it in my bag and I go to work. I left without it (forget). 5:00PM hits: don't forget Tom has baseball practice. Now I'm starting to panic. If I don't leave, then I will be in the dog house. I'm starting to panic. I pack everything up and what do I see? Now I see the letter. I'm double panicking. Ed's wife is now getting this letter. But baseball! I run over to Ed's desk and his laptop is there but Ed has.... left the office? But I'm looking at my watch but Ed is prorbably back. We all get there on time. Did Tom make it to practice on time? Did you give Ed the letter? Wife gives him a kiss, life is good....

BUT HERE'S THE PROBLEM:

My wife comes over to me, pissed off. She's ready to hit me. But if she had a spoon in her hand, she would've beat me clean. His wife argues with William Kennedy. Now I have to defend himself. He busts out of the house, because what am I going to do? I'm scared actually... But I have to be macho. So I get out of the house and I'm really panicking now and I call Ed... and Ed says, what letter?

I love this story because it describes the best detail I can, what a buffered channel is.

#INFORMATIONLOSS #TROUBLE #NOMOREBUFFEREDCHANNELS #GUARANTEEORPERFMAKEACHOICE

Buffered channel provide risk. Unbuffered chanel provide guarantee.

Management rules

  1. Know EVERY goroutine that is running
  2. Manage back pressure at all times. Every channel operation that you add to your code: what happens if the sender to that blocks receive?
  3. Timeouts: no goroutine is allowed to live forever. It has a certain amount of time to do its thing, and that's it. There is no network call that doesn't provide you with a timeout option.

There is a timeout option! You must set them appropriately. I have much more than 10000 goroutines trying to acceess requests and the time is getting slower and slower... before I know it the systems implodes. Now imagine I set a timeout. I set a timeout.

No request is allowed to take more than 800ms.

Clients are getting messages: we have a problem.

Still have 10K....

where is this latency coming from? That is talking to that DB.What do I find out? We ran out of disk space. My clients aren't happen but they're being toldlife is bad.

Everything comes back to normal once we manage it.

What if something happened but we were hitting this time out for other reasons?

MAIN IDEA

Always, always check the timeouts that manage the backpressure that can come from channels!

Let me tell you a story about backpressure.

For every socket connection, there's 10 connections. 10,000: What happens if the send blocks on this channel? I don't now. There's no management of backpressure. What couldbe happening in this code?

Dozen channels per goroutine.

Wht about these channels here?

Play a game: let's put a timeout on all these channels.We use a select case to time.after, let's say 100ms.

Turn every channel send into a select case with a time.After for a 100ms. None of these sends block

DO NOT THROW MORE GOROUTINES AT THE PROBLEM.

Special Use Case for Buffered Channels

Takes performance with risk.

Best scenario: when the send never blocks! you get performance and guarantee. Example: Goroutine that does 10 DB inserts. It means that the number is not magical but it has meaning.

Slower and solid rather than super fast and worry about it all the time.

ONE MORE THING JACKIEEEEEEE

Anytime an error occurs in your program, I want you to ask yourself one question: If CTO came to me, can I look this person in the eyes and say: "at 100% guarantee the integrity of the system is intact"?

Your code should never panic, ever.

	if (yes) {
		cool()
	} else {
		whatDoWeDo()
		panic(recover(panic))
		panicSomeMore(recover)
	}

SIGNAL QUIT ALL THE THINGS

06-stack_trace/example2/example2.go

DO NOT OVER ENGINEER. DO NOT BE CLEVER.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment