Skip to content
Snippets Groups Projects
Commit 6d7783f0 authored by Jing Lan's avatar Jing Lan
Browse files

p3 draft update

parent 4825f358
No related branches found
No related tags found
No related merge requests found
......@@ -141,35 +141,38 @@ This method facilitates testing and subsequent benchmarking. The method should:
1. Remove all local file previously uploaded by method `Upload()`
2. Reset all associated server state (e.g., counters, paths, etc)
## Part 3: Multi-threading Client
## Part 3: Multi-threading Server/Client
With the Global Interpreter Lock (GIL), commonly-used CPython does not support parallel multi-threading execution. However, multi-threading can still boost the performance of our small system (why?). In Part 3, you are required to add threading support to `client.py`, then `server.py`.
### Client
More specifically, you will need to manually create *N* threads for `client.py` (with thread management primitives come with the `threading` module) to concurrently process the provided `workload`. For example, each worker thread may repeatedly fetch one command line from `workload` and process it. You can load all command strings to a list, then provide thread-safe access to all launched threads (how?).
## Part 4: Benchmarking the System
You don't need to explicitly create threads using Python calls because
gRPC will do it for you. Set `max_workers` to 8 so that gRPC will
create 8 threads:
**HINT:** Before moving to work on the `server`, test your multi-threading client by running it with a single thread:
```bash
python3 client.py workload 1
```
### Server
Now with concurrent requests sent from `client.py`, you must correspondingly protect your server from data race with `threading.Lock()`. Make sure only one thread can modify the server state (e.g., names, paths, counters...). Note that you don't need to explicitly create threads for `server.py` as gRPC can do that for you. The following example code creates a thread pool with 8 threads:
```python
grpc.server(
futures.ThreadPoolExecutor(max_workers=????),
options=[("grpc.so_reuseport", 0)]
futures.ThreadPoolExecutor(max_workers=8),
options=[("grpc.so_reuseport", 0)]
)
```
Now that your server has multiple threads, your code should hold a
lock (https://docs.python.org/3/library/threading.html#threading.Lock)
whenever accessing any shared data structures, including the list(s)
of files (or whatever data structure you used). Use a single global
lock for everything. Ensure the lock is released properly, even when
there is an exception. Even if your chosen data structures provide any
guarantees related to thread-safe access, you must still hold the lock
when accessing them to gain practice protecting shared data.
**Requirement:** reading and writing files is a slow operation, so
your code must NOT hold the lock when doing file I/O.
**Requirement 1:** The server should properly acquire then release the lock. A single global lock is sufficient. Lock release should also work with any potential exceptions.
**Requirement 2:** The server *MUST NOT* hold the lock when reading or writing files. A thread should release the lock right after it has done accessing the shared data structure. How could this behavior affect the performance?
## Part 4: Benchmarking the System
## Grading
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment