Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to simulate slow DVD drive?

Does anyone know any feasible ways to simulate a slow DVD drive, e.g. over a mounted DMG/ISO image?

The goal is to program against a slow drive, thus a simulation requirement. Any ideas would be greatly appreciated!

Update: again, the goal would be to simulate a slow I/O process. Tools like Network Conditioner or Charles do not provide a solution unfortunately. trickle is out of date and no more actively developed :(

like image 948
Ain Tohvri Avatar asked Jul 07 '14 14:07

Ain Tohvri


2 Answers

With hdiutil, you could mount a disk image over a specially crafted HTTP server, but you do not control the OS cache and I/O slowness would not be fine-grained. I would suggest two non-network solutions.

Inserting slowness in I/O system calls

You could do slow-down I/O system calls, for example through DYLD_INSERT_LIBRARIES. This approach is quite easy and this is what I would try first.

You simply create a library with read(2) and pread(2) implementations like:

/* slow.c */
#define SLEEP_TIMESPEC {0, 25000000} // 25ms
ssize_t
read(int fildes, void *buf, size_t nbyte) {
    struct timespec s = SLEEP_TIMESPEC;
    (void) nanosleep(&s, NULL);
    return (ssize_t) syscall(SYS_read, fildes, buf, nbyte);
}

ssize_t
pread(int d, void *buf, size_t nbyte, off_t offset) {
    struct timespec s = SLEEP_TIMESPEC;
    (void) nanosleep(&s, NULL);
    return (ssize_t) syscall(SYS_pread, d, buf, nbyte, offset);
}

You might also need to implement readv(2). You simply need to compile this C code as a shared library and set DYLD_INSERT_LIBRARIES to load this library before running your program. You will probably also need to define DYLD_FORCE_FLAT_NAMESPACE. See dyld(1).

clang -arch i386 -arch x86_64 -shared -Wall slow.c -o slow.dylib

(The library is compiled universally, as the AIR app I had on disk was actually i386, not x86_64).

To test the library, simply do:

env DYLD_INSERT_LIBRARIES=slow.dylib DYLD_FORCE_FLAT_NAMESPACE=1 cat slow.c

You might want to try with values higher than 25ms for cat, e.g. 1 second which can be inlined as {1, 0}. Likewise, you should start your application from the command line:

env DYLD_INSERT_LIBRARIES=slow.dylib DYLD_FORCE_FLAT_NAMESPACE=1 path/to/YourApp.app/Contents/MacOS/YourApp

This will slow down every read calls (even through higher-level APIs). Some read operations will not be affected (e.g. mmap(2)), however, and you might want to slow down I/Os on some files but not on others. This later case can be handled by trapping open(2) but requires more work.

25ms per read accesses is enough to make any AIR app noticeably slower. Of course, you should adjust this value to your needs.

Working with a slower file system

Alternatively, you could implement a Fuse plug-in. This is especially easy if you start from LoopbackFS (C or ObjC).

Indeed, you can very easily call nanosleep(2) in the readFileAtPath:userData:buffer:size:offset:error: method or loopback_read function.

like image 56
Paul Guyot Avatar answered Oct 22 '22 10:10

Paul Guyot


Well, read and write speeds for the first DVD drives and players were of 1350 kB/s (or 1,32 MB/s); this speed is usually called "1×" and is the slowest speed that you can find in any DVD drive.

USB 1.1 flash drives have nominal speed of 12Mbps or 1,5MB/s, the actual speed is really close to a 1x DVD Drive.

So why don't you copy your image to an old USB 1.1 flash drive and mount it from there? If you don't have any you can find used ones in eBay.

I should also mention that broadband internet connections like ADSL2 or HSPA (3.5G) have actual download speed about 12Mbps which is what you want.

like image 2
Panayotis Avatar answered Oct 22 '22 10:10

Panayotis