Back to all episodes

RNR 323 - Static Hermes with Tzvetan Mikov

February 28, 2025
45:02
E
323
Tzvetan Mikov, Mazen Chami, Jamon Holmgren, Robin Heinze

Tzvetan Mikov joins Jamon, Robin, and Mazen to discuss Static Hermes—how it improves React Native performance through bytecode and native compilation. They dive into optimization strategies, the role of typing, and what this means for developers. Plus, insights into Hermes's evolution and what’s next for JavaScript performance in React Native!

 

Show Notes

  1. Tzvetan's talk at React Universe Conf 2024


Connect With Us!


This episode is brought to you by Infinite Red!

Infinite Red is an expert React Native consultancy located in the USA. With nearly a decade of React Native experience and deep roots in the React Native community (hosts of Chain React and the React Native Newsletter, core React Native contributors, creators of Ignite and Reactotron, and much, much more), Infinite Red is the best choice for helping you build and deploy your next React Native app.

Todd Werth:

Welcome to React Native Radio Podcast, brought to you by Lumen Marshmallows. But remember, marshmallows are only for team players. Episode 3 23, static Hermes.

 

Jamon Holmgren:

Hey everybody. I'm Jamon. She's Robin. He's Mazen, and we are React Native Radio. Today we have a really fun guest koan. Did I say your name correctly?

 

Robin Heinze:

Yes,

 

Jamon Holmgren:

You did. First off, you did even the last name.

 

Robin Heinze:

This is a point of pride for Jamon.

 

Jamon Holmgren:

Well, the Was it Micko? Yes. Ov. Okay. S Satan ov. Why didn't you keep the stress in the same spot? It would've made it a lot easier for me. Yeah. I didn't choose those. Yeah, that's okay.

 

Tzvetan Mikov:

It's been a problem.

 

Jamon Holmgren:

Tell us a little bit about yourself. Where did you grow up and how'd you get into tech, that sort of thing.

 

Tzvetan Mikov:

Oh, well, okay, so that's a long and boring story. I grew up in Bulgaria during communism it was, well, that's a different topic. Anyways,

 

Robin Heinze:

I can do a whole episode on that.

 

Tzvetan Mikov:

I'm sure I was maybe fifth grade when I started seeing magazine articles about computers, but computers were really actually hard to come by in Bulgaria at that time, even though we would manufacture them for the entire Eastern block, nobody could buy one. They weren't available, but I really got into it, so I bought books. I read the books without ever having touched the computer. I made a keyboard out of carton, draw the letters there and started practicing, started writing software in a notebook without, again, without having touched the computer. That's amazing.

 

Robin Heinze:

Yeah. That's like a whole new level of pseudo code.

 

Mazen Chami:

Yeah. Well, he wrote all the code and then eventually got to where he's at and wants to now compile all that code. I see where the story is going.

 

Jamon Holmgren:

That's where this is going. This

 

Mazen Chami:

Is where I'm going. I see it.

 

Tzvetan Mikov:

And then eventually I was able to get to the single computer in my school, and the teachers, their credit were very helpful, so I was able to get some actual coding in to type in the computer. All that software had already written, but this was still like a hobby. And then I won a programming competition in the school and they gave me a box of floppy discs, which at that point were very expensive and I was hooked. It's like, oh, I can get stuff from this. I was hooked very early

 

Robin Heinze:

On and all of a sudden it was portable.

 

Tzvetan Mikov:

Yeah,

 

Robin Heinze:

You used to bring computer programs on a floppy disc in a boat to somewhere.

 

Jamon Holmgren:

Yes, yes. This is a whole thing. Previous episode, I went all over that.

 

Robin Heinze:

That's amazing.

 

Jamon Holmgren:

That's how it started,

 

Tzvetan Mikov:

I don't think.

 

Jamon Holmgren:

What language were you writing pseudocode in

 

Tzvetan Mikov:

Basic, of course, apple two

 

Jamon Holmgren:

Basic. Yeah, that's where I started too. Eventually graduated a qba and yeah, then started making little games and yes, like Robin said, I brought 'em to my cousin's house on a boat to an island with a floppy disc. Now were these like five and a quarter floppies that you got?

 

Tzvetan Mikov:

Yeah, of course.

 

Jamon Holmgren:

Like the really big floppies.

 

Tzvetan Mikov:

Yeah. Yeah. 360 kilobytes. If you use both sides or something like

 

Jamon Holmgren:

That, if you use both sides, you have to flip it.

 

Tzvetan Mikov:

Right.

 

Jamon Holmgren:

That should be good enough for anybody. Right? That's enough. You shouldn't need more than that

 

Robin Heinze:

Teaches you to be efficient.

 

Jamon Holmgren:

