zoukankan      html  css  js  c++  java
  • Concurrency Is Not Parallelism (Rob pike)

    Rob pike发表过一个有名的演讲《Concurrency is not parallelism》(https://blog.golang.org/concurrency-is-not-parallelism),

    演讲胶片在talks.golang.org中可以找到(https://talks.golang.org/2012/waza.slide#1),

    演讲视频地址 :https://vimeo.com/49718712

    以下是根据视频转换的文本信息。

    if you looked at the programming
    languages of today you probably get this
    idea that the world is object oriented
    but it's not it's actually parallel
    you've got everything from the lowest
    level like multi-core machines and up
    through networking and so on somebody
    gets all the way up to users who knows
    planets the universe there's all these
    things that are happening simultaneously
    in the world and yet the computing tools
    that we have are really not very good at
    expressing that kind of worldview and
    that seems like a failing but we can fix
    that if we understand what concurrency
    is and how to use it now I'll assume
    that most of you at least heard of the
    go programming language is just what
    I've been working on at Google the last
    few years and go is a concurrent
    language which means that it has some
    things that make concurrency useful like
    is God the ability to execute things can
    currently the ability to communicate
    between things that are executing
    concurrently and it's got this thing
    called a select statement which is a
    multi-way concurrent control switch if
    that doesn't make any sense to you yet
    don't worry but when we announced go
    which was about two years ago all these
    programmers out there said Oh concurrent
    tools I know what to do like and run
    stuff in parallel yay but that actually
    isn't true concurrency and parallelism
    are not the same thing it's a commonly
    misunderstood problem and I'm here to
    try to explain why and to show you that
    concurrency is actually better what
    would happen to these people who were
    confused was they take a program they'd
    run it on more processors and it would
    get slower and they think this is broken
    it doesn't work I'm going away but what
    was really broken was the world view and
    I hope I can fix that so what is
    concurrency well concurrency as I'm
    using it as its intended to be used in
    the computer science world is a way to
    build things it's the concurrent it's a
    composition of independently executing
    things typically functions but they
    don't have to be and we usually express
    those as the is interacting processes
    now by process I don't mean a Linux
    process I mean the sort of general
    concept that embodies threads and co
    routines and proceeds the whole thing so
    I think in the most abstract possible
    sense so it's the composition of
    independently executing processes
    parallel ism on the other hand is the
    simultaneous
    Dainius execution of multiple things
    possibly related possibly not and if you
    think about it in sort of a general
    hand-wavy way concurrency is about
    dealing with a lot of things at once and
    parallelism is about doing a lot of
    things at once and those are obviously
    related but they're actually separate
    ideas and there's a little confusing to
    try to think about them if you don't
    have the right tool kit so one is really
    about structure concurrency and one is
    about execution parallelism and I'll
    show you why those are important so
    concurrency is a way to structure a
    thing so that you can maybe use
    parallelism to do a better job but
    parallel ism is not the goal of
    concurrency concurrence ease goal is a
    good structure so here's an analogy
    might be familiar with if you're running
    an operating system it might have a
    mouse driver a keyboard driver display
    driver network drivers whatever else and
    those are all managed by the operating
    system as independent things inside the
    colonel but those are concurrent things
    they aren't necessarily parallel if you
    only one processor only one of them is
    ever running at a time and so there's a
    concurrent model for these in bio
    devices but it's not inherently parallel
    it doesn't need to be parallel whereas a
    parallel thing might be something like a
    vector dot product which you can break
    that into microscopic operations as you
    can execute on some fancy computer in
    parallel very different idea not the
    same thing at all so in order making
    currency work though you have to add
    this idea of communication which I'm not
    going to focus on too much today but
    you'll see a little bit about it so
    concurrency gives you a way to structure
    programming to independent pieces but
    then you have to coordinate those pieces
    and to make that work you need some form
    of communication and tony hoare in 1978
    wrote a paper called communicating
    sequential processes which is truly one
    of the greatest papers in computer
    science and if you haven't read it if
    anything out of this talk sinks in is
    that you should go home and read that
    paper it's absolutely amazing but based
    on that a lot of people with lesser
    minds have followed and built tools to
    use these his ideas into concurrent
    languages like Erlang is another one
    that's great go has some of these ideas
    in it but the key points are all in that
    original paper with with a couple of
    minor exceptions which will come up to
    but look this is all way too abstract we
    need Gophers
    so let's get some Gophers going here's a
    real problem we want to solve ok we have
    a pile of ancient of obsolete manuals
    may say the C++ 98 manuals know that C++
    11 is 0 or maybe it's the C++ 11 books
    we don't need them anymore whatever the
    point is we got to get rid of them
    they're taking up space so we have a go
    for whose job is to take the books from
    one pile and move them into the
    incinerator and get rid of them okay but
    with only one go over it's going to take
    a long time if it's a big pile also
    Gophers not very good at moving books
    although we've given in the cart so
    let's put another gopher in the problem
    except he's not going to get any better
    right because he needs the tools and
    this this is kind of pointless we need
    to give him all the parts he needs in
    order to do this so this gopher needs
    not only the ability to be a gopher but
    he also needs the tools to get the job
    done so let's give them another car now
    that's going to go faster we're
    definitely going to be able to move
    books quicker with two Gophers pushing
    the cards but of course there may be a
    little problem because we're going to
    have to synchronize them they can get
    stuck at the incinerator the book pile
    getting each other's way running back
    and forth so they're going to need to
    coordinate a little bit so you can
    imagine the Gophers sending for the
    little tony hoare messages saying Here I
    am I need space to put the books in the
    incinerator or whatever it is but you
    get the idea this is silly but I want to
    make it really clear these ideas are not
    deep so just they're just good okay well
    how do we make them go faster well we
    double everything we put two Gophers in
    and we double the the pile that the
    piles and the incinerators as well as
    the Gophers and now we can move twice as
    many books in the same amount of time
    that's parallel right but think of it
    instead of parallel as really the
    concurrent composition of to go for
    procedures moving books so concurrency
    is how we've expressed the problem these
    two this this gopher guy can do this and
    we paralyze it by instantiating more
    instances of this gopher procedure and
    that's called the concurrent composition
    of processes or in this case Gophers now
    this design is not automatically
    parallel because sure there's two
    Gophers but who says they both have to
    work at the same time I could say the
    only one gopher is allowed to move at
    once which would be like having a unit a
    single core computer and the design is
    still concurrent and correct a nice but
    it's not intrinsically
    parallel and thus i can make both those
    Gophers move at once that's when the
    parallelism comes in having two things
    executing simultaneously not just having
    two things okay that's a really
    important model but once we've decided
    that we understand we can break the
    problem down under these concurrent
    pieces we can come up with other models
    so here's a different design okay now we
    got three golfers on in them in the
    picture it's the same pile of books the
    same incinerator but now we've got three
    Gophers right there's a gopher whose job
    is just to load the card there's a job
    as a goal for his job is just to carry
    the cart and then presumably return the
    empty back again and then there's a
    gopher whose job is to load the
    incinerator so three golfers it's going
    to go faster might not go much faster
    though because they're going to get
    blocked you know the cart the books is
    going to be in the wrong place and
    there's time to bring the Gopher running
    back with the empty where nothing useful
    is getting done with the car so let's
    clean that up by having another go for
    returning empties okay now this is
    obviously so right but i want to point
    something fairly profound that's going
    on here this this version of the problem
    will actually execute better than this
    problem this guy even though we're
    actually doing more work by having
    another goal for running back and forth
    in here so once we thought this
    concurrency idea we're able to add
    Gophers to the picture and actually do
    more work but make it run faster because
    the concurrent composition of better
    managed pieces can actually run faster
    and it's pretty unlikely that things
    will work out just perfectly but you can
    imagine that if all the Gophers were
    time just right Nepal we're just right
    and they knew how many books to move at
    a time this thing could actually keep
    all four gopher is busy at once and it
    could in fact move four times faster
    than our original version unlikely but I
    want you understand that it's possible
    so here's an observation it's really
    important and it's kind of subtle we
    improve the performance of this program
    by adding a concurrent procedure to an
    existing design we actually added more
    things but the whole thing got faster
    and if you think about it that's kind of
    weird it's also kind of not weird
    because you added another gopher and
    Gophers to work but if you forget the
    fact that he's a gopher and think of it
    it's just adding design adding things
    that the design can actually make it
    more efficient and that parallelism can
    come from better concurrent expression
    of the problem it's a fairly deep
    insight that doesn't look
    like it because their Gophers involved
    but that's okay so we have four
    concurrent procedures running it right
    there's a gopher that loads things into
    the cart there's a gopher that takes the
    cart and trucks it across towards the
    incinerator there's another gopher who's
    unloading the carts contents into the
    incinerator and there's a fourth gopher
    who is returning the empty carts back
    and you can think of these as
    independent procedures just running as
    independent things completely and we
    just compose those in parallel to
    construct the entire program solution
    but that's not the only way we could do
    it here's a completely different design
    sorry not going to do it we can we can
    here's the same design made more
    parallel by putting another pile of
    books another in center in and for more
    Gophers but you see the key point is you
    we're taking the idea that we have how
    we break the problem up and once we
    understand is it's concurrent
    decomposition we can actually paralyzed
    on different axes and get better
    throughput or or not but at least we
    understand the problem in a much more
    fine-grain way we have control over the
    pieces in this case is if we get
    everything just right we've got eight
    Gophers working hard for us burning up
    those C++ manuals or maybe there's no
    paralyzation at all who says that all
    these Gophers have to be busy at once I
    might only be able to run one gopher at
    a time in which case this design would
    only run at the rate of a single gopher
    like the original problem and the other
    seven would all be idle while he's
    running but the design is still correct
    and that's a pretty big deal because it
    means that we don't have to worry about
    parallelism when we're doing concurrency
    forget the concurrency right the
    parallelism is actually a free variable
    that we can decide just how many Gophers
    are busy or we could do a completely
    different design for the whole thing
    let's let's forget the old pattern put
    in a new pattern and we'll have to go
    furs in the in the in the story but
    instead of having one go for carry that
    all the way from the pile to the
    incinerator we put a staging dump in the
    middle so the first gopher carries the
    books to the to the dump drops them off
    runs back gets more the second guy sits
    there waiting for cart for books to
    arrive to the pile takes them from there
    was a new sinner ater and if you get
    this right you've got to go for
    procedures running but they're kind of
    different procedures the kind of the
    same but they're subtly different they
    have slightly different parameters but
    if you get this system running right at
    least once it's
    verted it can in fact in principle run
    twice as fast as the original even
    though it's a completely different
    design in some in some sense the
    original one but of course once we've
    got this composition we can go another
    way we can paralyze the usual way run
    two versions of this whole program at
    once and double again now we got four
    golfers maybe up to four times the
    throughput or we could take a different
    way again and put the staging pile in
    the middle into the original concurrent
    multi gopher problem so now we've got
    eight Gophers on the fly and books
    getting burned a terrific right but
    that's still not good enough because we
    can paralyze on another dimension and go
    full-on so here's 16 Gophers moving
    those books to the burning pot and it
    obviously this is is very very
    simplistic and silly it's got Gophers in
    its that makes it good but I want you
    understand that conceptually this is
    really how you think about running
    things in parallel you don't think about
    by running in parallel you think about
    how you break the problem down into
    independent components that you can
    separate and understand and get right
    and then compose to solve the whole
    problem together so what does this all
    mean well first of all there are many
    ways you could do this I showed you just
    a couple if you sit there with a
    sketchbook you can probably come up with
    50 more ways to have go for his move
    books there's lots of different designs
    they're not necessarily all equivalent
    but they can all be made to work and you
    can then take those concurrent designs
    and refactor them rearrange them scale
    them in different dimensions to get
    different abilities to process the
    problem and it's nice because however
    you do this the correctness of your
    algorithm for doing this is easy it
    really it's not going to break I mean
    they're just go firs but you know the
    design is intrinsically safe because
    you've done it that way however it's
    this is obviously a stupid problem this
    has no bearing on real work well
    actually it does because if you take
    this problem and you change the book
    pile into some web content you change
    the gophers into CPUs you change the
    card to the networking or the
    marshalling code or whatever it is you
    need to run to move the data and then
    the incinerator is the web proxy or
    browser whoever you want to think about
    the consumer of the data you've just
    constructed the design for a web serving
    architecture and you don't probably
    don't think of your webs
    architecture is looking like that but
    the fact this is pretty much what it is
    right and you can see by substituting
    the pieces this is exactly the kind of
    designs that you think about when you
    talk about things like proxies and
    forwarding agents and and buffers and
    all that kind of stuff scaling up more
    instances there on this drawing they
    just don't think of it that way so
    they're not intrinsically hard things to
    understand Gophers can do it so can we
    right so let me now show you how to use
    these ideas a little bit in building
    things with go now i don't i'm not going
    to teach you go in this talk i hope some
    of you know it already i hope lots of
    you go and learn about more more about
    it afterwards but i'm going to try to
    teach you a little tiny bit ago and they
    hope the rest car gets absorbed as we as
    we do it so go has these things called
    go routines which you can think of as
    being a little bit like threads but
    they're actually different and i rather
    than go into the details of how the
    different let's just say what they are
    so let's say we have a function that in
    this case takes two arguments if we call
    that function are in our program then we
    wait for the function to complete before
    the next statement executes that's very
    very familiar you all know that but if
    instead you put the keyword go before
    you call that function then what happens
    is that function starts running but you
    get to run right away at least
    conceptually not necessarily remember
    concurrency versus parallel but
    conceptually your program keeps running
    while f is off you're doing his thing
    right and you don't have to wait for the
    f to return and if you that seems
    confusing just think of it as being a
    lot like the ampersand in the show so
    this is like running f ampersand off in
    the background ok now what is exactly is
    it go routine well they're kind of like
    threads right because they run together
    they're in the same address space within
    a program they are at least but they're
    much much cheaper it's pretty easy to
    make them and they're very cheap to
    create and then they get multiplex
    dynamically onto operating system
    threads as required so you don't have to
    worry about scheduling unblocking and so
    on the system takes care of that for you
    and when a when a girl routine does need
    to block like doing a read system call
    or something like that no other girl
    routine needs to wait for it they're all
    scheduled than anything so they feel
    like threads but there are much much
    lighter weight version of them and it's
    not an original idea that other
    languages and systems have done things
    like this but we we give them our own
    name to make it clear what they are so
    call them go routines okay now I
    mentioned we have to communicate between
    these things right so to do that we have
    these things in go called channels which
    are like a little bit like pipes in the
    shell but they have types and they have
    other nice properties which we're not
    going to go into here today but here's a
    fairly trivial example we create a timer
    channel and say it's a channel of time
    time values and then we launch this this
    function in the background that we sleep
    for a certain amount time delta T and
    then sends on the timer channel the time
    at that instant timer time now and then
    the other process because the other guru
    team because this one was launched with
    a ghost statement can doesn't have to
    wait it can do whatever it wants and
    when it's ready to hear that the other
    guys completed he says I want to receive
    from the timer channel whatever that
    value is and that goroutine will block
    until there's a value to be delivered
    and once it is completed that will be
    get set to the time at which the other
    go routine completed trivial example but
    everything you need is in that one
    little slide and then the last piece is
    a thing called select and what it does
    is that lets you control your programs
    behavior by listening to the by looking
    at multiple channels at once it seeing
    who's ready to communicate and you can
    decide to rate in this case between
    channel 1 or channel 2 and the program
    will behave differently depending on
    weather channel 1 our channel two is
    ready in this case if neither is ready
    the default clause will run which is me
    lets you sort of fall through if
    nobody's ready to communicate if the
    default clause is not present in the
    Select then you'll wait until one or the
    other of the channels is ready and if
    they're both ready the system will just
    pick one randomly so this this will come
    up a little later but it's pretty much
    like a switch statement but for
    communications and if you know
    Dijkstra's guarded commands it should
    seem fairly familiar now I said go
    sports concurrency I mean it really
    supports concurrency it is routine in a
    go program to create thousands of go
    routines and we are once debugging
    actually live at a conference go thing
    that was running in production that he
    created 1.3 million go routines and had
    something on the neighborhood of ten
    thousand actually active at the time we
    were debugging it and to make this work
    of course they have to be much much
    cheaper than threads and that's kind of
    the point so they're not free there's
    allocation involved but not much and
    they grow and shrink as needed and they
    sort of well man
    but they're very very cheap and you can
    think about them as being you know as
    cheap as Gophers you also need closures
    I showed your closure sort of under the
    covers before here is just proof that
    you have them in the language because
    they're very handy and concurrent
    expressions of things to create nonce
    procedures so you can create a function
    that here in this case composes a couple
    more function returns a function it's
    just a show that it works and and
    they're real closures you can go so
    let's use these elements to build some
    examples and I hope you'll learn a
    little bit of concurrent go programming
    by osmosis which is the best way to
    learn so let's start by launching a
    demon you can use a closure here to wrap
    some background operation you want done
    but not wait for it so in this case we
    have two channels input and output and
    for whatever reason we have to deliver
    input to output we do but we don't want
    to wait until the copying is done so we
    say go funk for a closure and then have
    a for loop that just reads the input
    values and writes into the output and
    the full range clause in go will drain
    the channel so I'll run until the
    channel is empty and then exit so this
    little burst of code just drains the
    channel automatically and does it in the
    background so you don't have to wait for
    anything I was a little bit of
    boilerplate there but you get it's not
    too bad and you get used to it let me
    now show you a very simple load balancer
    a very simple one and if there's time
    which is I'm not sure there will be i'll
    show you another one but this is a
    simple one so imagine you have a bunch
    of jobs that need to get done and we've
    abstracted them away here or maybe
    concretize them into a work structure
    with three integer values that you need
    to do some operation on so the worker
    tasks what they're going to do is
    compute something based on these values
    and then I put a sleep in there so that
    this guarantee do we have to think about
    blocking because this is work attached
    may block an arbitrary amount of time a
    way we structure it is we have the
    worker task read the input channel to
    get work to do and have an output
    channel to deliver the results so the
    arguments of this function and then in
    the loop we range over the input values
    doing the calculation sleeping for some
    essentially arbitrary time and then
    delivering the output to the respond to
    the output to the guy who's waiting so
    we have to worry about blocking so
    that's got to be pretty hard right well
    there's the whole slew
    and the reason this is so easy is that
    the channels and the way they work along
    with the other elements of the language
    lets you express these concurrent things
    and compose them really well this what
    this does is creates two channels an
    input channel in an output channel which
    is the things connected to the worker
    they're all reading off one input
    channel and delivering to one output
    channel and then you start up some
    arbitrary number of workers notice the
    go clause in the middle there all these
    guys are running concurrently maybe in
    parallel and then you start another job
    up that says generate lots of work for
    these guys to do and then you hang
    around in this call function call
    received lots of results which will read
    the values coming out of the output
    channel in the order that they complete
    and because of the way this thing is
    structured whether you're running on one
    processor or a thousand if job will run
    correctly and completely anyone use the
    resource as well it's all taken care of
    for you and if you think about this
    problem it's pretty trivial but it's
    actually fairly hard to write concisely
    in most languages without concurrency
    concurrency makes it pretty compacted to
    do this kind of thing and more important
    it's implicitly parallel although not
    you don't have to think about problems
    if you don't want to but it also can
    scale really well there's no
    synchronization or nonsense in their num
    workers could be a huge number and the
    thing would still work efficiently and
    the tools of concurrency therefore make
    it easy to build these kind of solutions
    to fairly big problems also notice there
    was no locking no mutexes all these
    things that people think about when they
    think about the old concurrency models
    they're just not there you don't see
    them and yet this is a correct
    concurrent and parallelizable algorithm
    with no locking in it that's got to be
    good right but that was too easy so
    let's see how we doing yeah I got I got
    time to do the harder one this is a
    little trickier but it's the same basic
    idea but done much more realistically so
    imagine we have a load balancer that we
    want to write that's got a bunch of
    requesters generating actual work okay
    and we want we have a bunch of work of
    tasks and we want to distribute all
    these requesters workload on to an
    arbitrary number of workers and make it
    all sort of load balance out so the work
    gets assigned to the least lightly
    loaded worker so you can think of the
    workers have up may have large amounts
    of work they're doing it once it's not
    just one at a time they may be doing
    lots and the
    lots of requests going on so it's a very
    busy system this could be maybe on one
    machine which is how i'm going to show
    it to you but you could also imagine
    that some of these these lines represent
    network connections that are doing
    proper load balancing architectural e
    the design is still going to be safe the
    way we do it so whatever crest looks
    like is very different now we have some
    arbitrary function closure if you like
    that represents the calculation that we
    want to do and we have a channel on
    which we're going to return the result
    now notice the channel is part of the
    request in go unlike a lot of the other
    languages like Erlang the channel idea
    is there and it's a first-class value in
    the language and that allows you to pass
    channels around and they're kind of like
    file descriptors in the sense if you
    have the channel you can communicate
    with someone but no1 with anyone who
    does not have the channel is not able to
    so it's like you know being able to pass
    a phone call to somebody else to do or
    to pass a file descriptor over a file
    descriptor there it's pretty pretty
    powerful idea so the idea is you're
    going to send a request with a
    calculation to do and a channel on which
    to return the result once it's done so
    what here's an artificial but somewhat
    illustrative version of the requester
    what we do is we have a channel of
    requests that are coming in and we're
    going to generate stuff to do on that
    work channel so we make a channel which
    is going to go inside each request to
    come back to us for the answer we do
    some work which I've just represented
    here is sleeping who knows what what's
    actually doing and then you send on the
    work channel a request object with the
    function you want to calculate and
    whatever that is I don't care and a
    channel I want you send the answer back
    and then you wait for the on that
    channel to get the result to come back
    and once you've got that you probably
    have to do something with the result so
    this is just something generating work
    at some arbitrary rate it's just
    cranking out results but it's doing it
    by communicating on channels with with
    inputs and outputs and then the worker
    it which is on the other side of this
    picture remember we've got requesters
    hoops we've got requesters living at the
    balancer which is the last thing I'm
    going to show you and workers on the
    right what the workers have in them is a
    channel of incoming requests and then a
    count of pending tasks and
    which is going to represent the load
    that that worker has the number of tasks
    he's actually got busy and then an index
    which is part of the heap architecture
    to show you in a second so then what the
    worker does is receive work from his
    requester his request channel which is
    part of the worker object call the
    function on the worker side so you pass
    it request I guess from your father who
    passed the actual function from the
    requester through the balancer into the
    worker he does the answer and then he
    returns the the answer back on the
    channel now notice that unlike a lot of
    other load balancing architectures the
    channels from the worker back to the
    requester do not go through the load
    balancer once the load once the
    requester in the worker connected the
    bouncers out of the picture and the work
    on the requests are talking directly and
    that's because you can pass channels
    around inside the system as this running
    okay and then if you want to you could
    also put a go routine inside put a ghost
    statement inside here and just run all
    these requests in parallel on the worker
    it would work just fine if you did that
    but I that's enough going on at once
    already okay and then the balance was
    kind of magical you need a pool of
    workers and need some balance or object
    you're going to put the balancers
    methods on and that concludes a pool and
    then a single done channel which is how
    the workers tell the balancer that
    they've finished their most recent
    calculation so then the balancer is
    pretty easy what it does is it just
    forever does a select statement waiting
    either for more work to do from a
    requester in which case it dispatches
    that requests the most lightly loaded
    worker or a worker tells them he's done
    in which case you update the data
    structure e by saying the balancer that
    worker is complete his task so it's just
    a simple two-way select and then we just
    have to admit these two functions and to
    do that we actually what we actually do
    is construct a heap I'll skip that bits
    are very exciting you get the idea
    dispatch all this patch has to do is
    grab the least loaded worker which is a
    standard priority queue implementation
    on the heap so you pull the most likely
    little worker off the heap you send it
    the task by writing the request to its
    request channel now you increment the
    load because it's got one more guy you
    know about and that's going to influence
    the loading distribution and then you
    push it back onto the same spot on the
    heat and go and
    sit you've just dispatched it and you've
    updated in structure and that's what for
    executable lines of code and then the
    completion task which is when the work
    is finished you've got to do the sort of
    inverse you there's one for your guy on
    this work is Q so you decrement is
    pending cow you pop in from the heat and
    you put it back on the heat and that
    will put them back where it belongs in
    the priority queue and that's a complete
    implementation of a semi-realistic load
    balancer but the key point here is that
    the data structures are using channels
    and go routines to construct this
    concurrent thing and the result is
    scalable it's correct it's very simple
    it's got no explicit locking and yet the
    architecture just sort of makes it all
    happen and concurrency is therefore
    enabled the parallelism intrinsic in
    this thing and you can actually run this
    program i have this program it's all
    compilable and runnable and it works and
    it does the load balancing perf and the
    things i'll stay at exactly uniform load
    modulo quantization it's pretty good and
    you can of course have I never said how
    many workers there are or how many
    questions there are there could be one
    of each and 10 of the other or a
    thousand of each or a million of each
    the scaling still works and still
    behaves efficiently one more example
    which is somewhat more surprising but it
    fits on a single slides with a nice one
    to finish imagine you how to a
    replicated database so you've got
    database with with the same data in each
    of multiple what we call shards at
    Google saying the same instance right
    and what you want to do is deliver a
    quest to all the databases and a query
    and get back the result but they're all
    going to be the same you're using this
    to go faster by picking the first guy to
    answer as first got to come back with
    the answer is the one you want so if one
    of them's down or disconnected or
    something you don't care because
    somebody else will come in so here's how
    to do that this is the full
    implementation of it you have some array
    of connections and some query you want
    to execute you create a channel which is
    buffered to the number of elements the
    number of replicants inside this
    replicas inside the the query database
    and then you just run over all of the
    connections to the databases and
    for each one of them you start a go
    routine up to deliver the query to that
    channel to that database and then get
    the answer back but by this Duke we
    recall and then deliver the answer to
    the single channel that that's holding
    the results for all of these guys and
    then after you've launched them all you
    just wait on the bottom line there and
    we wait for the the first guy that comes
    back on the channel is the answer you
    want you return it and you're done and
    the thing is this looks like a toy and
    it kind of is but it's actually a
    complete correct implementation the one
    thing that's missing is clean teardown
    you want to sort of shut tell the
    servers that haven't come back yet when
    you've got an answer that you don't need
    them anymore and you can do that is it's
    more code but not an unreasonable amount
    more but then it wouldn't fit on the
    slide so I just want to show you this is
    a fairly sophisticated problem to write
    in a lot of systems but here it just
    sort of falls naturally out of the
    architecture because you've got the
    tools of concurrency to represent a
    fairly large distributed complex problem
    and it works out really nicely so five
    seconds left that's good conclusion
    concurrency is powerful but it's not
    parallelism but it enables parallelism
    and it makes parallelism easy and if you
    if you get that then I've done my job so
    if you want to read more there's a bunch
    of links here there's a goal enghadr
    guys everything about go you want to
    know there's a nice history paper that
    rust put together that's linked there I
    gave a talk a few years ago that led up
    to us actually doing go which you might
    find interesting Bob Harper at CMU has a
    really nice blog posting called
    parallelism is not concurrency which is
    very similar to the idea that
    concurrency is not parallelism but not
    quite and then there's a couple other
    things the most surprising thing on this
    is the concurrent power series work that
    Doug math were my old boss at Bell Labs
    did which is an amazing amazing paper
    but also if you want to be a different
    spin on it the last link on the slide is
    to another language God sawzall which I
    did at Yale at ha at Google shortly
    after coming there from Bell Labs and
    it's remarkable because it is incredibly
    parallel language but it has absolutely
    no concurrency and by now I think you
    might understand that that's possible so
    thanks very much for listening and
    thanks to eric for writing me and I guess it's time to have
    some drinks or something
    [Music]
    you

  • 相关阅读:
    eclipse配置自动提示EXTJS和jQurey
    Java用jdom.jar解析读取XML文件信息
    Hibernate配置XML连接数据库
    【codeforces】ZeptoLab Code Rush 2015 E 跳跃表? D kmp还不错的题
    各种语言版本的输出本身源代码的程序
    原地归并排序
    c/c++ static
    【程序员的自我修养——链接、装载与库】笔记
    【清华大学OS公开课】
    学习需要记录才行啊
  • 原文地址:https://www.cnblogs.com/majianguo/p/6753968.html
Copyright © 2011-2022 走看看