使用脚本自动跑实验(Ubuntu),将实验结果记录在文件中,并在实验结束之后将结果通过邮件发送到邮箱,最后在windows端自动解析成excel表格(因为要在windows的origin上作图)。
touch run.sh #创建但不编辑脚本
chmod 777 run.sh #给予脚本执行权限
gedit run.sh #编辑脚本
x='100'或r='rm -rf'即可,${x}在执行的时候以字符串形式读取。$(())包裹的变量将以数字形式解析,比如在某行中有这个参数:--num=$((${n}*1000000)),这里${n}将被以数字形式解析。receive='/home/renjc/easy-test2.txt'之后touch ${receive},当然变量本质上是以字符串形式读取的,用receive='../xx.txt'当然也行,还更灵活,就是程序容易整错。volumn='128 512 1024 2048'即是数组,也可以当做一串字符串来解析。#遍历数组,循环,遍历文件夹
workloads="./works/workloada.spec ./works/workloadb.spec ./works/workloadf.spec"
for file_name in $workloads; do
./ycsbc -db redis -threads 1 -P $file_name
done
#下面这个是单纯的for循环
for ((tn=1; tn<=8; tn=tn*2)); do
doneworkload
#下面这个是遍历文件夹workload_dir中所有以workload开头的spec文件
for file_name in $workload_dir/workload*.spec; do
done
#函数作用是记录name,当前时间,以及初步计算value
recordstart(){
time=$(date)
echo "db_name: ${1}" >> ${receive}
echo -n "start_time: ${time} and Value:" >> ${receive}
echo "scale=2;${3}*${4}/1024/1000"|bc >> ${receive}
#纯shell对除法的支持比较粗糙,如果想要保留两位小数,可以向上面这行一样。
}
$(date)代表当前时间,带年月日时分秒的那种。${1}就代表函数第一个参数,以此类推,其中按照惯例,${0}代表函数名(或者说程序名)。调用函数也很简单,recordstart name ${v}即可调用,函数名后面的都是参数,在函数中使用${1},${2},${3}识别。echo -n "xx" >> ${receive},只有echo的话,会输出到控制台中,加上>> ${receive}会输出到这个文件里面,加上-n代表这一行不换行,因为echo默认是每次都换行的。
使用以上几种组合基本可以完成绝大部分实验与程序。以下作为例子
receive='/home/renjc/spkv/resault/easy-test2.txt'
touch ${receive}
ulimit -Sn 16384
ulimit -Hn 32768
#解除堆栈限制,可能需要,先预备
rocksdb_base='rocksdb-base/db_bench'
rocksdb_split='rocksdb-split/db_bench'
wisckey='WiscKey-master/WiscKey/out-static/db_bench'
# database="${rocksdb_base} ${rocksdb_split} ${wisckey}"
rmstore='rm -rf /home/renjc/spkv/db/*'
recordstart(){
#${1} db_name,${2} number of threads,${3} value_size,${4} number of rows
time=$(date)
echo "db_name: ${1}" >> ${receive}
echo "thread_num: ${2}" >> ${receive}
echo "value_size: ${3}" >> ${receive}
echo "num:${4}" >> ${receive}
echo "start_time: ${time}" >> ${receive}
echo -n "resault GB is:" >> ${receive}
echo "scale=2;${3}*${4}/1024/1000/1000"|bc >> ${receive}
}
recordend(){
time=$(date)
echo "done_time: ${time},----clean store and sleep 10s-------------------" >> ${receive}
${rmstore}
sleep 10s
}
#rocksdb 用一个杠两个杠都行,leveldb/wisckey只能用两个,统一采用两个杠杠。
const_arg='--db=/home/renjc/spkv/db --bloom_bits=0 --write_buffer_size=134217728'
rocksdb_arg='--compression_type=none' #Wisckey do not support but rocksdb need
sperate_arg='--enable_blob_files=true' #rokcsdb的键值分离版本就是原来的版本上加一个参数,所以使用相同路径加一个参数
benchmarks='--benchmarks=fillrandom,stats,readrandom,stats'
volumn='128 512 1024 2048'
num='5 10'
echo "test start" >> ${receive}
for v in ${volumn}
do
for n in ${num}
do
recordstart r_sperate 1 ${v} 10000000
./${rocksdb_base} ${const_arg} ${rocksdb_arg} --num=$((${n}*1000000)) --value_size=${v} ${benchmarks} ${sperate_arg} >> ${receive}
recordend
recordstart r_split 1 ${v} 10000000
./${rocksdb_split} ${const_arg} ${rocksdb_arg} --num=$((${n}*1000000)) --value_size=${v} ${benchmarks} >> ${receive}
recordend
recordstart wisckey 1 ${v} 10000000
./${wisckey} ${const_arg} --num=$((${n}*1000000)) --value_size=${v} ${benchmarks} >> ${receive}
recordend
done
done
echo "all done" >> ${receive}
echo "run over \n file in attach" | mutt -s "Test run over" renjc0816@qq.com -a ${receive}
mail如何添加附件没整成功,现在使用mutt命令实现,控制台执行:
sudo apt-get install mutt安装
echo "Body : run over \n file in attach" | mutt -s "Test run over" renjc0816@qq.com -a 'path'即可。
其中,"Body"开头的是邮件内容,-s后面的是邮件标题,-a后面的'path'是附件地址,正常使用不用带单引号,写在脚本里时可以用之前创建的${receive}代替。邮件是立刻发送的,收件箱里找不到请到垃圾箱里面找找。如下:

