Skip to content

Commit

Permalink
fix(latex): use \emph instead of \em for compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
Roman Kashitsyn authored and Roman Kashitsyn committed Jun 1, 2024
1 parent fdca047 commit 7c4884c
Show file tree
Hide file tree
Showing 29 changed files with 481 additions and 481 deletions.
2 changes: 1 addition & 1 deletion blogware/symtab.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var (
SymBold = BuiltinCmd("b", ArgTypeSeq)
SymUnderline = BuiltinCmd("u", ArgTypeSeq)
SymNormal = BuiltinCmd("normal", ArgTypeSeq)
SymEmphasis = BuiltinCmd("em", ArgTypeSeq)
SymEmphasis = BuiltinCmd("emph", ArgTypeSeq)
SymSmallCaps = BuiltinCmd("sc", ArgTypeSeq)
SymCircled = BuiltinCmd("circled", ArgTypeNum)
SymCode = BuiltinCmd("code", ArgTypeSeq)
Expand Down
26 changes: 13 additions & 13 deletions posts/01-effective-rust-canisters.tex
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ \subsection{canister-state}{Canister state}
The issue can stay undetected until your canister is in active use, storing (and corrupting) user data.
If we used a \code{RefCell}, the code would panic before we shipped it.

It should now be clear \em{how} to declare global variables.
Let us discuss \em{where} to put them.
It should now be clear \emph{how} to declare global variables.
Let us discuss \emph{where} to put them.

\advice{clear-state}{Put all your globals in one basket.}

Expand All @@ -132,10 +132,10 @@ \subsection{canister-state}{Canister state}
I borrowed \href{https://sdk.dfinity.org/docs/language-guide/upgrades.html#_declaring_stable_variables}{Motoko terminology} here:
\begin{enumerate}
\item
The system preserves \em{stable} variables across upgrades.
The system preserves \emph{stable} variables across upgrades.
For example, a user database should probably be stable.
\item
The system discards \em{flexible} variables on code upgrades.
The system discards \emph{flexible} variables on code upgrades.
For example, you can make a cache flexible if it is not crucial for your canister.
\end{enumerate}

Expand Down Expand Up @@ -405,7 +405,7 @@ \subsection{cycle-consumption}{Reducing cycle consumption}

\advice{instruction-counter}{Measure the number of instructions your endpoints consume.}

The \href{https://docs.rs/ic-cdk/0.5.3/ic_cdk/api/fn.instruction_counter.html}{\code{instruction_counter}} API will tell you the number of \em{instructions} your code consumed since the last \href{https://internetcomputer.org/docs/current/references/ic-interface-spec/#entry-points}{entry point}.
The \href{https://docs.rs/ic-cdk/0.5.3/ic_cdk/api/fn.instruction_counter.html}{\code{instruction_counter}} API will tell you the number of \emph{instructions} your code consumed since the last \href{https://internetcomputer.org/docs/current/references/ic-interface-spec/#entry-points}{entry point}.
Instructions are the internal currency of the IC runtime.
One IC instruction is the \href{https://en.wikipedia.org/wiki/Quantum}{quantum} of work that the system can do, such as loading a 32-bit integer from a memory address.
The system assigns an instruction cost equivalent to each \href{https://sourcegraph.com/github.com/dfinity/ic@cfdbbf5fb5fdbc8f483dfd3a5f7f627b752d3156/-/blob/rs/embedders/src/wasm_utils/instrumentation.rs?L155-177}{WebAssembly instruction} and \href{https://sourcegraph.com/github.com/dfinity/ic@cfdbbf5/-/blob/rs/embedders/src/wasmtime_embedder/system_api_complexity.rs?L40-107}{system call}.
Expand All @@ -432,7 +432,7 @@ \subsection{cycle-consumption}{Reducing cycle consumption}
let tx = apply_transfer(from, to, amount)?;
let tx_id = archive_transaction(tx).\b{await}?;

\em{// \b{BAD}: the await point above resets the instruction counter.}
\emph{// \b{BAD}: the await point above resets the instruction counter.}
let end = ic_cdk::api::instruction_counter();
record_measurement(end - start);

Expand All @@ -454,7 +454,7 @@ \subsection{cycle-consumption}{Reducing cycle consumption}
struct HttpResponse {
status_code: u16,
headers: Vec<(String, String)>,
\em{// \b{BAD}: inefficient}
\emph{// \b{BAD}: inefficient}
body: Vec<u8>,
}
\end{code}
Expand All @@ -466,7 +466,7 @@ \subsection{cycle-consumption}{Reducing cycle consumption}
struct HttpResponse {
status_code: u16,
headers: Vec<(String, String)>,
\em{// \b{OK}: encoded efficiently}
\emph{// \b{OK}: encoded efficiently}
#[serde(with = "serde_bytes")]
body: Vec<u8>,
}
Expand All @@ -479,7 +479,7 @@ \subsection{cycle-consumption}{Reducing cycle consumption}
struct HttpResponse {
status_code: u16,
headers: Vec<(String, String)>,
\em{// \b{OK}: also efficient}
\emph{// \b{OK}: also efficient}
body: serde_bytes::ByteBuf,
}
\end{code}
Expand Down Expand Up @@ -537,7 +537,7 @@ \subsection{cycle-consumption}{Reducing cycle consumption}

#[query]
fn http_request(_request: HttpRequest) -> HttpResponse {
\em{// \b{NOTE}: we are making a full copy of the asset.}
\emph{// \b{NOTE}: we are making a full copy of the asset.}
let body = ASSET.with(|cell| cell.borrow().clone());

HttpResponse {
Expand Down Expand Up @@ -619,7 +619,7 @@ \subsection{cycle-consumption}{Reducing cycle consumption}
I experimented with a one-megabyte asset and measured that the original code relying on a deep copy consumed 16 million instructions.
At the same time, versions with reference counting and explicit lifetimes needed only 12 million instructions\sidenote{sn-candid-copy}{
The 25\% improvement shows that our code does little but copy bytes.
The code did at least \em{three} copies: \circled{1} from a \code{thread_local} to an \code{HttpResponse}, \circled{2} from the \code{HttpResponse} to candid's \href{https://sourcegraph.com/github.com/dfinity/candid@8b742c9701640ca220c356c23c5f834d13150cc4/-/blob/rust/candid/src/ser.rs?L28}{value buffer}, and \circled{3} from candid's \href{https://sourcegraph.com/github.com/dfinity/candid@8b742c9701640ca220c356c23c5f834d13150cc4/-/blob/rust/candid/src/ser.rs?L61}{value buffer} to the call's \href{https://sourcegraph.com/github.com/dfinity/cdk-rs@39cd49a3b2ca6736d7c3d3bf3605e567302825b7/-/blob/src/ic-cdk/src/api/call.rs?L481-500}{argument buffer}.
The code did at least \emph{three} copies: \circled{1} from a \code{thread_local} to an \code{HttpResponse}, \circled{2} from the \code{HttpResponse} to candid's \href{https://sourcegraph.com/github.com/dfinity/candid@8b742c9701640ca220c356c23c5f834d13150cc4/-/blob/rust/candid/src/ser.rs?L28}{value buffer}, and \circled{3} from candid's \href{https://sourcegraph.com/github.com/dfinity/candid@8b742c9701640ca220c356c23c5f834d13150cc4/-/blob/rust/candid/src/ser.rs?L61}{value buffer} to the call's \href{https://sourcegraph.com/github.com/dfinity/cdk-rs@39cd49a3b2ca6736d7c3d3bf3605e567302825b7/-/blob/src/ic-cdk/src/api/call.rs?L481-500}{argument buffer}.
We removed ⅓ of copies and got ¼ improvement in instruction consumption.
So only ¼ of our instructions contributed to work unrelated to copying the asset's byte array.
}.
Expand Down Expand Up @@ -673,7 +673,7 @@ \subsection{module-size}{Reducing module size}
As with any optimization process, you need a profiler to guide your experiments.
The \href{https://rustwasm.github.io/twiggy/}{\code{twiggy}}\sidenote{sn-twiggy-order}{
\code{twiggy} needs debug info to display function names.
Run it \em{before} you shrink your module with \code{ic-wasm}.
Run it \emph{before} you shrink your module with \code{ic-wasm}.
} tool is excellent for finding the largest functions in your WebAssembly modules.

\begin{figure}
Expand Down Expand Up @@ -764,7 +764,7 @@ \subsection{upgrades}{Upgrades}
You can view stable memory as a communication channel between your canister's old and new versions.
All proper communication protocols have a version.
One day, you might want to change the stable data layout or serialization format radically.
The code becomes messy and brittle if the stable memory decoding procedure needs to \em{guess} the data format.
The code becomes messy and brittle if the stable memory decoding procedure needs to \emph{guess} the data format.

Save your nerve cells and think about versioning in advance.
It is as easy as declaring, ``the first byte of my stable memory is the version number.''
Expand Down
18 changes: 9 additions & 9 deletions posts/02-ic-state-machine-replication.tex
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
\section{state-machine}{The state machine}

Before we dive into the internals of the protocol, let's first define the \href{https://en.wikipedia.org/wiki/Finite-state_machine}{state machine} that we'll be dealing with.
Nodes participating in the Internet Computer are grouped into units called \em{subnet blockchains}, or simply \em{subnets}.
Nodes participating in the Internet Computer are grouped into units called \emph{subnet blockchains}, or simply \emph{subnets}.
Nodes in the same subnet run their own instance of the core Internet Computer Protocol (i.e., they form an independent peer-to-peer network and reach consensus independently from other subnets).
We'll model as a state machine the computation that nodes in the same subnet perform.

Expand All @@ -28,7 +28,7 @@ \section{state-machine}{The state machine}
These blocks are the inputs of our state machine.
}
\term{Outputs}{
In our model, the main artifact of the execution is a data structure called \em{state tree}.
In our model, the main artifact of the execution is a data structure called \emph{state tree}.
We'll learn more about state trees in a moment.}
\term{States}{
The single most important thing that the Internet Computer does is hosting canisters.
Expand All @@ -48,7 +48,7 @@ \section{state-machine}{The state machine}
\item Executes the messages on the selected canisters and records the execution results.
\end{itemize}
All of the above modifies the data structure that we call ``state'' and acts as a transition function.
Note that we can call this procedure a \em{function} only if it's deterministic: given the same block and the same original state, the replica will modify the state in exactly the same way.
Note that we can call this procedure a \emph{function} only if it's deterministic: given the same block and the same original state, the replica will modify the state in exactly the same way.
Thanks to the careful design of execution algorithms and guarantees that WebAssembly provides, the procedure is indeed deterministic.
}
\term{Output function}{
Expand All @@ -62,22 +62,22 @@ \section{state-machine}{The state machine}
}
\end{description}

I call these state machines (one for each subnet) \em{replicated} because each honest node on a subnet has an exact copy of the machine.
I call these state machines (one for each subnet) \emph{replicated} because each honest node on a subnet has an exact copy of the machine.

\subsection{checkpoints}{Checkpoints}

Let's say we want to add a new node to an existing subnet because a flood destroyed one of the data centers hosting the subnet.
This new node cannot start processing and proposing new blocks until it has the right state, the state that results from execution of all the blocks produced by this subnet so far.

One way to bring the node up to date is to download all those blocks and ``replay'' them.
This sounds simple, but if the rate of change is high and message execution is costly, the new node might need a \em{lot} of time to catch up.
This sounds simple, but if the rate of change is high and message execution is costly, the new node might need a \emph{lot} of time to catch up.
As the Red Queen put it: ``My dear, here we must run as fast as we can, just to stay in place.
And if you wish to go anywhere you must run twice as fast as that.''

Another solution is to create persistent snapshots of the state from time to time.
The peers can fetch and load those snapshots when they need help.
This method works really well for our state machine: it reduces the catch up time from days to minutes.
Let's call those persistent snapshots \em{checkpoints}.
Let's call those persistent snapshots \emph{checkpoints}.

\begin{figure}[grayscale-diagram]
\marginnote{sm-components}{Components of the state machine: blocks as inputs, states, state trees as outputs, and checkpoints.}
Expand Down Expand Up @@ -149,13 +149,13 @@ \subsection{state-artifact}{State as an artifact}
Load the checkpoint, replay a few blocks, and you're ready to rock.
There is a more interesting case, however: a healthy replica can help other replicas catch up by sending them a recent checkpoint.

Replicas in a subnet communicate by exchanging \em{artifacts} using a peer-to-peer protocol.
Replicas in a subnet communicate by exchanging \emph{artifacts} using a peer-to-peer protocol.
Most of these artifacts (e.g., user ingress messages, random beacons, state certifications) are relatively small, up to a few megabytes in size.
But the machinery for artifact transfer is quite general: the protocol supports fetching arbitrary large artifacts by slicing them into chunks, provided that there is a way to authenticate each chunk independently.
Furthermore, multiple chunks can be fetched in parallel from multiple peers.
Sounds a lot like \href{https://en.wikipedia.org/wiki/BitTorrent}{BitTorrent}, isn't it?

Before advertising a checkpoint, replica computes a \em{manifest} for that checkpoint.
Before advertising a checkpoint, replica computes a \emph{manifest} for that checkpoint.
Manifest is an inventory of files constituting a checkpoint.
Files are sliced into chunks, and the manifest enumerates paths, sizes and cryptographic hashes of every file and every chunk of each file.
In our BitTorrent analogy, manifest plays a role of a \href{https://en.wikipedia.org/wiki/Torrent_file}{.torrent file}.
Expand All @@ -177,7 +177,7 @@ \subsection{trigger-transfer}{Triggering state transfer}
As you might have guessed, the consensus subsystem armed with \href{https://en.wikipedia.org/wiki/Threshold_cryptosystem}{threshold signatures} comes to the rescue again.
Replicas gather a threshold signature on a full state hash and use that signature as a proof of checkpoint authenticity.
The result is an artifact containing a state height, a full state hash, and a threshold signature.
We'll call this artifact a \em{catch-up package}.
We'll call this artifact a \emph{catch-up package}.

The interaction between the replica consensus module and the state machine is something like the following
\begin{enumerate}
Expand Down
Loading

0 comments on commit 7c4884c

Please sign in to comment.