字幕列表 影片播放
[MUSIC PLAYING]
THOMAS NATTESTAD: My name is Thomas,
and I'm the product manager for WebAssembly.
ALEX DANILO: My name is Alex, and I'm a software engineer
on Chrome OS.
THOMAS NATTESTAD: And today we're
going to talk to you about WebAssembly.
We're going to start off by briefly
describing what WebAssembly is and what you can use it for.
Then I want to show off some of the amazing new features
that the WebAssembly team has been working on to deliver
to you in this last year.
Then I'll showcase some of the amazing applications
that have managed to build with WebAssembly,
and our shipping and production.
All right.
So first off, what is WebAssembly, actually?
WebAssembly is a new language for the web,
and offers an alternative to JavaScript for expressing logic
on the web platform.
It's important to note, though, that WebAssembly is in no way
a replacement for JavaScript.
Rather, it's designed to fill the gaps that
exist in JavaScript today.
Specifically, WebAssembly is designed as a compilation
target, meaning that you write in higher level languages,
such as C++, and then compile into WebAssembly.
WebAssembly is also designed to deliver
reliable and maximized performance, which
is something that can be difficult to get out
of JavaScript.
Most exciting, though, is the fact
that WebAssembly is now shipping in all four major browsers,
making it the first new language to be fully supported
in every major browser since JavaScript was
created more than 20 years ago.
All right.
So what can you actually do with this?
Well, as I already mentioned, because WebAssembly offers
maximized and reliable performance,
you can now expand the set of things
that you can feasibly do in the browser.
Things like video editing, complex application, codecs,
digital signal processing, and many, many more
performance-demanding use cases can now
be supported on the web.
Secondly, WebAssembly offers amazing portability.
Because you can compile from other languages,
you can port not only your own applications and libraries
but also the wealth of open-source C++ libraries
and applications that have been written.
Lastly, and potentially most exciting to many of you,
is the promise for more flexibility
when writing for the web.
Since the web's inception, JavaScript
has been the only fully supported way
to execute code on the web, and now with WebAssembly you
have more choice.
All right, so now that we all know what WebAssembly is,
I want to jump in and show off some of the new features
that we've been adding in just the last year.
First off is source maps.
You likely all know how important source maps are
when you're working with something like TypeScript
or Babel, but it's even more important
when you're trying to debug your WebAssembly code.
Source maps let you turn something
that looks like this into something just slightly more
friendly, like this.
With source maps you can see the specific line of code
where an error has occurred and you can also
set breakpoints and have the program actually pause
at the appropriate moment.
One of the big feature requests that we've heard from users
is for better performance when you're starting up
your application so that your module can actually
get going faster.
And for that we've created streaming compilation.
In the past, when you wanted to compile a module
you had to wait for the entire module
to be loaded off of the network, and only then could
you move on and actually compile it.
Now with streaming compilation, you
can start compiling each piece of your module
immediately, even before the other parts have
finished downloading.
To show you what that actually looks like,
here's a simple example where we called a fetch function--
or fetch for a WebAssembly Fibonacci module,
and then we just passed that fetch promise directly
into WebAssembly.inst antiateStreaming,
and it takes care of all of this underlying bits
and pieces for you to deliver this experience.
We did some profiling at different network speeds
to see the impact of this.
We found that all the way up until 50 megabits
per second network speed, the network
was actually the primary bottleneck,
and that the compilation was done as soon as the module was
loaded.
It wasn't until you hit the 100 megabits per second speeds
that you actually needed additional time past the time
it took to download the module in order to fully
compile and get it going.
To make startup time even faster,
the team built and launched an entire new compiler
that we called the Liftoff compiler.
This Liftoff compiler takes the WebAssembly byte code
that comes down off of the wire and then starts executing it
immediately.
The WebAssembly module is then taken off the main thread
and optimized further by the TurboFan optimizing compiler.
When TurboFan is done optimizing the WebAssembly code,
it's then hot swapped in directly
without any need for explicit developer action.
Unity did some benchmarking on the effects that Liftoff had.
On a benchmark where they tried to load a very large game,
they found that it went from taking seven seconds to load
the game to less than one second, which
makes all of the difference when you're waiting
to get into a game experience.
Probably the biggest feature that the team's
been working on this year is WebAssembly threads.
WebAssembly threads lets you run fast, highly paralyzed code
for the first time across multiple browsers.
It also lets you bring existing libraries and applications
that use threaded code such as Pthreads to the web.
This is such a big feature that I'm actually
going to leave most of the explanation to Alex later on.
But before I get into that, I want
to show off some of the cool new applications
that have already been building and launching with WebAssembly
this last year.
First off is SketchUp.
SketchUp is a 3D modeling software
that you can learn and start using really quickly.
Unlike traditional computer-aided design,
most people can learn SketchUp almost right away.
SketchUp lets people draw in perspective and then
push-pull things into 3D.
In no time, people can draw and redesign a living room,
plan out a do-it-yourself project,
or create and export a model for 3D printing.
This app is a lot of fun and you should all check it out,
which you can do right now instantly, just
by going to app.sketchup.com.
SketchUp has been around for a desktop application,
but the team's strategy has always
been to expand and broaden the market
of people who can use 3D modeling,
and by making it simple and easy to use
and accessible to everyone.
Delivering the app over the web was a critical step
in that strategy, and the team knew
that they wanted to use the same code
base as their desktop applications,
because rewriting their entire application in JavaScript
was just simply not an option.
The team's approach was to use the WebAssembly and Emscripten
compiler to compile their core 3D modeler
and bring it to the web.
The initial port took two engineers only three months
to bring to the web, which is pretty phenomenal when
you realize just how drastically it expanded
the reach of their application.
The early focus for SketchUp has always
been on the next generation of 3D modelers,
and today SketchUp is already one
of the most popular apps on the G Suite for education
marketplace.
At the same time, the app has opened up a subscription model
for SketchUp, and in just over six months,
the team has increased its paying customer base by 10%.
SketchUp has also seen consistent growth
in session time, returning visitor percentage,
and active users.
Moving on, the next application that I want to mention
is Google Earth.
I'm happy to say that Google Earth has successfully
gotten their application ported to WebAssembly, including
the newly added support for WebAssembly threads.
The best part is that they actually
got this threaded build working in both Chrome and Firefox,
making Google Earth the first WebAssembly
multi-threaded application to be running in multiple browsers.
Google Earth did some benchmarking,
comparing their single threaded version
to their multi-threaded version.
They found that the frame rate almost
doubled when they went to their threaded version,
and the amount of jank/dropped also reduced by more than half.
All right, so the last big company
and launch that I want to mention is Soundation.
Soundation is a web-based music studio
that enables anyone to make music
online with a wide selection of instruments, loops, samples,
and effects.
No additional hardware or installation or storage
is required.
Everything is accessible instantly and everywhere.
Soundation's mission is to facilitate musical creativity
in the world, and they do this by offering
a powerful, accessible, and affordable service
to the growing demographic of casual producers.
As an online web app, Soundation streamlines
the ability for producers to connect with peers,
get feedback, enter competitions, and even get
record deals.
Soundation is using a wide variety
of advanced web features to deliver this smooth experience.
And the first of these is audio worklets.
Launched in Chrome 66, the audio worklet
brings fast performance and extensible audio processing
to the web platform.
It could be used in conjunction with other cutting edge web
technologies such as WebAssembly and SharedArrayBuffer.
Soundation is also one of the world's first adopters
of WebAssembly threads, and they use these threads
to achieve fast parellelized processing to seamlessly mix
songs.
So let's have a look at their architecture
and see if we can learn anything.
On the JavaScript side of the world,
they have their application UI.
That application UI then talks to an audio mixing engine.
This audio mixing engine then spawns off
multiple different worker threads in WebAssembly,
and each of these worker threads can
talk to the same piece of SharedArrayBuffer memory.
This SharedArrayBuffer memory is then
passed on to the mixing threads, which further passes it
to the audio worklet, which produces the final result.
Here's a visualization showing the performance improvements
on rendering a song as they added multiple threads.
Adding just a single additional thread doubled
their performance, and by the time
they've added five threads, they had more than
tripled the performance of their application.
So that's a great visualization showing the performance
improvements that thread can bring,
but since this is Soundation, I thought we would instead
try and listen to it.
So here is us trying to render a song in Soundation
in the single threaded version of WebAssembly.
And fair warning, this is not going
to be an entirely pleasant experience.
[STATICY MUSIC]
So as you can imagine, this is not the experience
that you want when you're trying to create beautiful music.
But luckily Soundation succeeded in launching with WebAssembly
threads, and now they're able to deliver
an experience that sounds just a little bit better.
[SMOOTH MUSIC]
So as you can see, not only is this a much more
pleasant experience, but the CPU also
has additional cycle for other work.
All right, so I want to close off my segment by just talking
about some of the amazing community
projects that we've seen people working on out there.
And the first of these that I want to mention
is the awesome work that's been done by the Mozilla
team and the Rust community to bring Rust to the web
through WebAssembly.
They have an awesome set of tools and materials
to help you get started, and you can check those out
at rustwasm.github.io.
Speaking of languages, we've also
seen more than 30 different projects
trying to bring other languages to the web through WebAssembly.
These languages include ones like Perl, Python, Ruby,
Kotlin, OCaml, Go, PHP, and the .NET framework.
Many of these languages require garbage collection,
which isn't currently something that's
supported in WebAssembly, though we are working on it.
These languages come to the web by actually taking
their garbage collection system and other runtime bits
and compiling that itself down to WebAssembly,
and then shipping everything down to the application page.
This is a great strategy for getting started
and experimenting with some of these languages on the web,
but because of some of their performance and memory
characteristics, these aren't currently suited
for production applications.
The fully supported languages today are C, C++, and Rust,
but everything else should still be considered experimental.
And there are so many more amazing community projects
that I don't have time to do justice.
We've seen people porting Gameboy emulators, GNU
libraries, digital signal processing, and even
entire operating system like Microsoft Windows 2000 now
available in a browser tab, which
is, if not a exactly pleasant experience,
definitely interesting.
You can check out all of these demos
and much more at the forum where we have multiple demos
set up for you to check out.
And with that, I want to hand it back off to Alex
to talk to you more about WebAssembly threads
and how to use some of these features.
[APPLAUSE]
ALEX DANILO: Thank you, Thomas.
One of the kind of big things at the conference
here, when we talk about the browser,
we talk about using the platform.
And quite often people think of the platform as the software
stack that's inside the browser, but I
like to think of it a little bit different.
I like to think about the hardware, the platform that's
actually in your machine.
So here is an artist's rendition of the inside
of a desktop microprocessor.
This is what you see today if you
take the plastic off the top.
So at the top, we have the green bit,
which interfaces to the PCI bus, used
to be called the northbridge.
The left and right, you have memory interfaces.
These little yellow boxes are integrated memory controllers.
And you see all these blue tiles here.
And what they are is cores.
So each of those is a CPU core in its own right.
So this may be a desktop microprocessor, but even
in your pocket, if you have an iPhone or an advanced Android
phone, you'll have something like six
to eight cores in there, ready to be
used to do good computing work.
So when you write a normal web application,
you're looking at something like this.
You have one core running and so you have
all this silicon doing nothing.
So you're not really using the platform.
Now we've seen people come along and do something
like spawn a web worker to do the hard work,
and have the main thread for UI.
In that case, you're running a double threaded application.
And so you're using the platform a bit better,
but you're not really doing everything you could.
Now since we have introduced WebAssembly threads,
you can do stuff like this.
You could actually use many cores for your application.
And as we saw with the Soundation demo,
there's visible improvement in the user experience.
So I'd really like you to start thinking
about how you can adapt your application
to use all these cores.
Now when you create a web worker,
you have to understand that that is a threading primitive
and they run concurrently.
So you can do compute in parallel.
And this is a primitive that we all know pretty well.
But one of the things about when we do something
like this, if we have an app, on the left,
we have what we call the main thread--
we're all familiar with the main thread--
that interacts and talks to the DOM.
The worker that we generate is what
we call the background thread.
So it's running in parallel but it doesn't actually
have the ability to call web APIs
and interact with the DOM and stuff like that.
But when you create workers, and you create them
normally with a JavaScript thing, it creates an instance.
So these instances kind of sit on their own on the side,
they're running parallel, they don't get
to do anything with the DOM.
So they kind of run on the side.
So if you create one, you get V8 hanging off
the top of your main thread, and you get an instance hanging off
your worker.
So then if you go and create a bunch of workers,
you get a bunch more V8 instances.
Now each of these instances consumes memory.
So that means that if you start spawning lots of JavaScript
workers to make your application do stuff more complex,
it will actually consume more and more memory
and you might run out on a phone, or something like that.
But I'll let you in on a little secret.
They don't talk to each other.
So you've got separate bits of JavaScript
running in all these parallel threads,
but they don't communicate.
They don't have any shared state.
They're literally another copy of V8 sitting in memory.
The way these things can talk to each other,
though, is with postMessage.
And postMessage is kind of like sending a paper plane over.
I'll send it from this worker to that one,
I'll sit around and wait for it to arrive,
and there's no predictability about when
that will be delivered.
So it's not a great experience for a true multi-threaded
application.
Now, when the team built WebAssembly threads,
they implemented something that looks a lot more like this.
So what happens is, this is an example of, say,
having three threads.
So under the hood, we actually spin up the three web workers
but the difference here is that the WebAssembly module
is shared between the workers.
So there is one copy of the code,
so you're not consuming nearly as much memory.
But more importantly, they share state,
and the way they share state is through a thing
called SharedArrayBuffer.
So if you're a JavaScript engineer,
you probably know what a typed array is, because you use them
day to day.
So SharedArrayBuffer is basically the exact same thing,
except that it can be shared across workers.
And so what that means is the state
of the execution of the application is visible to any
of the workers in parallel.
Now if you farm off something into a pool of workers
and you have it hanging off your main app,
it will look something like this.
You'll have your main thread for your main application that
can talk to the DOM, it can use all the web APIs,
and it can see the SharedArrayBuffer,
and that SharedArrayBuffer is being
manipulated by all the parallel threads in the WebAssembly
module.
OK, but by now you're probably thinking,
this is all well and good, but how
do I use this stuff in my actual application?
So I'll start with a very simple example.
We'll do an example which is just a little Fibonacci program
that runs in two threads.
So it will look a bit like this.
There'll be the main thread, the background thread,
the WebAssembly module, all talking
to the SharedArrayBuffer.
So we just take some source code,
which will be something like this,
which is just a bit of C code.
And what we want to do is we want
to compile that into a form that we can use in parallel threads.
And the way we do that is with the Emscripten tool chain.
So it has a compiler called EMCC,
and there are a couple of flags here,
though, I want to point out.
The first one is -s USE_PTHREADS=1.
What that does is turn on the multi-threading support
when you're compiling your WebAssembly module.
The second flag that's interesting is -s
PTHREAD_POOL_SIZE=2.
What this does is tells the compiler
that I want to pre-allocate two threads for my application.
So when I actually start the WebAssembly module
it will pre-create two threads and get going with that.
Now this is kind of visualization
what would happen.
If you set PTHREAD pool size to two,
you get the picture on the left, you get two workers,
and if you set it to eight you get eight workers.
And that happens at startup time of your web app.
Now you may be wondering why you care about the number.
Well, the thing is that you should really try and set it
to the maximum number of threads.
If you say I only want two threads,
and then suddenly your application needs
three or four, it's a bit of a problem.
So what happens is that the WebAssembly module
has to yield to the main thread before it
can create that worker.
So if you're relying on all the threads being
there at the startup, you need to set the number high enough.
But of course, if you set that number too high,
you're wasting memory.
So this is something to tune.
So in Soundation's case they used five threads
and it works really well for them.
So when you're tuning your apps you need to think about it.
OK, so if you want to get out there and actually try
this stuff, which I'm sure you're all
dying to, if you fire up Chrome 70
and navigate to Chrome flags and search for WebAssembly thread
support, change the setting here from default
to enabled, and at that point, you'll
have to restart your browser.
And then you can start building stuff and testing it locally.
Now once you've built a working WebAssembly thread app,
you probably want to deploy it out to the public.
And the way you do that is by getting an origin trial token.
So an origin trial token is tied to your domain
and you get it from us.
And you basically-- it's just a meta tag
that you put on the page.
And that tells the browser, hey, these people
are trying WebAssembly threads and let's use it.
So if you want to go ahead and do that,
and I encourage you all to do so, just go to this short link,
and there's a form you can fill in, put
in your URL, the reason you want to use this stuff,
and go start building something really cool.
Now of course, as developers, we spend most of our times
in DevTools trying to debug things, which is how it is.
So in Chrome 70 at the moment, which is released to stable,
you can single step instructions.
And that is a WebAssembly instructions.
So it looks a little bit like this,
like not friendly, as Thomas pointed out.
So you can see this little box up here,
which is showing you the threads.
So this is a two thread application running.
And this box is the actual WebAssembly disassembled code.
So it's not the binary, it's a text form of the instructions
that are in the module.
And you can single step those and it's all
very well and good, but realistically, we don't really
like that debugging experience.
So Chrome 71 brings source map support,
as Thomas mentioned earlier.
So source maps lets you change what you saw before
into something-- oop, next slide--
something that looks like this.
So this is the source code of the Fibonacci function sitting
in Dev Tools, and you can single step over instructions,
you can set breakpoints, you can do all stuff like that.
Now, if you want to actually do this yourself
and you want to generate the source map,
you just need to set two flags on the EMCC compiler command
line.
The first is -g, which says generate debug symbols,
and the second is --source-map-base,
and that points to a URL where it will actually
find the source map file.
In this case, I'm using local host,
so I'll be using it on my own workstation.
OK, so I'll just recap on what we've talked about today,
just so you can remember what we talked about.
The first thing is it's streaming compilation,
which lets the browser compile the WebAssembly
module as it comes over the wire, which is launched now.
It's in Chrome 70, which speeds things up.
The second is Liftoff, which is the tiered compiler,
so you get the first compile really fast so your app starts,
and then hot swaps in the better code a bit later on.
Then we have, of course, WebAssembly threads shipping
now in Chrome 70, and you can use it with an origin trial,
so you can ship it to your customers
and they can use it and play with it.
And of course, Chrome 71, which will be out really soon,
contains source maps, which means
that it's a lot easier to debug your code.
And so I'd encourage all of you people
out there to start writing using WebAssembly threads,
because it unlocks the power of the supercomputer that's
sitting in your pocket right now.
Thank you.
[MUSIC PLAYING]