Right. That's pretty awesome. Thanks. We are going to get into our topic today, but before we do that, I do want to talk about our sponsor, which is Surprise Infinite Red. Infinite Red is a Premier React native consultancy. We are located fully remote in the us. We don't have anybody in Bulgaria. We're a team of 30 senior plus level React native developers and support staff, and have been doing this for basically a decade now. We're working on it. It's getting close, and if you're looking for React native expertise, just hit us up at Infinite Red slash Radio and don't forget to mention that you heard about us through the React Native Radio podcast. Alright, our topic, our topic today is about static Hermes, and we're obviously talking with Ton has been leading that team for how long now? At Meta?

 

Tzvetan Mikov:

Well, I've been leading the Hermes team since

 

Jamon Holmgren:

2016. Yeah, so way back in the beginning. Well, before it was even

 

Robin Heinze:

Almost a decade ago

 

Jamon Holmgren:

Announced. Yeah, that's right. Wow. Yeah, that is a long time. I didn't actually know that Hermes goes back that long, that that is something else.

 

Tzvetan Mikov:

Yeah.

 

Jamon Holmgren:

Yeah, so that's pretty amazing. Of course, we got the first word about that from Mark at the 2019 chain React, and that's where it was sort of, well, Hermes itself was announced and then Static Hermes was then announced in, I think 2013, or sorry, 2023. Is that correct?

 

Tzvetan Mikov:

Yes, I think, yeah, in direct Native Universe.

 

Jamon Holmgren:

Yeah, that's right. Obviously it's been a work in progress all along. You've had this amazing team, but yeah, okay. We're app developers here. Most of our audience are app developers. They're JavaScript developers, they're TypeScript developers. There might even be a few flow developers in the audience. We don't know, but we need you to dumb this down. Pretend that we don't know what Bite code is, we don't know what machine code is, we don't understand how computers work. We just write JavaScript and somehow magically boxes that are colored in the right ways appear in the right place on the screen. Not to reduce our jobs down to that, but it's mostly that. That's what I do.

 

Mazen Chami:

I dunno what you're

 

Jamon Holmgren:

Talking about.

 

Robin Heinze:

I know you put the word pretend in front of all that, and I don't dunno how much pretending you have to do.

 

Jamon Holmgren:

I know. So explain like we're five, what is Hermes and how does it benefit us as JavaScript and React native developers?

 

Tzvetan Mikov:

Well, okay, that takes me back to those early years when we open sourced it and we had to construct a really good case for it. So as I'm sure you know, JavaScript engines traditionally just consume JavaScript source directly. They take it and they run it, but running something directly from source is fairly expensive.

 

Tzvetan Mikov:

You have to passe that source, you have to compile it into some internal data structures. You have to validate it for things like missing identifiers and whatnot. Then you have to optimize it and you have to execute it. So that's a lot of upfront work that must occur before that JavaScript source starts running. And to this day, I see people even using Hermes with Eval a lot, and I don't think that it has been internalized how expensive that is. Even at the best of engines, even in VA JavaScript core, these heavy duty desktop engines, even with them, this takes work parts that source to analyze it, to validate it, and finally to convert it into a source, into a form that's convenient for execution. So with hermis, we have done something that is not particularly innovative, but it's may be innovative when applied to the JavaScript space. We've done essentially what Java does, take the source, do all of those things that I described ahead of time in the Kamp, and then produce an output that we call Bite Code, which can be executed directly without any of those steps. Again, that's what C does, that's what Java does. That's what we are doing. Really, the innovation is from applying this to Javas,

 

Robin Heinze:

You're putting the Java back in JavaScript.

 

Mazen Chami:

Exactly. Yeah. Real quick, before you continue fatten, at what point in the pipeline does this happen? Does it happen during Hot Reload or just at bundle time? When does this happen?

 

Tzvetan Mikov:

So for a production app, this happens after bundling currently after Bebo has been run, after Metro or whatever package is being used, which produces a large JavaScript bundle, and then that goes to Hermes, which produces somewhat smaller bite cold bundle.

 

Mazen Chami:

Is that still the case in development or is Hermes running every single time? My JavaScript bundle changes in development. So when I save my file, does it run through that entire pipeline again?

 

Tzvetan Mikov:

No. So in development, hermit actually runs the source from Source without compilation to bytecode. And this is really funny because Hermit initially didn't even have support for that at all. We didn't have eval, we didn't have the function constructor. It had none of that. And we added it as a joke to see whether we could to just

 

Jamon Holmgren:

Really, this seems to be kind of a theme here, just like, oh, can we do this? And then it turns out to be pretty useful.

 

Tzvetan Mikov:

And the React native folks just took it without asking and we didn't even know it was bu. Oh, no. And then we saw Fast, is it called Fast Reload or Fast Refresh?

 

Jamon Holmgren:

Fast Refreshness, fast Refresh

 

Tzvetan Mikov:

Called Fat. Yeah. And we saw it in how did you guys do this with Hermits? Yeah, so we've invested a lot of effort into making Hermits run acceptably directly from Source, but that's to be used only in dev mode.

 

Robin Heinze:

