Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial drop of the sources and a basic README. Signed-off-by: Andrei Warkentin <andrey.warkentin@gmail.com>
- Loading branch information
Showing
6 changed files
with
611 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
|
||
LOCAL_PATH:= $(call my-dir) | ||
|
||
include $(CLEAR_VARS) | ||
|
||
LOCAL_MODULE := sa | ||
LOCAL_MODULE_TAGS := eng | ||
|
||
LOCAL_SRC_FILES := \ | ||
sa.c dev.c | ||
|
||
#LOCAL_STATIC_LIBRARIES := libc | ||
#LOCAL_FORCE_STATIC_EXECUTABLE := true | ||
include $(BUILD_EXECUTABLE) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
CC := gcc | ||
CFLAGS := -O2 -Wall -Wextra -Wno-missing-field-initializers -Wno-unused-parameter -g2 | ||
LDFLAGS := -lrt -lm | ||
|
||
all: sa | ||
|
||
sa: sa.o dev.o | ||
sa.o: sa.c dev.h | ||
dev.o: dev.c dev.h | ||
|
||
clean: | ||
rm sa sa.o dev.o vm.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
Superalign | ||
========== | ||
|
||
A tool to measure read/write performance for block devices. | ||
It performs direct (unaffected by cache or filesystem) block transfers | ||
(reads or writes) linearly or "randomly" (LFSR) while collecting timing | ||
statistics on the transfers. You get min time/max time/avg time and standard | ||
deviation, so you can perform better analysis of the received data. It has | ||
tunable parameters such as aligning a transfer on a particular boundary, | ||
adding an offset to that alignment, or doing a discard on the device | ||
prior to transfers. | ||
|
||
The tool originally started out as an addition to Arnd Bergmann's | ||
excellent flashbench tool - git://git.linaro.org/people/arnd/flashbench.git | ||
|
||
It's a bit rough, and hopefully I'll have the time to clean up the code a | ||
bit soon. | ||
|
||
Examples | ||
======== | ||
|
||
Test 512-byte writes aligned to 4k. | ||
|
||
sa -s 512 -a 4096 /dev/mmcblk0p15 | ||
|
||
Test 1024-byte writes straddling 8k boundary. | ||
|
||
sa -s 1024 -a 8192 -o 7680 /dev/mmcblk0p15 | ||
|
||
Test 8k reads. | ||
|
||
sa -s 8192 -d /dev/mmcblk0p15 | ||
|
||
Test maximum 1000 different 8k writes (as opposite to as many as can | ||
fit in the device) | ||
|
||
sa -s 8192 -c 1000 /dev/mmcblk0p15 | ||
|
||
Repeat above test five times, blk erasing the device before each repeat. | ||
|
||
sa -s 8192 -c 1000 -r 5 -e /dev/mmcblk0p15 | ||
|
||
Use LFSR ("random") instead of sequential access. | ||
|
||
sa -s 8192 -R /dev/mmcblk0p15 | ||
|
||
Print verbose info. | ||
|
||
sa -v -s 8192 /dev/mmcblk0p15 | ||
|
||
Print really verbose info. | ||
|
||
sa -v -v -s 8192 /dev/mmcblk0p15 | ||
|
||
Contact Info | ||
============ | ||
|
||
Andrei Warkentin (andrey.warkentin@gmail.com, andreiw@motorola.com) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
#define _GNU_SOURCE | ||
#define _FILE_OFFSET_BITS 64 | ||
|
||
#include <sys/types.h> | ||
#include <sys/stat.h> | ||
#include <sys/time.h> | ||
#include <sys/ioctl.h> | ||
#include <unistd.h> | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <inttypes.h> | ||
#include <time.h> | ||
#include <errno.h> | ||
#include <fcntl.h> | ||
#include <limits.h> | ||
#include <sched.h> | ||
#include <string.h> | ||
#include <getopt.h> | ||
#include <stdbool.h> | ||
|
||
#include <linux/fs.h> | ||
|
||
#ifndef BLKDISCARD | ||
#define BLKDISCARD _IO(0x12,119) | ||
#endif | ||
|
||
#include "dev.h" | ||
|
||
#define MAX_BUFSIZE (64 * 1024 * 1024) | ||
|
||
static inline long long time_to_ns(struct timespec *ts) | ||
{ | ||
return ((long long) ts->tv_sec) * 1000 * 1000 * 1000 + ts->tv_nsec; | ||
} | ||
|
||
static long long get_ns(void) | ||
{ | ||
struct timespec ts; | ||
clock_gettime(CLOCK_REALTIME, &ts); | ||
return time_to_ns(&ts); | ||
} | ||
|
||
#if !(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) | ||
int posix_memalign(void **memptr, size_t alignment, size_t size) | ||
{ | ||
void *ptr; | ||
|
||
if (alignment % sizeof(void *)) | ||
return EINVAL; | ||
|
||
ptr = memalign(alignment, size); | ||
if (!ptr) | ||
return ENOMEM; | ||
|
||
*memptr = ptr; | ||
return 0; | ||
} | ||
#endif | ||
|
||
|
||
long long time_read(struct device *dev, off_t pos, size_t size) | ||
{ | ||
long long now = get_ns(); | ||
ssize_t ret; | ||
|
||
if (size > MAX_BUFSIZE) | ||
return -ENOMEM; | ||
|
||
do { | ||
ret = pread(dev->fd, dev->readbuf, size, (unsigned long long) pos % dev->size); | ||
if (ret > 0) { | ||
size -= ret; | ||
pos += ret; | ||
} | ||
} while (ret > 0 || errno == -EAGAIN); | ||
|
||
if (ret) { | ||
perror("time_read"); | ||
return 0; | ||
} | ||
|
||
return get_ns() - now; | ||
} | ||
|
||
long long time_write(struct device *dev, off_t pos, size_t size, enum writebuf which) | ||
{ | ||
long long now = get_ns(); | ||
ssize_t ret; | ||
unsigned long *p; | ||
|
||
if (size > MAX_BUFSIZE) | ||
return -ENOMEM; | ||
p = dev->writebuf[which]; | ||
|
||
do { | ||
ret = pwrite(dev->fd, p, size, (unsigned long long) pos % dev->size); | ||
if (ret > 0) { | ||
size -= ret; | ||
pos += ret; | ||
} | ||
} while (ret > 0 || errno == -EAGAIN); | ||
|
||
if (ret) { | ||
perror("time_write"); | ||
return 0; | ||
} | ||
|
||
return get_ns() - now; | ||
} | ||
|
||
long long time_erase(struct device *dev, off_t pos, size_t size) | ||
{ | ||
long long now = get_ns(); | ||
ssize_t ret; | ||
unsigned long long args[2] = { size, pos % dev->size }; | ||
|
||
if (size > MAX_BUFSIZE) | ||
return -ENOMEM; | ||
|
||
ret = ioctl(dev->fd, BLKDISCARD, &args); | ||
|
||
if (ret) { | ||
perror("time_erase"); | ||
} | ||
|
||
return get_ns() - now; | ||
} | ||
|
||
static void set_rtprio(void) | ||
{ | ||
int ret; | ||
struct sched_param p = { | ||
.sched_priority = 10, | ||
}; | ||
ret = sched_setscheduler(0, SCHED_FIFO, &p); | ||
if (ret) | ||
perror("sched_setscheduler"); | ||
} | ||
|
||
|
||
int setup_dev(struct device *dev, const char *filename) | ||
{ | ||
int err; | ||
void *p; | ||
set_rtprio(); | ||
|
||
dev->fd = open(filename, O_RDWR | O_DIRECT | O_SYNC | O_NOATIME); | ||
if (dev->fd < 0) { | ||
perror(filename); | ||
return -errno; | ||
} | ||
|
||
dev->size = lseek(dev->fd, 0, SEEK_END); | ||
if (dev->size < 0) { | ||
perror("seek"); | ||
return -errno; | ||
} | ||
|
||
err = posix_memalign(&dev->readbuf, 4096, MAX_BUFSIZE); | ||
if (err) | ||
return -err; | ||
|
||
err = posix_memalign(&p, 4096, MAX_BUFSIZE); | ||
if (err) | ||
return -err; | ||
memset(p, 0, MAX_BUFSIZE); | ||
dev->writebuf[WBUF_ZERO] = p; | ||
|
||
err = posix_memalign(&p, 4096, MAX_BUFSIZE); | ||
if (err) | ||
return -err; | ||
memset(p, 0xff, MAX_BUFSIZE); | ||
dev->writebuf[WBUF_ONE] = p; | ||
|
||
err = posix_memalign(&p , 4096, MAX_BUFSIZE); | ||
if (err) | ||
return -err; | ||
memset(p, 0x5a, MAX_BUFSIZE); | ||
dev->writebuf[WBUF_RAND] = p; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#ifndef FLASHBENCH_DEV_H | ||
#define FLASHBENCH_DEV_H | ||
|
||
#include <unistd.h> | ||
|
||
struct device { | ||
void *readbuf; | ||
void *writebuf[3]; | ||
int fd; | ||
off_t size; | ||
}; | ||
|
||
enum writebuf { | ||
WBUF_ZERO, | ||
WBUF_ONE, | ||
WBUF_RAND, | ||
}; | ||
|
||
extern int setup_dev(struct device *dev, const char *filename); | ||
|
||
long long time_write(struct device *dev, off_t pos, size_t size, enum writebuf which); | ||
|
||
long long time_read(struct device *dev, off_t pos, size_t size); | ||
|
||
long long time_erase(struct device *dev, off_t pos, size_t size); | ||
|
||
#endif /* FLASHBENCH_DEV_H */ |
Oops, something went wrong.