Refactoring to Rust MEAP V07 (Lily Mara, Joel Holmes) (Z-Library)

Author: Lily Mara, Joel Holmes

教育

Get the speed and reliability of Rust libraries, functions, and high-performance features through incremental adoption without rewriting your codebase from scratch. In Refactoring to Rust you will learn to: Create Rust libraries you can call from other programming languages Integrate Rust functions with code in other languages Use Rust’s ownership and borrowing system to write high performance code Handle errors as values using Rust’s enums Minimize unnecessary memory usage with Rust’s multiple string types Boost performance with Rust concurrency and async event processing Create Rust HTTP services Refactoring to Rust teaches you how to take advantage of Rust’s easy-to-use interoperating mechanisms. Learn practical code-mixing techniques like embedding Rust libraries into apps written in other languages. This practical guide emphasises techniques for incrementally refactoring performance-critical code to Rust while keeping the rest of your application in its original language.

📄 File Format: PDF
💾 File Size: 6.1 MB
51
Views
0
Downloads
0.00
Total Donations

📄 Text Preview (First 20 pages)

ℹ️

Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

📄 Page 1
(This page has no text content)
📄 Page 2
MEAP Edition Manning Early Access Program Refactoring to Rust Version 7 Copyright 2024 Manning Publications For more information on this and other Manning titles go to manning.com ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 3
welcome Thank you for purchasing the MEAP for Refactoring to Rust! Rust is one of the most exciting new languages out there. Consistently rated as the “most loved” language by the Stack Overflow developer survey, many developers wonder what about Rust makes its users so happy. In our development jobs, it can be difficult to get management buy-in to start up a new service around a language that may never have been used at the company before. Instead, replacing a small part of performance-critical code with Rust might be a more effective first project. This book intends to give you the tools and skills required to make a surgical refactoring like this possible. The chapters in this book will take you through the areas where Rust differs the most from other languages, introduce you to embedding Rust within a C program, using the Py03 library to embed Rust in Python, as well as testing, profiling, and monitoring your refactored code to ensure that it’s performing within expectations. Refactoring to Rust is intended for developers that have some familiarity with Rust already. I hope you can benefit from the instruction in this book, and it helps you on your journey to writing faster, safer, and simpler code. I also encourage you to post any questions or comments in the liveBook Discussion forums. Just like software development writing is an iterative, collaborative process, and you as the MEAP reader are an important part of that process. I had a lot of fun writing this book, and I hope you enjoy reading it. Please leave comments at liveBook's Discussion Forum. Thank you again for purchasing Refactoring to Rust! — Lily Mara ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 4
brief contents 1 Why Refactor to Rust 2 An overview of Rust 3 Introduction to C FFI and Unsafe Rust 4 Advanced FFI 5 Structuring Rust libraries 6 Integrating with dynamic languages 7 Testing your Rust integrations 8 Asyncronous Python with Rust 9 WebAssembly for refactoring JavaScript 10 WebAssembly Interface for Refactoring (Almost) Anything ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 5
1 This chapter covers If you have ever heard of the Rust programming language, you may have heard of software companies rewriting their code in Rust from a slower, interpreted language. A few of these companies have published blog posts lauding the performance benefits of Rust over their previous systems, and they tell a very tidy story: other languages are slow and Rust is fast. Therefore rewrite your code in Rust and your systems will be fast. While it may be tempting to think that we can all just rewrite our code when something better comes along, we all know the reality that software does not exist in a bubble of infinite resources. Performance improvements and technical debt payments need to be balanced with feature development, user requests, and the million other things that come along with modern software work. While re-implementing functionality in a new language, you also need to ensure that you are providing a consistent and reliable service to your users. How then, can a developer hope to improve their code base while maintaining the rapid pace of development & reliability expected? The answer lies not in big-bang-style rewrites, but in incremental refactoring. Why Refactor to Rust Why you may want to refactor an application Why Rust is a good choice for refactoring When it is and is not appropriate to start a refactoring project High-level overview of methods you can use to refactor your code into Rust ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 1 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 6
Refactoring is the process of restructuring code so that it performs better, is easier to maintain, or meets some other definition of “better.” There is a distinction, however fuzzy, between refactoring and rewriting. The difference between the two comes down to the size of the operation. Rewriting is taking a whole application, or large part of an application and re-implementing it from scratch. This might be to take advantage of a new programming language, a new data storage model, or just because the current system is difficult to maintain, and it seems easier to throw it out and start over than to improve it. Refactoring is really just rewriting on a much smaller scale. Instead of aiming to replace the current system wholesale, we want to find the parts of the system that are in need of the most help and replace the smallest amount of code possible to improve the system. The benefits of refactoring over rewriting are numerous: Because the current system is the “new system,” it can continue to run and serve customers while the refactoring is in progress. We can deploy very small code changes at a time to ensure that we know what change caused an issue. If we were rewriting the whole system and deploying the new system all at once, how would we know what part of the system was causing errors if we saw them? Existing code probably already has years of production experience and monitoring around it. The experience that others have operating and debugging existing code should not be undervalued. If there is a problem with a new system that you have no experience running, how are you going to find it? Ideally, existing code will have automated testing associated with it. These tests can be re-used to verify that our refactored code fulfils the same contract as the existing code. If your existing code does not have automated tests, refactoring is a great impetus to start on writing them! Figure 1.1 displays how deploys over time might be different in a rewrite vs in a refactor. 1.1 What is refactoring? ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 2 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 7
Figure 1.1 How refactoring and rewriting affect the size of deployments When rewriting a system, changes must often be bundled together and deployed at once. This decreases velocity and increases the risk of deployments. The longer that features sit on a branch or in a stale staging environment, the more difficult it will be to debug that code when it is deployed. If all software has some risk of a bug, then increasing the frequency and decreasing the lines of code changed in deployments will help to find and eliminate bugs in the least time. When refactoring, we strive to make small, independent changes that can be deployed as soon as possible. We add metrics and monitoring around our changes to ensure that when they are deployed, results remain consistent. This allows us to quickly and consistently deploy small changes to our system that fix bugs, add features, or improve the performance of our system. All that being said, there are a number of considerations that need to be made when refactoring code that’s already doing its job: ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 3 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 8
Ensuring that behavior is consistent between the old and new code Leveraging existing automated testing and writing new tests that deal with new data structures introduced by the refactoring Deploying the new code Determining the level of separation between the old and new code’s deployment environments How to compare the performance of both systems while they are both running? Controlling the rollout of the new system so that only a small percentage of customers access the new code paths In this book, we will explore techniques and approaches that can be used to refactor code that is slow or difficult to reason about into Rust. We’ll cover how to find the most critical parts of your code in need of refactoring, how to make your existing code talk to Rust, how to test your newly refactored code, and more. Rust is a programming language that emphasizes fast runtime, high reliability, and memory safety. According to rust-lang.org, Rust is “A language empowering everyone to build reliable and efficient software.” What does that mean? Empowering: Rust aims to give developers abilities that they would not have otherwise had. Everyone: The Rust community is extremely welcoming to everyone regardless of background. There are Rust developers from every skill level, some have Rust as their first programming language, and others know many. Some are coming from low-level programming, while others are application developers in languages like Python, Ruby, and Javascript. Reliable: Rust software aims to be fault-tolerant and explicit about how errors are handled so that nothing slips through the cracks. Efficient: Due to being compiled directly to machine code and the lack of a runtime garbage collector, Rust code is much faster than code written in interpreted languages like Python, Ruby, and Javascript right out of the box. On top of this, Rust provides developers with the tools to control lower-level details like memory allocations when required. This can lead to massive speedups while still keeping your application easy to understand. 1.2 What is Rust? ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 4 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 9
Rust combines memory safety, performance, and a fantastic type system - these features act together to keep your applications working correctly. The strong type system will ensure that data exchange follows the correct contract and unexpected data will not cause unexpected results. The lifetime and ownership systems will permit you to directly share memory across FFI boundaries without questions of where the responsibility for freeing resources lies. The strong guarantees around thread safety will allow you to add parallelism that would have previously been impossible or highly risky. When you combine these features, which were initially designed to help developers write better Rust programs, you will see that they are ideal for aiding in incremental refactoring of almost any language into Rust. There are a variety of reasons that you may want to refactor parts of your application into Rust, but the two primary goals that we will discuss in this book are performance and memory safety. Let’s imagine that you’re working on an application written in a language like Python, Node.js, or Ruby. You’ve been adding new features to your application for a while, and you have a large codebase. You have started to notice however, that as your user base is growing, you’re paying a lot for scaling your service with the required compute resources. Your application is being slowed down by some part of the request handling, but you’re not quite sure where yet. This book will guide you through techniques like benchmarking and profiling that will lead you to the places in your code that would benefit the most from a performance-oriented refactoring. Once these are found, we will explore techniques to implement the same functionality in Rust, along with some performance tuning that can make your code as fast as possible. Let’s look at a small example - imagine that the following CSV parsing code is in your web application: Listing 1.1 Python function that returns the sum of all values from a given column in a CSV string This is a fairly trivial Python function that returns the sum of all values from a given column in a 1.3 Why Rust? 1.4 Should I refactor to Rust? 1.4.1 Performance def sum_csv_column(data, column): sum = 0 for line in data.split("\n"): if len(line) == 0: continue value_str = line.split(",")[column] sum += int(value_str) return sum ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 5 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 10
CSV string. Writing the same function in Rust looks very similar: Listing 1.2 The same CSV column summing function written in Rust Functions in Rust always have their parameter and return types explicitly labeled. The keyword indicates that a variable is mutable and that its value can changemut over time. The function at the end of these lines indicates that the functions usedunwrap could possibly fail, and we’re just going to panic if they do. This syntax ( ) is called the “turbofish” operator in Rust, and it is used::<i64> when the compiler needs a hint about what type a function should return. Since the function can return different types depending on context, this is required forparse disambiguation. This will be covered in more detail in Chapter 2. The Rust version of the function may look slightly more intimidating at first, but it is quite similar to the Python version: Both are functions that take two variables - a string of CSV and a column number to sum. The Rust version has explicitly labeled types, but the Python version still expects variables to have those types too, even if they’re not labeled. Both functions return numbers, once again Rust explicitly labels this at the top of the function declaration, while Python does not. Both functions raise errors if the data they are given does not match expectations. The Python version raises Exceptions, and the Rust version will panic. We will cover error handling in Chapter 2. Both functions use the same naive CSV parsing algorithm to accomplish their goals. Despite their similar appearance, these two functions have quite different performance characteristics. The Python version will allocate a list of strings containing each line in the CSV input string, put those strings in a list, and allocate a new list of strings for each row of comma-separated values in the data. Because of the strong guarantees that the Rust compiler can make about when memory is allocated and de-allocated, the Rust version will safely use the same underlying string memory for the whole function, never allocating. Additionally, Rust’s fn sum_csv_column(data: &str, column: usize) -> i64 { let mut sum = 0; for line in data.lines() { if line.len() == 0 { continue; } let value_str = line .split(",") .nth(column) .unwrap(); sum += value_str.parse::<i64>().unwrap(); } sum } ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 6 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 11
function on strings creates an , not a list. This means that the whole sequence.split Iterator of substrings is moved over one at a time, instead of allocating the whole thing up front as the Python version does. This distinction will be discussed in more detail in chapter 2. If the input data is many millions of lines long, or has many fields, this will have a huge impact on performance. I ran both of these examples with the same input file of 1,000,000 rows and 100 columns. highlights their respective time and maximum memory usage:Table1.1 This represents a speedup of approximately 20 times, as well as using less than half the memory. These are significant performance gains without a significant increase in the complexity of the code. This is just a cherry-picked example, and Rust may perform better or worse in your use case. Alternatively, you may be working on a C or C++ project, and want to utilize Rust for the benefits in safety that it provides over those languages. At compile time, Rust can verify that your application is safe from memory bugs like data races, dangling pointers, and more. By incrementally refactoring the critical parts of your codebase into Rust, you can ship software more quickly with less time spent worrying about the memory invariants of your code. Let the compiler do the worrying for you! Many common bugs in C and C++ code are simply impossible to express in normal Rust code. If we try to write code that exhibits these bugs, the compiler will not accept the program. This is because the Rust compiler manages one of the most difficult parts of programming in C and C++ - memory ownership. Experienced C and C++ programmers will probably be familiar with the concept of memory ownership, but all C and C++ developers will have to deal with it eventually. It will be discussed in more detail in later chapters, but the bottom line is that there is always one handle that controls when a piece of memory is allocated and de-allocated, and this handle is said to "own" that memory. In a typical C or C++ program, the programmer is totally responsible for maintaining the state of memory ownership in their heads. The languages provide very few tools to strictly annotate what values are owned by what handles. The Rust compiler on the other hand, requires that programs strictly adhere to its memory ownership model. Table 1.1 Performance differences between Python and Rust CSV aggregation functionsm Version Runtime Max memory used Python 2.9 s 800 MiB Rust 146 ms 350 MiB 1.4.2 Memory Safety ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 7 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 12
This is one of the largest benefits of Rust development: taking errors that were traditionally runtime errors with unpredictable or dangerous consequences and turning them into compile-time errors that can be resolved before the code is ever executed. When projects written in dynamically typed programming languages start to reach into the tens of thousands of lines, you may find yourself asking questions like “what is this object?” and “what properties are available?” These are questions that the strong, static type system in Rust aims to solve. Static typing means that the type of every single value in your Rust program will be known at compile time. Static typing is coming back in a big way these days. Projects like Typescript, Mypy and sorbet aim to add type checking to Javascript, Python, and Ruby, respectively. These are programming languages that never had support for type checking, and the amount of effort that has gone into developing these systems highlights how helpful it is to know what type a value is ahead of time. The type system in Rust is very powerful, but in most cases it stays out of your way. Functions must have their input and output types annotated explicitly, but the types of variables inside of functions can usually be determined statically by the compiler without any extra annotations. Just because the types are not labeled explicitly, does not mean that they are not known. If a function is declared to only accept a boolean as its input, you cannot give it a string. Many IDEs and editor plugins exist that can show you these implicitly defined types to aid in development, but you as a developer don’t need to write them yourself. Some developers may be nervous about static typing, having last seen it when Java required you to use the following kafkaesque syntax: Listing 1.3 Initializing a map of numbers to lists of numbers in Java 1.6 Specifying the type of every single local variable in each function is exhausting, especially when the language requires you to do it more than once. The same operation in Rust takes only two lines, with no explicit types required: Listing 1.4 Initializing a map of numbers to lists of numbers in Rust How does the compiler know what type of values go into ? It looks at the call to andmap insert sees that it is passed an integer as the key and a list of integers as the value. The same code can 1.4.3 Maintainability HashMap<Integer, ArrayList<Integer>> map = new HashMap<Integer, ArrayList<Integer>>(); ArrayList<Integer> list = new ArrayList<Integer>(); list.add(4); list.add(10); map.put(1, list); let mut map = HashMap::new(); map.insert(1, vec![4, 10]); ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 8 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 13
1. be written with explicit type annotations in Rust, but it is completely optional in most cases. We will cover some of these cases in Chapter 2. Listing 1.5 Initializing a map of numbers to lists of numbers in Rust with explicit types This strong type system ensures that when you revisit code later, you can spend more time adding new features or improving performance, and less time worrying about what the 5th untyped parameter to the function means.perform_action If you are looking at a greenfield project, then you don’t need to refactor to Rust, you can just write your initial solution in Rust! This book primarily assumes that you have an existing software project that you want to improve. If you’re just starting out, then you may benefit more from a general-purpose Rust programming book. If your project is running in an environment that you don’t have very strong control over, such as a PHP shared hosting service, or tightly-controlled enterprise servers where you don’t have the ability to install new software, you may run into issues with some of the techniques outlined in this book. There must always be a plan for deploying any software project. How are you going to get it in front of the users? The type of refactoring discussed in this book assumes that deploying new code is fairly low cost and can be done frequently. If you need to ship physical media to customers for new versions, or your organization has a very rigid release structure, this may not be the right book for your needs. When writing new software, you should always plan for how it will be maintained for years to come. If you are the only one excited about Rust development in your large company, you may be setting yourself up to be “the Rust person” for when this system inevitably has issues down the line. Do you want to be the only one responsible for maintaining this system? Incremental refactoring of a mature production system is no simple task, but it can be broken down into a series of a few key steps: Planning What do I hope to improve by refactoring to Rust? If existing code is written in C or C++, you should be thinking of how Rust can improve the memory safety of your application. 1.5 When should I not refactor to Rust? 1.6 How does it work? let mut map: HashMap<i32, Vec<i32>> = HashMap::new(); map.insert(1, vec![4, 10]); ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 9 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 14
1. 2. 3. 4. If existing code is written in an interpreted, garbage-collected language like Python, you will be mostly concerned with improving the performance of your application. What parts of my code should be refactored? How should my existing code talk to the new code? Implementation Mirroring the functionality of existing code in new Rust code Integrating Rust code into the existing codebase Verification Using testing facilities of the Rust language to test new functionality Using your existing tests to compare results between the two code paths Deployment Depending on decisions you made earlier, there are different ways that your Rust code will need to be run when it is serving your customers How can you effectively roll out your refactored code without affecting your end-users? Figure 1.2 lists these steps and some of their finer parts in more detail. ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 10 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 15
Figure 1.2 Overview of the refactoring process that we will discuss in this book As you can see from the largest part of this process is planning. Performing this typeFigure 1.2 ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 11 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 16
of refactoring work is complex, and it requires you to know the effects of replacing code before that code is replaced. Along with this is the careful consideration for performance and maintainability that come along with introducing new code patterns. After planning, the largest section is deployment; controlling which users access the new functionality instead of the old. This book covers incremental refactoring in an abstract sense, then moves into how Rust can specifically benefit an incremental refactoring approach, and how it can be incorporated into your applications. There are two main techniques for integrating Rust code into existing applications, and they each have a few variations: In this model, you write a Rust library that acts like a library written in your existing programming language. The various techniques are discussed at a high level in this section, and will be discussed at length in later chapters. This model is illustrated by .Figure 1.3 Figure 1.3 When calling Rust directly from your existing application, your Rust code looks just like a normal module If you’re refactoring a Python project for instance, your Rust library will expose functions and classes that act just like Python functions and classes. This method will have the lowest possible overhead for communication between your existing code and the new Rust code, since they are both running as a part of the same OS process, and can directly share memory with each other. There are a few branches of this approach: Using the C Foreign Function Interface (FFI) This will be discussed at great length in Chapter 3, but the bottom line is that Rust will let you write a function that looks like a C function, and many other languages know how to call C functions. This will be the most universal approach since most commonly used programming languages understand C FFI. 1.7 What will I learn in this book? 1.7.1 Calling Rust functions directly from your program ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 12 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 17
This approach has the most potential for memory bugs, as the programmer will be directly responsible for ensuring that memory is allocated, de-allocated, passed back and forth correctly, and ownership is always clear. If your projects are in C or C++ this is the integration technique you will use. Using Rust libraries to bind directly to the other language’s interpreter Using this technique, you can write a Rust library that looks just like a Python, Ruby, or Node.js library for instance. Often easier to implement than the C FFI approach, this technique breaks down if there are not Rust bindings available for the language that you want to use. Compiling Rust to WebAssembly (WASM) and using WASM FFI WASM is a bytecode format for JavaScript engines, similar to Java bytecode. Many languages (Rust included) can compile to WASM instead of native machine code. This is useful for using Rust with in-browser JavaScript engines, or Node.js This technique relies on using a network protocol to communicate with a newly created Rust service. illustrates this concept.Figure 1.4 Figure 1.4 When Rust code is in an external service, there is additional overhead due to the network hop This has several advantages and disadvantages compared with the previously discussed model: Advantages Because there is no direct memory access with this technique, you don’t run the risk of memory corruption in the interop between the two languages. This approach allows for your Rust system to be scaled independently of your existing application. More developers have experience with networked communication between applications, so it is less of a conceptual jump than the idea of multiple programming languages coexisting in one application Disadvantages As alluded to in the last section, you will lose out on some performance due to the extra time it takes for data to be sent across the network. 1.7.2 Communicating with a Rust service over the network ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 13 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 18
There is additional operational overhead for adding an extra service with its own independent logging, monitoring, and deployment logic This book is written for programmers who already have several years of experience working with applications in a language other than Rust, and are looking for ways to improve their applications’ performance, safety, or maintainability. This book will also benefit Rust programmers that want to apply their knowledge to helping improve the performance or memory safety of existing applications written in other languages. There’s a lot more code out there that isn’t written in Rust than there is code written in Rust. The code examples in this book will of course mainly be Rust, but since this book covers moving from other languages Rust, we need something to compare to. In the chapter on C FFI, thereto will be many C and C++ code examples, and many of the remaining chapters will have code examples in Python that are used to highlight the differences between it and Rust, as well as to show how the integration methods work. You do not need to be an expert in these languages, experience with other procedural languages in the C family should suffice. The Unsafe Rust and C FFI chapter discusses many topics around memory safety that may be foreign to developers that primarily work in languages that have runtime garbage collection. These topics are not required for refactoring from these garbage collected languages, they are mainly for the benefit of the readers coming from a C and C++ background. All of the software tools that you need to get started are readily and freely available. You will need A recent Rust compiler Instructions for installing Rust can be found in the appendix A text editor suitable for programming A computer or virtual machine running a GNU/Linux operating system Most strictly-Rust programming examples in this book will work on any operating system, but some of the examples will be written assuming a GNU/Linux operating system. If you are using Microsoft Windows, the Windows Subsystem for Linux (WSL) provides a convenient way to run Linux programs that integrate with your normal Windows environment. All examples in the book will be tested on Ubuntu 20.04 running under WSL. Libclang development packages Again, this is not strictly required for the Rust-only coding exercises, but many of the chapters use libclang (indirectly) to generate code to talk between Rust and C/C++ code. Python 3, , and virtualenv pip 1.8 Who is this book for? 1.9 What tools do I need to get started? ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 14 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 19
This is required for running the Rust-based Python extension modules in later chapters. Refactoring can be used to replace small parts of your code at a time. This will help you to improve performance without the pain and time investment of a large rewrite. Rust has a Strong static type system which ensures that inputs and outputs are clearly defined and edge-cases are handled. Rust provides easy parallelism meaning that you can take already fast Rust code and use every bit of available CPU power to maximize performance. Rust can easily integrate with other languages, and lets you focus on delivering value, while not worrying about re-inventing the wheel. Refactoring to Rust can improve performance, memory safety, and maintainability. This will help your software systems scale faster and with less expense in the long term. 1.10 Summary ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 15 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
📄 Page 20
2 This chapter covers: Before we can integrate a Rust library into an existing application written in another language, we first need to understand the basics of Rust programming. This chapter will guide us through a simple application to manage digital artworks for an art museum, to learn about how the Ownership system works. Ownership & Borrowing are considered by many to be some of the most challenging things for new Rust developers to learn. We’re starting with it here instead of something simpler because these are the areas where Rust differs most from other programming languages, and they’re at the core of all Rust programs. If we don’t take the time to cover these important ideas now, it will make the rest of the book far more difficult. We’re going to use an example that ties the ownership & borrowing components of Rust programs to ownership and use of digital artwork. This should make reasoning about ownership easier, and we’ll introduce tools for visualizing changes to ownership over time. One of the biggest differences between Rust and other programming languages is the enforcement of a few very important rules about how data can be accessed and dependencies between different forms of data access. These rules are not overly complicated, but they are different from many other languages, which have no enforcement of such rules. Here are the rules for ownership: An overview of Rust Designing systems that properly utilize Rust’s ownership system Visualizing Rust’s lifetime system to aid in debugging Controlling allocations of strings for fast performance Enums and basic error handling 2.1 Ownership & Borrowing ©Manning Publications Co. To comment go to liveBook https://livebook.manning.com/#!/book/refactoring-to-rust/discussion 16 Licensed to Yuriy Larin <yuriy.larin@gmail.com>
The above is a preview of the first 20 pages. Register to read the complete e-book.

💝 Support Author

0.00
Total Amount (¥)
0
Donation Count

Login to support the author

Login Now
Back to List