It sounds like the React native team is separate enough from the Hermes team. Was Hermes originally intended for React native or was it a separate project that just ended up being useful for React Native? How did that kind of happen and come about at minute?

 

Tzvetan Mikov:

Yeah, we are very separate teams. We are in different orgs, different management structures. Yes, Hermes was intended for React Native from the very start. That's what it was conceived. It wasn't intended only for React Native, but React Native was one of the major motivating use cases for us.

 

Mazen Chami:

So as React native has evolved over time via Flow, JavaScript, TypeScript, all these coming in, has that really changed how Hermes works underneath the hood?

 

Tzvetan Mikov:

Well, recently with static Hermes, that's the whole thing of static Hermes that we want to consume flow and type stream directly. So that's how we have changed. Previously, we just were focused on doing optimizations with React Native to make the startup faster. So we worked really closely with them to measure what happens during startup, how many objects are created. It turns out, for example, that tons of functions are being created and every function has a name, has a length property, and all of these things, if you multiply by 50,000 functions

 

Tzvetan Mikov:

To

 

Tzvetan Mikov:

Initialize at startup takes a long time, for example, things of that nature. We were trying to very heavily optimize influenced by real production React native bundles.

 

Jamon Holmgren:

And so JavaScript core obviously was the engine that was used primarily prior to Hermes, and I think some people use V eight as well. There are a few who will drop in V eight. Can you basically use any JavaScript engine and just drop it into React native? Is there a lot of work that has to happen to make that happen? And then also, you already mentioned startup time. Was that the primary problem with all the existing ones?

 

Tzvetan Mikov:

Yes. The primary problem was startup time and the secondary problem was memory consumption. The jits being a little bit unpredictable in how much memory they'll consume and when they'll be able to optimize something,

 

Jamon Holmgren:

Right? Because those engines have just in time compilers, which allow them to basically optimize on the fly by sampling and analyzing how the code is behaving and more or less optimizing specifically for that. Something that Apple doesn't let us do, we're not going to get too far into that, but it doesn't let us do with any custom engines.

 

Tzvetan Mikov:

Yeah, apple doesn't let us produce machine code, which is the code that the C CPU executes. I know you know that, but I Doing what to ask? No. Yes. Yeah,

 

Jamon Holmgren:

Don't

 

Robin Heinze:

Jamon knows it, but I think a lot of our audience probably doesn't,

 

Jamon Holmgren:

Bean knows why I know this. It's because I've sent him hundreds of stupid messages over the past three years, five years, I don't know. Just saying, okay, so this is my mental model. Tell me why it's dumb. And he very nicely helps me out. So

 

Robin Heinze:

I mean honestly, a lot of React native developers, for better or for worse, don't have a mental model, know how this all works and it's because, I mean, you can easily get away with not having one because it kind of just works and it does its thing behind the scenes, but it's such a level up too to understand it as an app developer because it lets you do more with native integrations. It lets you debug better and faster when you're getting native errors. Just understanding what you're shipping better makes you a better developer.

 

Jamon Holmgren:

I agree. So

 

Robin Heinze:

That's why we're doing this. We want to help the people out there that don't understand this to form that mental model.

 

Jamon Holmgren:

And by the way, this is just a quick episode on a podcast. I would love to do more deep dives on this stuff because this is a huge rabbit hole. So many things we can do more episodes. I'm planning on actually reinvigorating my Jam's Code Quest YouTube channel to explore some more Hermes and other related things. I did one episode already on it, but our time is going by quicker than I expected. Of course, as usual, there's more I want to talk to you about with Hermes itself, but let's move to static Hermes because that's the title of the episode. So a few years ago, as you kind of alluded to, you wanted to start taking advantage of the type information. So flow and TypeScript come with type information. In other words, instead of just being a variable that is defined with constant FU equals whatever or let FU equals whatever, it actually is annotated with the type that we expect with TypeScript and Flow. Turns out that information is actually useful to you on the compiler level. Can you explain why this was interesting to you? And we'll talk about the compilation to machine code later, but really more on the optimization level. I kind of want to hear your thoughts on that.

 

Tzvetan Mikov:

Yeah, so I mean we were thinking about how to take Hermes to the next level in terms of performance without making it much more heavyweight on the runtime side. So what can we do to make it faster without essentially Reimplementing V eight or JavaScript core because that wouldn't make sense. They already exist, they're great, but we are aiming for a slightly different use case. The cost in the executing JavaScript is from all of the uncertainty. You don't know the type of something. So at run time you have to check it. And what the just in Time Camp powers typically do is they speculate. They assume that something is a certain type after they've observed it for some time and they generate a bunch of code based on that assumption, and then they have to check every time, does the assumption still hold true? And if it doesn't, then it's an extremely complicated process to the so-called de optimization

 

Tzvetan Mikov:

To

 

Tzvetan Mikov:

Go back to less optimized code that doesn't execute with that assumption, but it's slower. So this is all very complicated, very effective to a degree, but also very complicated.

 

