1# Dittosuite 2 3Dittosuite is a work in progress collection of tools that aims at providing 4a high-level language called Dittolang that defines operations. 5 6The defined Dittolang operations can be interpreted by Dittosim for simulation 7to provide a simulated performance measurement and quickly identify 8the goodness of a solution. 9 10Specularly, Dittobench interprets the Dittolang operations and executes them on 11a real device, tracking the behavior and measuring the performance. 12 13# How to run 14 15``` 16$ ./dittobench [options] [.ditto file] 17``` 18 19To run a benchmark, a well formed .ditto file must be provided, see section 20[How to write .ditto files](#how-to-write-ditto-files) 21In addition, these options can be set: 22 23- `--results-output=<int | string>` (default: report). Select the results output format. 24Options: report, csv with 0, 1 respectively. 25- `--log-stream=<int | string>` (default: stdout). Select the output stream for the log messages. 26Options: stdout, logcat with 0, 1 respectively. 27- `--log-level=<int | string>` (default: INFO). Select to output messages which are at or below 28the set level. Options: VERBOSE, DEBUG, INFO, WARNING, ERROR, FATAL with 0, 1, 2, 3, 4 and 5 29respectively. 30- `--parameters=string`. If the benchmark is parametric, all the parameters (separated by commas) 31can be given through this option. 32 33# How to write .ditto files 34 35Every .ditto file should begin with this skeleton: 36``` 37main: { 38 ... 39}, 40global { 41 ... 42} 43``` 44 45Optionally, it can contain `init` and `clean_up` sections: 46``` 47init: { 48 ... 49}, 50main: { 51 ... 52}, 53clean_up: { 54 ... 55}, 56global { 57 ... 58} 59``` 60 61## `global` 62 63Global section should contain general benchmark configuration. Currently available options: 64 65- (optional) `string absolute_path` (`default = ""`). Specifies the absolute path for the files. 66 67## `init` 68 69`init` is optional and can be used to initialize the benchmarking environment. It executes 70instructions similar to `main`, but the results are not collected in the end. 71 72## `main` 73 74`main` is the entry point for the benchmark. It can contain a single `instruction` or 75`instruction_set` (also with nested `instruction_set`). 76 77## `clean_up` 78 79`clean_up` is optional and can be used to reset the benchmarking environment to the initial state, 80e.g, delete benchmark files. Similar to `init`, it executes instructions like `main`, but results 81are not collected in the end. 82 83## `instruction` 84 85``` 86{ 87 <name of the instruction>: { 88 <first argument>, 89 <second argument>, 90 ... 91 }, 92 <general instruction options> 93} 94``` 95 96Currently available options: 97- (optional) `int repeat` (`default = 1`). Specifies how many times the instruction should be 98repeated. 99 100## `instruction_set` 101``` 102{ 103 instruction_set: { 104 instructions: { 105 { 106 <name of the first instruction>: { 107 <first argument>, 108 <second argument>, 109 ... 110 }, 111 <general instruction options> 112 }, 113 { 114 <name of the second instruction>: { 115 <first argument>, 116 <second argument>, 117 ... 118 }, 119 <general instruction options> 120 }, 121 ... 122 }, 123 iterate_options: {...} 124 }, 125 <general instruction options> 126} 127``` 128 129Instruction set is an Instruction container that executes the contained instructions sequentially. 130Instruction set can optionally iterate over a list and execute the provided set of instructions on 131each item from the list. To use it, `iterate_options` should be set with these options: 132- `string list_name` - Shared variable name pointing to a list of values. 133- `string item_name` - Shared variable name to which a selected value should be stored. 134- (optional) `Order order` (`default = SEQUENTIAL`) - Specifies if 135 the elements of the list should be accessed sequentially or randomly. Options: 136 `SEQUENTIAL`, `RANDOM`. 137- (optional) `Reseeding reseeding` (`default = ONCE`) - Specifies how often the random number 138generator should be reseeded with the same provided (or generated) seed. Options: `ONCE`, 139`EACH_ROUND_OF_CYCLES`, `EACH_CYCLE`. 140- (optional) `uint32 seed` - Seed for the random number generator. If the seed is not provided, 141current system time is used as the seed. 142 143## `multithreading` and `threads` 144 145``` 146multithreading: { 147 threads: [ 148 { 149 instruction: {...}, 150 spawn: <number of threads to spawn with the provided instruction> 151 }, 152 ... 153 ] 154} 155``` 156 157Multithreading is another instruction container that executes the specified instructions 158(or instruction sets) in different threads. If the optional `spawn` option for a specific 159instruction (or instruction set) is provided, then the provided number of threads will be created 160for it. 161 162## Example 163 164``` 165main: { 166 instruction_set: { 167 instructions: [ 168 { 169 open_file: { 170 path_name: "newfile2.txt", 171 output_fd: "test_file" 172 } 173 }, 174 { 175 close_file: { 176 input_fd: "test_file" 177 } 178 } 179 ] 180 }, 181 repeat: 10 182}, 183global { 184 absolute_path: "/data/local/tmp/"; 185} 186``` 187See more examples in `example/`. 188 189# Predefined list of instructions 190 191## `open_file` 192 193Opens the file with a file path or a shared variable name pointing to a file path. If neither of 194those are provided, a random name consisting of 9 random digits is generated. Optionally saves the 195file descriptor which can then be used by subsequent instructions. Also, can optionally create the 196file if it does not already exist. 197 198### Arguments: 199- (optional) `string path_name` - Specifies the file path.<br/> 200OR<br/> 201`string input` - Shared variable name pointing to a file path. 202- (optional) `string output_fd` - Shared variable name to which output file descriptor 203should be saved. 204- (optional) `bool create` (`default = true`) - Specifies if the file should be created if it does 205not already exist. If the file exists, nothing happens. 206 207## `delete_file` 208 209Deletes the file with a file path or a shared variable name pointing to a file path. 210Uses `unlink(2)`. 211 212### Arguments: 213- `string path_name` - Specifies the file path.<br/> 214OR<br/> 215`string input` - Shared variable name pointing to a file path. 216 217 218## `close_file` 219 220Closes the file with the provided file descriptor. 221Uses `close(2)`. 222 223### Arguments: 224- `string input_fd` - Shared variable name pointing to a file descriptor. 225 226## `resize_file` 227 228Resizes the file with the provided file descriptor and new size. If the provided size is greater 229than the current file size, `fallocate(2)` is used, while `ftruncate(2)` is used if the provided 230size is not greater than the current file size. 231 232### Arguments: 233- `string input_fd` - Shared variable name pointing to a file descriptor. 234- `int64 size` - New file size (in bytes). 235 236## `resize_file_random` 237 238Resizes the file with the provided file descriptor and a range for new size. New file size is 239randomly generated in the provided range and if the generated size is greater 240than the current file size, `fallocate(2)` is used, while `ftruncate(2)` is used if the generated 241size is not greater than the current file size. 242 243### Arguments: 244- `string input_fd` - Shared variable name pointing to a file descriptor. 245- `int64 min` - Minimum value (in bytes) 246- `int64 max` - Maximum value (in bytes) 247- (optional) `uint32 seed` - Seed for the random number generator. If the seed is not provided, 248current system time is used as the seed. 249- (optional) `Reseeding reseeding` (`default = ONCE`). How often the random number 250generator should be reseeded with the provided (or generated) seed. Options: `ONCE`, 251`EACH_ROUND_OF_CYCLES`, `EACH_CYCLE`. 252 253## `write_file` 254 255Writes to file with the provided file descriptor. For `SEQUENTIAL` 256access, the blocks of data will be written sequentially and if the end of 257the file is reached, new blocks will start from the beginning of the file. For 258`RANDOM` access, the block offset, to which data should be written, will 259be randomly chosen with uniform distribution. `10101010` byte is used for the 260write operation to fill the memory with alternating ones and zeroes. Uses 261`pwrite64(2)`. 262 263### Arguments: 264- `string input_fd` - Shared variable name pointing to a file descriptor. 265- (optional) `int64 size` (`default = -1`) - How much data (in bytes) should be written in total. 266If it is set to `-1`, then file size is used. 267- (optional) `int64 block_size` (`default = 4096`) - How much data (in bytes) should be written at 268once. If it is set to `-1`, then file size is used. 269- (optional) `int64 starting_offset` (`default = 0`) - If `access_order` is 270 set to `SEQUENTIAL`, then the blocks, to which the data should be written, 271 will start from this starting offset (in bytes). 272- (optional) `Order access_order` (`default = SEQUENTIAL`) - Order of the 273 write. Options: `SEQUENTIAL` and `RANDOM`. 274- (optional) `uint32 seed` - Seed for the random number generator. If the seed is not provided, 275current system time is used as the seed. 276- (optional) `bool fsync` (`default = false`) - If set, `fsync(2)` will be called after the 277execution of all write operations. 278- (optional) `Reseeding reseeding` (`default = ONCE`) - How often the random number 279generator should be reseeded with the provided (or generated) seed. Options: `ONCE`, 280`EACH_ROUND_OF_CYCLES`, `EACH_CYCLE`. 281 282## `read_file` 283 284Reads from file with the provided file descriptor. For `SEQUENTIAL` 285access, the blocks of data will be read sequentially and if the end of 286the file is reached, new blocks will start from the beginning of the file. For 287`RANDOM` access, the block offset, from which data should be read, will 288be randomly chosen with uniform distribution. Calls `posix_fadvise(2)` before 289the read operations. Uses `pread64(2)`. 290 291### Arguments: 292- `string input_fd` - Shared variable name pointing to a file descriptor. 293- (optional) `int64 size` (`default = -1`) - How much data (in bytes) should be read in total. 294If it is set to `-1`, then file size is used. 295- (optional) `int64 block_size` (`default = 4096`) - How much data (in bytes) should be read at 296once. If it is set to `-1`, then file size is used. 297- (optional) `int64 starting_offset` (`default = 0`) - If `access_order` is 298 set to `SEQUENTIAL`, then the blocks, from which the data should be read, 299 will start from this starting offset (in bytes). 300- (optional) `Order access_order` (`default = SEQUENTIAL`) - Order of the 301 read. Options: `SEQUENTIAL` and `RANDOM`. 302- (optional) `uint32 seed` - Seed for the random number generator. If the seed is not provided, 303current system time is used as the seed. 304- (optional) `ReadFAdvise fadvise` (`default = AUTOMATIC`) - Sets the argument 305 for the `posix_fadvise(2)` operation. Options: `AUTOMATIC`, `NORMAL`, 306 `SEQUENTIAL` and `RANDOM`. If `AUTOMATIC` is set, then 307 `POSIX_FADV_SEQUENTIAL` or `POSIX_FADV_RANDOM` will be used for `SEQUENTIAL` 308 and `RANDOM` access order respectively. 309- (optional) `Reseeding reseeding` (`default = ONCE`) - How often the random number 310generator should be reseeded with the provided (or generated) seed. Options: `ONCE`, 311`EACH_ROUND_OF_CYCLES`, `EACH_CYCLE`. 312 313## `read_directory` 314 315Reads file names from a directory and stores them as a list in a shared variable. Uses `readdir(3)`. 316 317### Arguments: 318- `string directory_name` - Name of the directory 319- `string output` - Shared variable name to which files names should be saved. 320 321## `invalidate_cache` 322 323Drops kernel clean caches, including, dentry, inode and page caches by calling sync() first and 324then writing `3` to `/proc/sys/vm/drop_caches`. No arguments. 325 326# Dependencies 327 328## Android 329 330The project is currently being developed as part of the Android Open Source 331Project (AOSP) and is supposed to run out-of-the-box. 332 333## Linux 334 335The following utilities are required to build the project on Linux: 336 337``` 338sudo apt install cmake protobuf-compiler 339 340``` 341 342# Testing 343 344## Linux 345 346A suite of unit tests is provided in the test/ directory. 347In Linux these tests can be run with the following commands: 348 349``` 350mkdir build 351cd build 352make 353cd test 354ctest 355``` 356 357 358# Use cases 359 360 361## File operations performance (high priority) 362 363Bandwidth and measurement when dealing with few huge files or many small files. 364Operations are combinations of sequential/random-offset read/write. 365 366Latency in creating/deleting files/folders. 367 368These operations should be able to be triggered in a multiprogrammed fashion. 369 370 371## Display pipeline 372 373A graph of processes that are communicating with each others in a pipeline of 374operations that are parallely contributing to the generation of display frames. 375 376 377## Scheduling (low priority) 378 379Spawning tasks (period, duration, deadline) and verifying their scheduling 380latency and deadline misses count. 381 382 383# Workflow example and implementation nits 384 385In the following scenario, two threads are running. 386 387T1 runs the following operations: Read, Write, Read, sends a request to T2 and 388waits for the reply, then Write, Read. 389T2 waits for a request, then Read, Write, then sends the reply to the requester. 390 391Operations are encoded as primitives expressed with ProtoBuffers. 392The definition of dependencies among threads can be represented as graphs. 393 394 395## Initialization phase 396 397The first graph traversal is performed at initialization time, when all the 398ProtoBuffer configuration files are distributed among all the binaries so that 399they can perform all the heavy initialization duties. 400 401 402## Execution phase 403 404After the initialization phase completes the graph can be traversed again to 405put all the workloads in execution. 406 407 408## Results gathering phase 409 410A final graph traversal can be performed to fetch all the measurements that 411each entity internally stored. 412 413 414## Post processing 415 416All the measurements must be ordered and later processed to provide useful 417information to the user. 418 419T1: INIT : [ RD WR RD ] SND RCV [ WR RD ] : END 420T2: INIT : RCV [ RD WR ] SND : END 421 422 423# Scratch notes 424 425critical path [ READ WRITE READ ] [ READ WRITE ] [ WRITE READ ] 426--------------------> 427 > < 428Thread1 III-XXXXXX|X-SSSSSS-XX-TTTT 429Thread2 III-XXXX|XXX-TTTT 430 ^ 431 432 > XXXXXXX XX< 433 XXXX 434 435 436READ WRITE READ 437 438---> 439 440vector<instr*> {read(), write(), read()}; 441-> start() 442 443 444RECEIVE READ WRITE READ SEND 445---> 446vector<instr*> {receive(), read(), write(), read(), send()}; 447start() 448 449lock on receive() 450 451