惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
V
Vulnerabilities – Threatpost
博客园_首页
GbyAI
GbyAI
Martin Fowler
Martin Fowler
S
Secure Thoughts
Help Net Security
Help Net Security
Attack and Defense Labs
Attack and Defense Labs
大猫的无限游戏
大猫的无限游戏
量子位
腾讯CDC
博客园 - 叶小钗
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Security Blog
Microsoft Security Blog
Cisco Talos Blog
Cisco Talos Blog
V
V2EX
P
Proofpoint News Feed
T
Tailwind CSS Blog
U
Unit 42
A
Arctic Wolf
PCI Perspectives
PCI Perspectives
B
Blog
F
Fortinet All Blogs
B
Blog RSS Feed
H
Hacker News: Front Page
P
Privacy & Cybersecurity Law Blog
Scott Helme
Scott Helme
G
GRAHAM CLULEY
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
H
Heimdal Security Blog
人人都是产品经理
人人都是产品经理
Forbes - Security
Forbes - Security
TaoSecurity Blog
TaoSecurity Blog
N
Netflix TechBlog - Medium
aimingoo的专栏
aimingoo的专栏
Security Archives - TechRepublic
Security Archives - TechRepublic
Y
Y Combinator Blog
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Latest news
Latest news
P
Privacy International News Feed
SecWiki News
SecWiki News
L
LINUX DO - 最新话题
M
MIT News - Artificial intelligence
W
WeLiveSecurity
博客园 - 聂微东
T
Tor Project blog
T
Troy Hunt's Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Engineering at Meta
Engineering at Meta

Whexy Blog

We lost the AIxCC. So, what now? Arm VMM with Apple's Hypervisor Framework Driving WaveShare E‐Paper Display with a Raspberry Pi Pico in MicroPython Use cgroup v2 inside docker containers Annual Hit Piece: Fuzzing Top Conference Paper Debunking Report Solving SSH Key Login Issues on Synology NAS Can SSD Cache Improve Synology NAS Write Speeds? Virtualization is all you need Running Windows Games on Mac Without Virtual Machines Tears of the Kingdom: End of an Era Anonymous CDN Traffic Relay Self-host Relay Service with CDN Home Networking Solution Building Your Own Blog System Connecting Smart Devices to SUSTech Campus Network Function Color Theory PMU Interrupts: How to handle them Asynchronous Mutex Using QEMU to run Linux images on M1 Macbook Alligator In Vest - My first research work Experience Using Several Plugins in Complex LaTeX Projects Variance in Rust Understanding Rust Generic Traits SUSTeam: Ultimate Gaming Platform Inline Assembly Language in C React Learning Notes Building a School Bus Schedule App for Apple Watch 12307 Train Ticket Purchase Platform Sakai and Local Folder Synchronization Building a Super Simple OpenJudge in Two Nights Setting Up Remote Backup for macOS Shell Script for Automatically Logging into SUSTech Campus Network Building a Movie Streaming System in the Dorm
Stop Forkin' Around: Faster Creating of Large Processes on Linux
Whexy · 2021-11-04 · via Whexy Blog

Whexy /

November 04, 2021

Forking is how a process in Linux is created. Even though the fork has been improved over the years to use the COW (copy-on-write) semantics, it still has to copy a certain amount of data from parent to child. Some students in the lab are working with a fuzzing machine, and they encounter some problems...

TL;DR

  • Use posix_spawn() to replace fork() if you want to launch a new program.
  • Use Pool to avoid time-consuming PT copying if you want to have multiple processes running simultaneously around a huge task.

Some students in the lab are working with a fuzzing machine. Fuzzing launches applications thousands of times with mutated input to see if a bug is triggered.

What bothered us is that launching the target application takes more and more time as the fuzzing goes. We sampled the program and found the most time-consuming part is the fork() system call. It turned out that the fuzzing process, collecting running information of every launch, grows larger and larger in the memory. When the process bloats to a certain level, cloning becomes a performance impact factor that we cannot ignore.

We know that fork() has been under optimization for decades. It now uses the COW (copy-on-write) semantics, which means no data in the user space would be copied until modified. But still, it has to copy a certain amount of data from parent to child.

We immediately thought that dynamic language interpreters face the same problem as we do. Along with the execution of the program, the interpreter process also experiences memory bloat. If they choose to create a new process, it can be pretty expensive. We investigated several solutions offered by Python in the face of multiprocess programs. Two of the most representative solutions are considered: pool and spawn.

Pool

The process pooling technique is a straightforward solution. It creates several empty processes at program initialization before the process grows too large and then assigns tasks to the processes for execution when needed. After the execution is finished, the processes are recycled to the pool to be used. 1

Limitation

  1. We must determine the number of concurrent processes required in advance. If I want to run 100 processes concurrently and find the pool only has five available, the program must stop and wait until running processes are freed and recycled.
  2. For processes that have been replaced with a brand new task by exec(), we cannot recycle it into the pool. That means we will lose the process forever.

Summary: Pooling techniques should be used for multitasking, especially for the initialization of multiprocess programs. However, it should not be used to launch other processes quickly.

Spawn

When launching other processes with exec(), we know that the copying in the fork() is unnecessary since the child process is immediately replaced with a new one. So what exactly does it copy? Well, the most prominent part is the page table. The page table is the part that Linux must copy to implement COW. It records whether the data in a particular memory address has been modified or not.

vfock()

The Berkeley version of Unix (BSD) introduced thevfork() system call in the early 1980s. vfork(2) does not copy the parent process to the child. Both processes share the parent's virtual address space; the parent is suspended until the child exits or calls exec() 2

🤔

posix_spawn()

On Linux, posix_spawn() is just implemented with fork() and exec(). It will use vfork() instead of fork() if it is safe. You can use posix_spawn(2) with the POSIX_SPAWN_USEVFORK flag to avoid the overhead of copying page tables when forking from a large process, while Linux can protect you from the deadlock we mentioned above.

This is the solution we finally adopted. It enables fast creation of new processes, avoids invalid copies of fork, and eliminates the need to create processes in advance, regardless of the pool size.

  1. Multi-processing in Python; Process vs Pool | by Nikhil Verma | Medium

  2. Minimizing Memory Usage for Creating Application Subprocesses (archive.org)

© LICENSED UNDER CC BY-NC-SA 4.0