Jamon Holmgren:

Just to stop you for a second, because I think this is a super important point. You write a function in JavaScript and if you had a just in time compiled engine or compiler engine, you run this function and the first 3000 times it runs, you're getting a float, like a number as the parameter of that function. And so just in time compiler says, okay, well, instead of saying, okay, is argument one a string, is it an object? Is it an array? It's checking all these things. It says, okay, it's a number, so let's check is it a number first and then just run this code that we have optimized for it being a number. Everything up after it. You don't have to check anymore because it's a number, but it still has to check if it's a number. It still has to say, okay, if it's not a number, then it has to go back to the old way, the de optimized way of checking every possible thing. And just a general principle of programming and computers, they're running at the same speed. JavaScript, Ruby, c plus plus, all these things are running at the same speed. The only difference on the same clock speed. The only difference is how much work they're doing to

 

Robin Heinze:

Do the same

 

Jamon Holmgren:

Result.

 

Robin Heinze:

That's what makes one language slower than the other. Exactly.

 

Jamon Holmgren:

That's not

 

Robin Heinze:

Easy. It's literally just doing more. It's not optimized.

 

Jamon Holmgren:

Exactly. Skipping a bunch of the code pads and code to just get back to working on the other things. So does that make sense? And then yeah, hopefully that kind of sets the scene there.

 

Robin Heinze:

On that point, I found it really interesting that you explained to me last week that console log, just like your regular console log is doing that. It's checking the type. It's just like going through all the types, trying to figure out what it is before I can print it out, which is why they're so expensive to leave in your production code. It's crazy to me anyway.

 

Tzvetan Mikov:

Exactly. Yeah. I mean this is a fascinating way to look at it, that they all run at the same speed, but they do different amounts of work. Yeah, I remember that. That is very cool.

 

Jamon Holmgren:

That was kind of a breakthrough for me because I don't know, you just have this impression if you have a really fast car versus a very slow car, they go at different speeds, but they're doing the same amount of work, but it's different with a programming language. The clock speed is constant. It doesn't change. You're still,

 

Robin Heinze:

It's determined. Same computer, it's determined by your machine and your processor, how everything goes. It's at the rate that your machine can process it.

 

Tzvetan Mikov:

But what if it was a tractor?

 

Robin Heinze:

If it was a Kubota has one speed. It is good

 

Tzvetan Mikov:

Slow.

 

Jamon Holmgren:

My speed gym is speed. My top, the top speed of my Kubota is eight and a half miles per hour. And don't forget the half because that matters.

 

Todd Werth:

That's why JavaScript is JavaScript is a tractor, is the tractor eight and it's attractive.

 

Jamon Holmgren:

No, no, but really when it comes down to it, why is c plus plus fast? Well, it's fast because tons of companies have put tons and tons of money into optimizing and basically coming up with tricks more or less on how to get to the result faster. And that's what you're doing here too,

 

Robin Heinze:

And it's fast, but you have to, but you also have compiled it. You've done a bunch of work on it prior to running it. That means when it's running, it's fast.

 

Jamon Holmgren:

That's right. The compiler has all those built-in optimizations.

 

Robin Heinze:

Exactly.

 

Jamon Holmgren:

Anyway, I interrupted you. Go ahead.

 

Tzvetan Mikov:

Yeah, so we were talking about how to get Hermes to the next level performance wise, and there are all tricks that we could do at runtime or we could do profiling ahead of time and then somehow try to use that, which is, by the way, a trick that we still have in the bag and probably will do. And then I thought, what if we just try to cut the Guardian knot? I just, let's eliminate all that complexity. Let's just use the types that the developers have already put there, and that should in theory, allow us to run with the same performance as C plus was, which is amazing. Yeah,

 

Robin Heinze:

Well, but it's not groundbreaking for, like you said, for a Java developer that would be like, well, yeah, of

 

Tzvetan Mikov:

Course. Exactly. Although ironically, Java didn't have ahead of time compilation to Native coal until fairly recently with Grow before that. It wasn't really, but yeah, anyway, so that's how it started. It was just a quick experiment. Could we implement this little procedural language that vaguely looks like JavaScript but is actually based on flow and TypeScript? It turned out to be much harder than we thought. Much, much harder.

 

Jamon Holmgren:

Classic. These things always are,

 

Tzvetan Mikov:

The difficulty actually doesn't come from the type language. It comes from the realization that there will always be tons of typed codes in a real React native application. So that code has to continue to work, it has to be fast, and you have to find a way for the typed code and the UN typed to coexist. That's where the main challenge is. That's what has taken the majority of our time.

 

Jamon Holmgren:

And when you have typed code and typed code interacting, that means the un typed code could be sending the wrong type to a typed function, and so your annotation is wrong. So you still need some protections in there for that.

 

Tzvetan Mikov:

Yeah, I think if you know Java, the best way to think about this is reflection.

 

Jamon Holmgren:

