Dust and Stars - 1992 | Chapter 150 | Compilation and Bone Gaps | English
In Computer Lab B, only one of the backup machines could run at full load. Lin Chen applied for access; the administrator’s approv
Chapter 150: Compilation and Bone Gaps
In Computer Lab B, only one of the backup machines could run at full load. Lin Chen applied for access; the administrator’s approval email arrived twenty minutes later. He plugged in his USB drive and dragged the Python 2.6 source package and the gcc toolchain into a local directory. The time in the lower-right corner of the screen flipped to 18:40. Forty-one hours and twenty minutes remained before the deadline.
He dealt with the environment first. The training camp’s shared network blocked outside access, so he could only rely on local mirrors and cached documentation. The C API header files were scattered across different directories; he created symbolic links by hand, pointing Python.h and structmember.h to the proper paths. He typed make into the terminal, and the progress bar began its slow crawl upward. The fans’ droning filled the empty lab, magnified into something like the low, rough breathing of a beast. The student from the provincial capital at the neighboring station had left long ago, half a bottle of unfinished cola and a dog-eared copy of Introduction to Algorithms still on the desk. Lin Chen did not look at them. He looked only at his own terminal.
Under the desk, his left foot had gone completely numb. Only an occasional muscle spasm tugging at the Achilles tendon reminded him it was still there. Lin Chen nudged his chair back half an inch and let his left leg hang free, avoiding pressure on it. He opened his editor and began writing the skeleton of the C extension. Python 2.4 had no ready-made multiprocessing module, and os.fork() was unavailable in a Windows environment. He had no choice but to fall back to a single-process architecture and peel the most time-consuming regex matching and string parsing down into the C layer.
static PyObject* parse_line(PyObject* self, PyObject* args)
He typed out the argument parsing, memory allocation, and regex compilation calls line by line. Pointer work had to be exact; a single out-of-bounds access would lead straight to a segmentation fault. Out of habit, he marked the ownership of each block of memory in comments: // malloc: 512 bytes for buffer, // free on Py_DECREF. Code was not art. It was a ledger. Every line had to balance cost against return. He pulled out the blank notebook and drew the lifetime of the C extension’s memory as a flowchart: allocate, use, release, catch exceptions. The page filled with dense arrows, like a net. He knew he could not afford mistakes. The cost of a mistake was not repeating a course. It was being pushed out entirely.
The first compilation failed. Error: undefined reference to 'pcre_compile'. He had forgotten to link the PCRE library. The training camp server did not have it preinstalled, so he had to compile a lightweight static version from the source package himself. Reconfigure, make, make install. While the progress bar climbed again, he got up to fetch water. The motion-activated lights in the corridor did not come on. He moved slowly with one hand on the wall, his weight on the right foot, the toes of the left only barely touching the ground. The dull ache in the seams of his bones rolled in like a tide, receded, then surged back. He drank two mouthfuls of warm water and returned to his seat. His stomach felt hollow with hunger. He took out the two cold buns he had bought that morning, broke them apart, and swallowed them with the water. The skin had hardened; chewing them was like grinding sawdust. He did not care. As long as there were calories, it was enough. He opened his online banking page. Balance: 810.4 yuan. The bonus for an A-level project at the training camp was two thousand. If he got it, it would cover exactly the three-month gap after Xiaoman’s next round of dressing changes, with enough left for his own meals. Numbers were cold, but they were clear.
The second compilation passed. It produced a .so file. He wrote a simple test script, imported the module, and fed it five hundred thousand lines of simulated logs. The terminal output read: Memory: 14.2MB | Time: 3.8s. It met the mark. He let out a breath, but he did not stop. The production environment meant two million lines, and it required file-lock contention under concurrent writes to be minimized. He brought in mmap, mapping the file directly into virtual memory to bypass the overhead of system calls. The Python-layer mmap module under 2.6 was limited, so he sank down into C once more and used the mmap() system call directly on the file descriptor.
Time slid toward 23:15. He was the only person left in the lab. The air conditioning had shut off, and the room was stifling. He took off his jacket and sat in a washed-out short-sleeved shirt. Sweat ran down his back and soaked the chair. Every forty-five minutes, he forced himself to stand and move for three minutes. Whenever his left foot touched the floor, his knee would soften uncontrollably for an instant; he would catch himself on the desk with his right hand and wait for the dizzy spell to pass. He could not sit too long, and he could not stop. Progress was the only medicine. He stared at the memory curve on the screen as if he were staring at a taut string.
One in the morning. The two-million-line test began. The memory curve rose steadily and stopped at 41 MB. The time display read: 14.2s. That worked out to roughly 71 milliseconds per ten thousand lines, far below the red line of 300 milliseconds. He stared at the screen without moving his fingers. It had gone too smoothly. He opened the system monitor and discovered the CPU usage was only 35 percent. The bottleneck was not parsing. It was I/O. The hard drive was an old SATA disk; its random read-write speed could not keep up. He had to decouple the parsing logic from disk writes.
He created a new ring buffer and implemented a lock-free queue in C. The producer thread would handle mmap reads and regex matching; the consumer thread would write the results into a temporary file. Thread synchronization would rely on pthread_cond_wait and mutexes. The amount of code surged, and the logic grew exponentially more complex. He had to guarantee that the buffer would neither overflow nor spin empty. Pointer arithmetic, the wake-up order of condition variables—one wrong step and the whole thing would deadlock. He took out a red pen and worked through the thread state machine in his notebook: idle, waiting, ready, running. He marked every possible exception branch at every stage. He wrote: if (pthread_mutex_lock != 0) goto cleanup;. Defensive programming. No room for luck.
At 3:20 in the morning, the third compilation ran. The terminal spat out Segmentation fault (core dumped). He fixed his eyes on the error line: the consumer thread had not properly checked the condition variable before reading from an empty buffer. He added a while (queue_empty) loop and compiled again. Run. Peak memory: 46 MB. Time: 11.8s. Fifty-nine milliseconds per ten thousand lines. CPU usage jumped to 78 percent. It met the standard.
He leaned back in his chair and closed his eyes. His ears were full of nothing but the roar of the fans and the sound of blood moving through him. His left foot was numb enough to feel absent, save for the involuntary twitching in his calf. He pulled a spray bottle of Yunnan Baiyao from the drawer and sprayed his ankle and knee twice. The sharp smell of medicinal herbs mixed with the ozone in the lab and cleared his head. He opened the notebook and put a check mark after the third item. For the moment, the crisis of being on the edge had eased. But it was not over.
The time in the lower-right corner of the screen changed to 04:50. He organized the code and packed it into project_07_v3.tar.gz. He wrote a brief readme, noting peak memory, latency data, and environment dependencies. He was preparing to shut the machine down when the phone on the desk vibrated once.
A message from Engineer Li on the intranet: “Wednesday, 2 p.m., Lab B. Bring a runnable prototype and complete logs. The client has temporarily adjusted the acceptance criteria: the prototype must support resumable transfer and exception rollback. The test dataset has been updated to three million lines and includes 15% corrupted blocks. Submit final architecture confirmation by 9 a.m. tomorrow.”
Lin Chen stared at the screen. Resumable transfer. Exception rollback. Three million lines. Corrupted blocks.
He reopened the editor. The cursor blinked over the blank space. Beneath the desk, his left foot twitched faintly. He did not move. He created a new file and named it checkpoint_manager.c.
Outside the window, the sky was beginning to pale into gray-white. The clouds were thick. He typed the first line of a comment: // Goal: persistent state, crash recovery, zero memory leaks.
His fingers came down on the keys. The rhythm was slow, but steady.
More from WayDigital
Continue through other published articles from the same publisher.
Comments
0 public responses
All visitors can read comments. Sign in to join the discussion.
Log in to comment