西维蜀黍

【Golang】源码 - strings.Builder

Definition

type Builder struct {
	// contains filtered or unexported fields
}

A Builder is used to efficiently build a string using Write methods. It minimizes memory copying. The zero value is ready to use. Do not copy a non-zero Builder.

  ...


【Golang】使用 - Concatenate String

Clean and simple string building

For simple cases where performance is a non-issue, fmt.Sprintf is your friend. It’s clean, simple and fairly efficient.

s := fmt.Sprintf("Size: %d MB.", 85) // s == "Size: 85 MB."
  ...


【Golang】使用 - Unsafe Pointers

Background

Although the restrictions on type-safe pointers really make us be able to write safe Go code with ease, they also make some obstacles to write efficient code for some scenarios.

In fact, Go also supports type-unsafe pointers, which are pointers without the restrictions made for safe pointers. Type-unsafe pointers are also called unsafe pointers in Go. Go unsafe pointers are much like C pointers, they are powerful, and also dangerous. For some cases, we can write more efficient code with the help of unsafe pointers. On the other hand, by using unsafe pointers, it is easy to write bad code which is too subtle to detect in time.

  ...


【NFC】macOS 连接 ACR122U

安装 libnfc

ACR122U 是一款 NFC (Near Field Communication) 读卡器。要在 macOS 上使用 ACR122U,通常需要安装相应的驱动程序和库。

via brew

运行以下命令安装 libnfc:

brew install libnfc

via 手工编译

$ brew install libtool automake autoconf libusb pkg-config
$ git clone https://github.com/nfc-tools/libnfc
$ autoreconf -vis
$ ./configure --with-drivers=acr122_pcsc
$ sudo make clean all && sudo make && sudo make install
  ...


【Operating System】进程 - 进程间通讯 - Memory Barrier/Fence

Memory Barrier/Fence

A memory barrier, also known as a membar, memory fence or fence instruction, is a type of barrier instruction that causes a central processing unit (CPU) or compiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction. This typically means that operations issued prior to the barrier are guaranteed to be performed before operations issued after the barrier.

Memory barriers are necessary because most modern CPUs employ performance optimizations that can result in out-of-order execution. This reordering of memory operations (loads and stores) normally goes unnoticed within a single thread of execution, but can cause unpredictable behaviour in concurrent programs and device drivers unless carefully controlled. The exact nature of an ordering constraint is hardware dependent and defined by the architecture’s memory ordering model. Some architectures provide multiple barriers for enforcing different ordering constraints.

  ...


【Operating System】进程 - 上下文切换

Switching cases

There are three potential triggers for a context switch:

Multitasking

Most commonly, within some scheduling scheme, one process must be switched out of the CPU so another process can run. This context switch can be triggered by the process making itself unrunnable, such as by waiting for an I/O or synchronization operation to complete.

On a pre-emptive multitasking system, the scheduler may also switch out processes that are still runnable. To prevent other processes from being starved of CPU time, pre-emptive schedulers often configure a timer interrupt to fire when a process exceeds its time slice. This interrupt ensures that the scheduler will gain control to perform a context switch.

  ...


【Golang】源码 - Atomic 包

Definition

// A Value provides an atomic load and store of a consistently typed value.
// The zero value for a Value returns nil from Load.
// Once Store has been called, a Value must not be copied.
//
// A Value must not be copied after first use.
type Value struct {
	v interface{}
}

// ifaceWords is interface{} internal representation.
type ifaceWords struct {
	typ  unsafe.Pointer
	data unsafe.Pointer
}
  ...


【Golang】使用 - Atomic Counters

  ...


【Lock】活锁(Livelock)

活锁(Livelock)

Analygy

考虑一个场景:进程P1占有A资源并请求占用资源B,进程P2占有B资源并请求占用资源A。

如果是等待式的请求,两者都会陷入无尽的等待中。这是死锁(deadlock)

如果请求不是等待式的,而是一旦发现资源已经被占有了,就释放所有等待占用和已经占用的资源,并重新开始。此时P1放弃占有资源A重新开始,P2放弃占有资源B重新开始。则P1、P2可能会出现重复不断的开始-回滚循环。这种情况我们称之为活锁(livelock)

相比死锁,活锁更难检测,也更浪费资源(重复不断的开始-回滚循环)。

  ...


【Lock】自旋锁(Spinlock)

背景

在介绍自旋锁前,我们需要介绍一些前提知识来帮助大家明白自旋锁的概念。

阻塞或唤醒一个Java线程需要操作系统进行 context swtich(e.g., kernel space <-> user space, interrupt handling due to I/O or waiting for synchrnization operation to complete)来完成,

Refer to https://swsmile.info/post/os-context-swtich/ in details.

这种 context 转换需要耗费处理器时间。如果同步代码块中的内容过于简单,context 转换消耗的时间有可能比用户代码执行的时间还要长。

在许多场景中,同步资源的锁定时间很短,为了这一小段时间去切换线程,线程挂起和恢复现场的花费可能会让系统得不偿失。如果物理机器有多个处理器,能够让两个或以上的线程同时并行执行,我们就可以让后面那个请求锁的线程不放弃CPU的执行时间,看看持有锁的线程是否很快就会释放锁。

而为了让当前线程“稍等一下”,我们需让当前线程进行自旋,如果在自旋完成后前面锁定同步资源的线程已经释放了锁,那么当前线程就可以不必阻塞而是直接获取同步资源,从而避免切换线程的开销。这就是自旋锁。

  ...