Okay. Reflection being where you can inspect the actual objects and whatnot to see what methods they have and what types they are and things like that.

 

Tzvetan Mikov:

That's part of it. So typically in Java, when you call a method directly, the compile time will ensure the types of the parameters are correct. So that's where static typing comes from. So then these checks don't have to occur at runtime. I'm simplifying a little bit, but you get

 

Jamon Holmgren:

Yeah, that makes sense.

 

Tzvetan Mikov:

But if you use reflection that allows you to call any method dynamically with any parameters, and then at turn time, the types of these parameters, again, at turn time, a great expense has to be validated against the actual types that the statically type function expects. So it's exactly the same with static Hermes. If UN typed codes calls type code, there has to be a validation step.

 

Jamon Holmgren:

Yes.

 

Mazen Chami:

Can I ask a follow up to that then? Let's say as an app developer, is it in my best interest to make sure my app at the end of the day is very performant and all these steps are optimized? Is it best for me to make sure that I'm typing as I'm using TypeScript typing every single

 

Robin Heinze:

Basically

 

Mazen Chami:

Constant, every single function input and output of them, should I be incessant about just everything is typed so there's no gaps? I have strict mode on everything is typed, there's no gaps along the way. Is that better for me or not? Or it doesn't really matter at the end of the day?

 

Tzvetan Mikov:

Well, it's hard to say because we have to balance with convenience of JavaScript. If you're forced to type every single thing, it becomes a little bit annoying.

 

Mazen Chami:

It does. And with IntelliSense, right, TypeScript these days, it can infer what my return type from the function is. Right. But it sounds like you are still going to have to run through the validation to make sure that it is a number that is returned, for example.

 

Tzvetan Mikov:

We can infer that too, hopefully.

 

Robin Heinze:

Yeah. I was going to ask, does the TypeScript compiler, do the inferred types get translated then to more definite types for her sig?

 

Tzvetan Mikov:

Yes. I mean, we have to implement the inference independently for TypeScript. We have to match what they're doing. And one problem with TypeScript, not only TypeScript four has that too, but in TypeScript it's more pronounced is that a lot of the types in TypeScript are actually unsound. So even if something is typed, that doesn't mean that this type is usable for optimization. True.

 

Robin Heinze:

You see that a lot. I mean, ultimately it comes down to the fallibility of developers

 

Jamon Holmgren:

And the fact that TypeScript is and flow are supersets on top of JavaScript because if you have something like Elm or maybe Reason Rescript, et cetera, where they have sound types, you can rely on the types a lot more. But like you said, they're annoying. Actually. The flexibility of JavaScript is pretty amazing, and I've been been a big proponent of embracing that as a strength of TypeScript more so than a weakness. And I've done Elm, and if you want to do Elm, go for it and enjoy yourself, and you're probably going to get less done than me at the end of the day. What's going to happen with TypeScript? And I do like Elm. It's not like I don't, it's just a different paradigm. Have you thought about with static Hermes, and we do want to get to the binary compilation stuff as well, because bite code is really another representation, more or less of the JavaScript in some ways. You're just running it, you're not running it directly, you're running it through an interpreter, through an engine. But have you thought about having a mode in Hermes where you can turn on, Hey, tell me where you're Deming and let me provide some hints in those areas so I can help you basically do your job better. Is there something like that already?

 

Tzvetan Mikov:

There isn't, because I mean, this is a complicated topic, but Hermes doesn't have the ops. This is what it is. That would not be, I mean, that's something to think about, but no, we don't have anything like that today. This makes a little bit more sense in the context of a speculative jet because the jet constantly makes these guesses, and when the guesses fail, the jet can tell you, look, I tried to guess here many times and I can never guess it help

 

Tzvetan Mikov:

Me.

 

Tzvetan Mikov:

In our case, I think this would be somewhat roughly equivalent. Profiling your codes, finding the hotspots that are slow, and just adding type of notations there

 

Jamon Holmgren:

And seeing if that helps. Right, exactly. Yeah, that makes sense. Let's talk about native code, machine code. What do you call it? What do you call the binary that is running on the arm processor?

 

Tzvetan Mikov:

I don't know. Machine code, I guess I don't code it anything because for me, that's the natural state of things. It's just code. Yeah, it's just code. David. That's

 

Mazen Chami:

Code. Everything else is an imposter.

 

Robin Heinze:

Yeah,

 

Mazen Chami:

I think, let me ask you a question here. So we're typing our app in flow, JavaScript, TypeScript, right? For simplification, let's skip all the metro and all this other stuff that's happening along the way comes into Hermes's. First of all, what is Hermes's written in? What is the language you all are using?

 

Tzvetan Mikov:

C plus plus.

 

Mazen Chami:

C plus plus. There we go. Okay, so we take our front end code, pipe it into TypeScript, it does its job. What is spit out on the other end?

 

Robin Heinze:

On the end of Hermes?

 

Mazen Chami:

Hermes? Well, bike code.

 

