Lightweight Thread Model

The Cangjie language uses the user-level thread model. Each Cangjie thread is an extremely lightweight execution entity with an independent execution context, and all the threads share the same memory. This model not only simplifies concurrent programming, but also brings significant performance advantages.

  • Development state: The user-level thread model makes concurrent programming as easy as common programming. Generally, this model may be implemented in two solutions: stackless and stackful. Although the stackless coroutine can reduce the memory usage to a very low level, a new syntax, such as the async or await keyword, is usually required to be used in the Cangjie language. However, the use of a new syntax significantly increases the concurrent programming complexity. Developers need to manually mark functions during programming (for example, mark an asynchronous function as async and its call site as await). Such operation is contagious (that is, all functions containing await must be marked as async) and results in colored functions. Each Cangjie thread has an independent execution context and can be freely switched. Therefore, developers do not need to mark functions during programming.
  • Runtime state: Compared with traditional operating system threads, the lightweight thread model has obvious advantages in performance. The lightweight thread model is entirely implemented and managed in user space, fundamentally reducing the overheads of thread creation and destruction and simplifying the thread scheduling process. This design achieves more efficient resource utilization and faster program execution in the Cangjie language, especially in high-concurrency scenarios. On one x86 server, the average time required for creating a Cangjie thread is 700 ns, which is far less than the overhead of creating an operating system thread (generally hundreds of microseconds). Because one Cangjie thread occupies only 8 KB memory, developers can create hundreds of thousands of Cangjie threads in one program at the same time, which is much more than the number of threads that can be created in an operating system.

In general, the lightweight thread model not only reduces the system load, but also enables developers to easily implement thousands or even tens of thousands of concurrent tasks without increasing programming complexity. This model has the following key advantages:

  • Simple concurrent programming. The model does not impose too many syntax restrictions on concurrent programming, so that developers can easily use Cangjie threads for service processing.
  • Lightweight overhead. Compared with traditional kernel threads, the user-level thread model has much lower thread creation and switching overheads. Therefore, developers can quickly create and destroy a large number of user-level threads in the Cangjie language and easily develop high-concurrency applications.
  • Higher concurrency. A large number of concurrent tasks can be executed at the same time, making this model especially suitable for I/O-intensive and high-concurrency network service scenarios.
  • Lower context switching costs. Context is switched in the user space, avoiding high costs of frequent switching between the kernel mode and user mode during thread switching.

This design enables developers to easily and quickly execute high-concurrency tasks in the Cangjie language. They can use simple syntax to construct a large number of user-level threads without worrying about common performance bottlenecks in traditional concurrency models. For example, a developer can easily handle multiple network requests by executing the following code:

func fetch_data(url: String) {
    let response = http_get(url)
    process(response)
}

main() {
    let urls = ["https://example.com/data1", "https://example.com/data2", ...]
    let futures = ArrayList<Future<Unit>>()
    for (url in urls) {
        let fut = spawn {fetch_data(url)} // Creates Cangjie threads to send network requests.
        futures.append(fut)
    }
    for (fut in futures) { // Waits for all Cangjie threads to complete.
        fut.get()
    }
}

In the preceding example, the spawn keyword is used to create a new Cangjie thread. Each thread independently executes the fetch_data function. The runtime environment of the Cangjie language automatically schedules these threads. Therefore, developers can focus on the implementation of service logic. Finally, the developer calls the fut.get() function to wait for and obtain the execution result of the child threads, ensuring that the main thread can obtain the execution result of the child threads synchronously.

With its obvious performance advantages and lightweight design concept, the user-level thread model used by the Cangjie language provides developers with a new and attractive solution for concurrent programming. It makes high-concurrency application coding more direct and efficient. It is not only applicable to high-load network services, but also meets the requirements of various computing-intensive tasks. By using this new concurrency model, the Cangjie language achieves simple concurrent programming and makes full use of the powerful processing capabilities of modern multi-core processors.