这个程序自己写去
如何生成excel可读取的文件?csv文件:csv文件可以被excel读取,第一行表示excel的那个列名,用逗号分割,底下的数据也是,每一行代表excel表格内的一行,每一列的内容用逗号分割,英文的逗号。
至于解析实验结果,就逐行读取,然后捕捉自己想要的关键词就行了,性能啥的就不用考虑优化了,咋简单咋来。
下面的是自用的解析rocksdb的参数的,仅供参考
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <fstream>
#include <iomanip>
#define default_file_path "E:\\Code\\Windows\\FileOperate\\easy-test.txt"
#define resault_file_name "E:\\Code\\Windows\\FileOperate\\resault.csv"
using namespace std;
struct arguments {
arguments(string s,string t):name(s),data(t){}
string name;
string data;
};
void readFile(vector<arguments>& resault,const string& file_path);
void trimEmpty(string &s);//用于去除字符串首尾空格
void recordString(const string& type, string& s,vector<arguments>& resault);//用于格式化并记录data
void recordInFile(const vector<arguments>& resault);//解析结果记录到文件中,测试用
void recordCSVMode(const vector<arguments>& resault);
void printInShell(const vector<arguments>& resault);//打印到控制台,测试用
//按顺序存放需要捕捉的关键词,问题在于只能顺序
//如果该行以该关键词结尾,那么就将所有的东西记录下来
//注意,这个数组并不是最终参数结果,有的一行记了两三个参数
const static vector<string> key_words = {"db_name","thread_num","start_time","Values","Entries","RawSize","FileSize",
"fillrandom","Cumulative compaction","Cumulative writes","Cumulative stall",
"readrandom","Cumulative compaction","Cumulative writes","Cumulative stall","done_time"};
const static int length = key_words.size();
int main(int arg_count, char *arg_value[]){
string file_path = default_file_path; //默认路径
if(arg_count > 1) file_path = arg_value[1];
//argv[0]为程序名,这点由shell传统决定,argv[1]是程序名的输入
vector<arguments> resault;
readFile(resault,file_path);
// printInShell(resault);
// recordInFile(resault);
recordCSVMode(resault);
// getchar();
return 0;
}
void readFile(vector<arguments>& resault,const string& file_path){
int flag = 0;
string line;//按行读取
ifstream fp(file_path);
while(getline(fp, line)) {
string head = line.substr(0,line.find(":"));
trimEmpty(head);
if(key_words[flag] == head) {
string tail = line.substr(line.find(":")+1);
recordString(key_words[flag],tail,resault);
// resault.push_back(arguments(key_words[flag],tail));
flag = flag == length - 1 ? 0 : flag + 1;
}
}
}
void trimEmpty(string &s){
//删除字符串的前后空格
if (!s.empty()){
s.erase(0, s.find_first_not_of(" "));
s.erase(s.find_last_not_of(" ") + 1);
}
}
void recordString(const string& type, string& s,vector<arguments>& resault){
//为什么不使用精确的下表标位置
//因为数据的长度不一定,所以必须使用标点符号等来相对定位。
trimEmpty(s);
if(type == "fillrandom" || type == "readrandom"){
int start = s.find("op")+3;
int len = s.find(";") - start;
string kops = s.substr(start,len);
resault.push_back(arguments("Kops",kops));
start = s.find(";")+1;
len = s.find_last_of("s")+1 - start;
s = s.substr(start,len);
trimEmpty(s);
resault.push_back(arguments("Speed",s));
return;
}
if(type == "Cumulative stall") {
string stall_time = s.substr(0,s.find(" "));
resault.push_back(arguments("Cumulative stall",stall_time));
s = s.substr(s.find(",") + 2);
resault.push_back(arguments("Average stall",s));
return;
}
if(type == "start_time" || type == "done_time"){
s = s.substr(s.find_last_of(":")-5,8);
}else if(type == "Values"){
s = s.substr(0,s.find(" "));
}else if(type == "RawSize" || type == "FileSize"){
s = s.substr(0,s.find_last_of(" "));
}else if(type == "Cumulative compaction"){
s = s.substr(0,s.find(" ")+3);
}else if(type == "Cumulative writes"){
int start = s.find_last_of(":") + 2;
int length = s.find_last_of(",") - start;
s = s.substr(start,length);
}
resault.push_back(arguments(type,s));
return;
}
void recordInFile(const vector<arguments>& resault){
ofstream record;
remove(resault_file_name);
record.open(resault_file_name, ios::app);
for (size_t i = 0; i < resault.size(); i++) {
record << left << setw(25) << setfill(' ') << resault[i].name;
record << resault[i].data << endl;
}
}
void recordCSVMode(const vector<arguments>& resault){
//key_words的长度并不是最终参数的数量
ofstream record;
remove(resault_file_name);
record.open(resault_file_name, ios::app);
size_t point = 0,point_t = 0;
string head = resault[0].name;
while(resault[point+1].name != head){
record << resault[point++].name << ",";
}
record << resault[point].name << endl;
for (size_t i = 0; i < resault.size(); i++) {
if(point_t < point) {
++point_t;
record << resault[i].data << ",";
} else {
point_t = 0;
record << resault[i].data << endl;
}
}
}
void printInShell(const vector<arguments>& resault){
// 格式化输出,left表示偏左,setw是设置宽度,stefill是设置填充字符
for (size_t i = 0; i < resault.size(); i++) {
cout << left << setw(25) << setfill(' ') << resault[i].name;
cout << resault[i].data << endl;
}
}
解析结果如下(这个花花绿绿的颜色是vscode的插件,创建csv文件之后就会提示安装)

excel可以直接打开,wps没下就没试。excel打开如下:

刚打开可能数据显得有点拥挤,可以另存为excel正常的格式进行调整,要不然调整了这csv文件也保存不下来的。
好了,这波整完就可以开始摸鱼啦把实验放那跑,跑完手机会收到邮件提示,回去自动解析一波就行,至于更多的分类啥的功能,都可以在程序中实现。
(>.o)
我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我正在使用ruby1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("