Robin Heinze:

Bike Hermes bike code HB

 

Mazen Chami:

Cs HBC, Hermes bike code. Yeah. Cool. Now that Hermes bike code, where does it live within the app as far as when it comes to my bundle? Right, so we're outputting a bundle that we're

 

Robin Heinze:

Going to your IPA file or your A PK,

 

Mazen Chami:

The one that gets pushed up to the stores. Where does this HBC live within that? Can we call it wrapper for simplification here? I feel like I'm simplifying it, but I'm complicating it by trying to simplify it. But I think you see where I'm kind of going with this HBC code that comes out on the other end of Hermes from my JavaScript TypeScript or Flow. Where does that live in the larger context of the app that gets submitted to the store?

 

Tzvetan Mikov:

I mean, it lives in the same place where the JavaScript source would live. It's just a file, separate file or resource package with the app.

 

Mazen Chami:

So it's still the JavaScript bundle

 

Robin Heinze:

Is, but it's just not JavaScript anymore. The bundle is Hermes's bike code,

 

Mazen Chami:

Bike code

 

Jamon Holmgren:

Bundle. I could be wrong. Sorry for those of you, I would just go look, but don't have time right now. I think it's literally still called main JS bundle, and so it's the same as the JavaScript thing. It's just her's bike code under the hood. You go try to open it, it says it's binary,

 

Robin Heinze:

And your app also has to include the Hermes engine along with it in order to run the Hermes bike code because iOS doesn't know how to run Hermes bike code. Right?

 

Mazen Chami:

Yeah. And I also, I made that simplification because I also came to the realization not long ago where I thought looking at that main bundle JS, I was deploying again, again, simplifying, deploying a JavaScript file,

 

Robin Heinze:

Which used to be true. That used to be true, and that's what JavaScript core was running the JavaScript directly.

 

Mazen Chami:

And I thought Hermes would come in, do its compilation, do its optimization, but then still spit out a JavaScript file for you at the end, and then that lives in the larger context. But I think that's good to know that it's no longer

 

Robin Heinze:

No, no. It's spitting out its own machine like white code.

 

Tzvetan Mikov:

Yeah. Yeah. Interesting. We did have such a project to optimize JavaScript and speed up JavaScript, but unfortunately it died. Okay,

 

Robin Heinze:

So it's not like a totally off the wall thing to assume that it was doing.

 

Jamon Holmgren:

Yeah. Hermes's byte code at the end of the day is kind of in some ways a compression strategy. Is there anything more it's doing or is it basically the same as a bundled optimized JavaScript? I guess you can add other information in there because you control the format.

 

Tzvetan Mikov:

Well, that's a very interesting way to think about it. Yes. In many ways it's a compression strategy and that's why the Hermes bundle compresses a lot less than JavaScript because the entropy differ, but it's not a very direct representation of the JavaScript source. Wasm by comparison is kind of a binary compression thing, which very few people realize. Wasm is just a binary encoding of an A ST of a

 

Jamon Holmgren:

Web assembly. Yeah.

 

Tzvetan Mikov:

So web assembly is just a binary encoding of an expression tree. I take an expression, it left to right to left. Let's not go into details. And that's web assembly. It's very simple. Fundamentally, it's just a stack based machine while Hermes bytecode is really, when you look at it, it's very, very unlike the JavaScript source, it has been very heavily transformed. It's register based, it has very low level operations, so it's kind of a different concept.

 

Robin Heinze:

I mean, if you just inspect it, it looks a lot like binary. It's not able to be interpreted by the arm processor, just like binary would be. But I mean, it's essentially what it is.

 

Jamon Holmgren:

The tool. Is it HBC dump that will show what looks like assembly, one of those tools anyway?

 

Tzvetan Mikov:

Well, the best tool is just to use Hermes itself, Hermes dash dump by code, and then you give it the file. HBC dump also works, but it's a more specialized tool. It's not that convenient.

 

Jamon Holmgren:

Oh, I didn't actually know that. I'm going to have to do some more research on that, man. Like I said, this rabbit hole goes quite deep. We can do 10 episodes. I don't want to spend any more time there because we really have to talk about the actual machine code side of it. So when you compile a static Hermes, the nice thing is that you can actually output platform specific machine codes. So for example, you want to target ARM 64 that runs on Apple silicon or something like that, like an actual, an iPhone. You can compile your JavaScript, your type script into that. And by the way, from what I understand, you can compile straight JavaScript to it as it doesn't require types. It just won't be optimized. You told me a while ago I had asked about this and you said, yeah, you totally can compile just let's say an older just JavaScript only app into binary. It's just not going to do a lot of good for you because it's not going to be very optimized. So it'll run more or less about as fast as Hermes interpreting would. But then once you add the types and you go straight to binary, it's almost like those two things are somewhat decoupled in a way. You could have done it before, you could have done the binary thing before, but now this makes it worth it.

 

Tzvetan Mikov:

Yeah, yeah. It's very interesting. If you compile UN type JavaScript to native in a straightforward manner, it doesn't become faster. It's almost shocking. It's very disappointing. It's like, look, we compiled it to native, there's no interpreter, but why does it run with exactly the same speed is this,

 

Robin Heinze:

It's doing the same amount of work. It's not doing less work, it's just doing it in native instead of in JavaScript.

 

Tzvetan Mikov:

Right? Right. But it's very as if we've encountered a law of nature, like the speed of light.

 

Robin Heinze:

So I mean, it seems like, it feels like a big takeaway here is that typing your code is one of the biggest things you can do to improve performance with static. Static

 

Tzvetan Mikov:

Hermes

 

Robin Heinze:

With static Hermes, because static Hermes is not going to really give you any gains if your app is entirely typed JavaScript.

 

Tzvetan Mikov:

Oh, well. So it it'll give you gains. So I wanted to mention that a little. What you said was correct in 2023, but our vision has evolved a little bit since then. So we implemented the jet for static Hermes, which speeds up typed code. It speeds up type code even more, but it also helps on type code. So static Hermes helps you there. Also, our vision for the native compilation has evolved a little bit. One really strong constraint that we had initially for the native backend is that we didn't want to produce very large binaries. If you want to compile your entire app to native, then it might become really huge. But since then we introduced the jet and other technologies. So now it seems like maybe you want to compile only parts of your app to native, and then we can afford to have a different code generation strategy for native, which is actually much faster. This opens up really fascinating possibilities. So on iOS, even JavaScript core, when running React native cannot, JIT cannot produce native core. So even Apple's own technologies, Hobart on iOS, which is good for us in a way because it allows us to compete on more equal footing, but with static Hermes, you can take your regular typed Java slip code, compare it to native and run it on iOS with much higher performance, even though it's on type.

 

Robin Heinze:

That's amazing.

 

Jamon Holmgren:

And it's sort of optimizing to byte code to native to

 

Robin Heinze:

Native,

 

Jamon Holmgren:

Native

 

Robin Heinze:

Machine

 

Jamon Holmgren:

Code.

 

Tzvetan Mikov:

You shouldn't do that for your entire app, but you pick spots, compile them to native, and they'll run fast on iOS really

 

Jamon Holmgren:

Fast. That's awesome. And actually, really quick curiosity question. If I were to use static Hermes and ignore your advice and just go ahead and compile the whole thing, which is possible You've done this, I think you have.

 

Tzvetan Mikov:

Yeah,

 

Jamon Holmgren:

And yes, huge binary whatever, I would not have to ship the Hermes binary with my app. Then it's like I'm good, right?

 

Tzvetan Mikov:

Right. But you have to keep in mind that in a way you are shipping. It's just part. It's

 

Jamon Holmgren:

Just in your binary. Right. Wow. I have so many more questions. Okay.

 

Robin Heinze:

This is what happens every time jamon talks to spit

 

Jamon Holmgren:

Talk. It's true. If that happens, is it putting all of its functions into that binary or does it only put the ones that your code seems to need, for example?

 

Tzvetan Mikov:

Well, that's the thing about JavaScript. You never know for sure what will get executed. There's no way to detect because it's so dynamic, you have to afford that every single ecwa script function may be invoked.

 

Jamon Holmgren:

That's why it all lands in there.

 

Mazen Chami:

Yeah, yeah. It's like a tree. You almost need every single branch to know which one you're going to take, right? Because you can't just assume that, okay, no, this is going to be a number and only ship me my number, but in turn something else runs through it.

 

Jamon Holmgren:

You can call methods with strings and those can be dynamically generated at runtime. So you could construct console, square bracket and then give it a FU function in that FU function. Could be log, but you just don't know that, so you have to ship log with it no matter what. Yeah, that makes sense.

 

Mazen Chami:

I have a question that's more related on React native in general. So when we made the pivot to new architecture, new architecture of the whole thing was c plus plus and speed and all that kind of stuff, and Hermes is C plus plus, was that a positive for Hermes that we're looking at c plus plus code rather than what was previously there for speed also? So we're talking about same language as talking to each other, or does it not necessarily matter because Hermes is only looking at your JavaScript type script on flow code, and then at that point it's down to the machine level code, so it's fast regardless?

 

Tzvetan Mikov:

I don't think the difference between the new and the old architecture is that large in terms of the programming language, it was c plus plus before as well. Yeah. However, I'm really not a big expert on the internals of React Native, and I should say that at Meta, I believe we've been running the new architecture for a long time that I even forgot about the old architecture. But in practical terms for Hermes, for us, it did not make a huge difference. Although the introduction of Hermes is what caused us to develop JSI and JSI is what enabled the new architecture.

 

Jamon Holmgren:

Yes. Yeah. The core API of Hermes became very useful outside of it. Okay. I have two last little questions here. One is that do you anticipate Hermes being used outside of the React native context for other types of things?

 

Tzvetan Mikov:

Well, I don't know whether I anticipated, but I would love for that to happen. I've complained many times on Twitter that people outside of React Native don't realize that Herman even exists. While I think it's pretty awesome,

 

Robin Heinze:

It is, it doesn't get enough. It doesn't get enough attention and love for how awesome it is, and it works so well that it's just like it's invisible.

 

Tzvetan Mikov:

Oh, stop. It has a share of problems, but let's not talk about them.

 

Robin Heinze:

That's what I say about MyCode.

 

Jamon Holmgren:

I feel like, again, I love this topic. It's one of my favorite topics. I love the technology. I think it's super fun. Years and years and years ago was like, why can't we compile JavaScript to Native? I was like, we should be able to do this. And there are some attempts out there, but this is really the one that I think has hit the mark much, much better, and it's actually out in production and being used. When do you think static Hermes is going to be at a point where, I don't know, I guess obviously stable is a big question, but do you have a target for a stable, like, Hey, this is going to hit your master, your main branch on your repo, it's going to be the primary way you ship it, et cetera. Do you have any sort of idea on that?

 

Tzvetan Mikov:

Yes. Yes. So in order to explain that idea, I have to very quickly say that, and this is mostly my fault, people have a little bit of a misconception what static hermit is. Static Hermit is a super set of hermit in many ways. It's just the next version of Hermit that does all that hermit does, but better, and it is already replaced Hermes, and it'll definitely become the default in React Native instead of Hermes this year in terms of running the existing typed code just like Hermes does, but a little bit faster, a little bit better. If we're talking about the typed features of the language when they are going to become mainstream, so to speak, that is a much harder question. We certainly want that to become a CP, but there are ecosystem problems around that. I don't know whether I would be sharing too much, but it is our absolute goal is to completely get done with all the features of the type language this year before the middle of the year.

 

Jamon Holmgren:

I mean, obviously we're not going to hold you to it, but it's nice to know that it's drawing closer because I know this has been a labor of love for a long time, which is pretty amazing. Very last question, conceivably, could you write static Hermes or Hermes entirely in flow type script and compile it, the compiler and the engine from that? Like dogfooding it?

 

Tzvetan Mikov:

Well, you can write the compiler in TypeScript or Flow. You can't write the engine because you need to implement a garbage collector. Well, okay. Okay.

 

Jamon Holmgren:

I just gave him ideas.

 

Tzvetan Mikov:

Unfortunately, I am not, I'm thinking too much in the box. Lemme take that back. Yes, you can. It'll not be pleasant. I would not recommend it, but it is actually possible.

 

Jamon Holmgren:

It's possible. That's wild. I don't know. There's something about building a languages compiler and potentially engine in that language. I don't know. That's wild to me. Alright. Anyway, let's wrap up. Editors are already going to be a little upset at us for how long this has gone and we didn't touch on half the things I wanted to touch on. Thanks so much. S Satan, this has been absolutely wonderful. I appreciate you coming on. I know that we've talked about it for quite a while here, but it finally happened and I consider you one of the most brilliant programmers that I interact with. I really love your energy and your passion for this stuff. I think that your whole team is this way. It's really fun to, I just love the whole team. You have a fantastic team there at Meta and so thanks for working on this. It certainly makes our lives better as application developers. Yeah, can't wait to see Static Hermes's roll out and what we can do with it.

 

Tzvetan Mikov:

Well, thanks for having me. As you can tell, I really love to talk about Herman, so I really appreciate this.

 

Jamon Holmgren:

I'm the same, so awesome. Well, thanks everybody. We're going to have to wrap up quick here, so if you want to find us, you can find us online at React native R dio on Twitter. You can find Ton at TM IKOV on Twitter as well as I'm sure. What are you on GitHub? Same. Is it? Same. Same. Okay. And yes, so thanks so much. As always, thanks to the whole crew here and we will talk to you later. Bye

 

Tzvetan Mikov:

Bye. Bye.

 

Jed Bartausky:

As always, thanks to our editor, Todd Werth,, our assistant editor, Jed Bartausky, our marketing and episode release coordinator, Justin Huskey and our guest coordinator, Mazen Chami. Our producers and hosts are Jamon Holmgren, Robin Heinze and Mazen Chami. Thanks to our sponsor, Infinite Red. Check us out at infinite.red/radio. A special thanks to all of you listening today. Make sure to subscribe to React Native Radio on all the major podcasting platforms.

 

 

Photo of Gant Laborde and Mark Rickert hugging at a retreat.Photo of Todd Werth laughing during an online team game. Other members of the team are in the background.Photo of team members Jed Bartausky and Carlin Isaacson at a team dinner.Photo of Darin Wilson sitting at a table listening to a presentation

Ready to get started with us? Chat with our team over zoom

There’s no perfect time to get started. Whether you have a formal proposal or a few napkin sketches, we’re always happy to chat about your project at any stage of the process.

Schedule a call