Sequence是一系列相同类型的值的集合,并且提供对这些值得迭代能力
迭代一个Sequence最常见的方式就是for-in,并且提供对这些值得迭代能力
我们经常把for-in循环用到Array,Dictonary,set等数据结构中,那是因为它们都是实现了Sequence协议。
Sequence协议的定义:
Sequence的协议里只有一个必须实现的方法就是makeIterator(),
makeIterator()需要返回一个Iterator,他就是一个IteratorProtocol类型。
只要提供一个Iterator就能实现Sequence,那么Iterator又是什么了???
Iterator 在 Swift 31 标准库中即为 IteratorProtocol,它用来为 Sequence 提供迭代能力。对于 Sequence,我们可以用for-in来迭代其中的元素,其实for-in的背后是 IteratorProtocol 在起作用。
IteratorProtocol 的定义如下:
associatedtype 声明了元素的类型
next()用来返回Sequence中的下一个元素,或者当没有了下一个元素就返回nil
举例1
这个例子中的Iterator不会迭代出任何元素,确切的说,这个Iterator在迭代时仅调用一次next()就结束了。
举例2
这个一直迭代出的是1
实现一个Sequence首先要实现一个Iterator
实现一个Iterator,接收一个字符串数组,并可以迭代这个数组中的所有字符串的首字母,当数组中的最后一个字符串迭代完后迭代完成,退出迭代
这个Iterator的需要输入一个字符串数组,在哪next()中,判断边界,并返回数组为offset的字符串的首字母,并将offset加1
有了实现好的Iterator,就可以简单的用他实现Sequence,在makeIterator()中返回这个Iterator即可
现在Sequence已经实现完成了,
打印结果:
值类型 Iterator
一般 Iterator 都是值类型的,值类型的 Iterator 的意思是:当把 Iterator 赋值给一个新变量时,是把原 Iterator 的所有状态拷贝了一份赋值给新的 Iterator,原 Iterator 在继续迭代时不会影响新的 Iterator。
例如用stride函数创建一个简单的 Sequence,它从 0 开始,到 9 截止,每次递增 1,即为 [0, 1, 2, , 8, 9]。
然后获取到它的 Iterator,调用 next() 进行迭代。
输出结果
然后做一个赋值 *** 作,建一个新的i2
然后输出
输出结果
这里的i1和i2相互不影响,赋值对i1做了一份完整的拷贝,这里的Iterator是一个值类型的Iterator
应用类型的Iterator
可以把任何一个值类型 Iterator 用AnyIterator这个包一下就形成了一个引用类型的 Iterator。
输出
输出结果
引用类型的 Iterator,再赋值给一个新的变量后,新的 Iterator 和原 Iterator 在进行迭代时会互相对对方产生影响。
学习博客参考
Swift 中的 Sequence(一)
Swift 中的 Sequence(二)
Sequence是数据中一个特殊存放等差数列的表,该表受数据库系统控制,任何时候数据库系统都可以根据当前记录数大小加上步长来获取到该表下一条记录应该是多少,这个表没有实际意义,常常用来做主键用。不过各个数据库厂商没有一个统一的标准--各有各的一套对Sequence的定义和 *** 作。
更详细的内容请参见百度百科:百度百科链接
(1)通过 uvm_do_pri 和 uvm_do_pri_with 改变所产生的transaction的优先级:
"my_case0sv"
class sequence0 extends uvm_sequence #(my_transaction);
virtual task body();
`uvm_do_pri(m_trans, 100)
or
`uvm_do_pri_with(m_trans, 200, {m_transploadsize < 500;})
第二个参数是优先级,这个数必须是一个大于等于-1的整数,数字越大,优先级越高。
(2)sequencer的仲裁算法:
SEQ_ARB_FIFO(默认仲裁算法,遵循先入先出,不考虑优先级)
SEQ_ARB_WEIGHTED(加权的仲裁)
SEQ_ARB_RANDOM(完全随机选择)
SEQ_ARB_STRICT_FIFO(严格按照优先级,当有多个同一优先级的sequence时,按照先入先出的顺序选择)
SEQ_ARB_STRICT_RANDOM(严格按照优先级,当有多个同一优先级的sequence时,随即从最高优先级中选择)
SEQ_ARB_USER (用户自定义的仲裁算法)
若想要优先级起作用,应该设置仲裁算法为SEQ_ARB_STRICT或者SEQ_ARB_STRICT_RANDOM:
envi_agtsqrset_arbitration(SEQ_ARB_STRICT_FIFO);
fork
seq0start(envi_agt_sqr);
seq1start(envi_agt_sqr);
join
(3)lock *** 作
grab *** 作(比lock优先级更高,放入sequencer仲裁队列的最前面)
is_relevent() 函数(1说明此sequence有效,否则无效)
wait_for_relevent() 函数
(1)uvm_do系列
(2)uvm_create 与 uvm_send
(3)uvm_rand_send,与uvm_send类似,唯一区别是它会对transaction进行随机化
m_trans = new("m_trans");
`uvm_rand_send(m_trans);
(4)`uvm_do系列宏其实是将下述动作封装在了一个宏中:
tr = new("tr");
start_item(tr);
assert(trrandomize() with {trploadsize() == 200;});
finish_item(tr);
(5)pre_do (task), mid_do (function), post_do (function)
(1)嵌套的sequence:在一个sequence的body中,除了可以使用uvm_do宏产生transaction外,该可以启动其他的sequence,直接在新的sequence的body中调用定义好的sequence。
(2)uvm_do, uvm_send, uvm_rand_send, uvm_create宏,其第一个参数除了可以是transaction的指针外,还可以是sequence的指针。start_item & finish_item,这两个任务的参数必须是transaction的指针。
(3)sequence与transaction都可以调用randomize进行随机话,都可以由rand修饰符的成员变量。在sequence中定义的rand类型变量以向产生的transaction传递约束时,变量的名字一定要与transaction中相应字段的名字不同。
(4)`uvm_declare_p_sequencer(my_sequencer) == (my_sequencer p_sequencer);这个过程在pre_body()之前就完成了,因此在sequence中可以直接使用成员变量p_sequencer来访问sequencer中的成员变量。
(1)实现sequence之间同步最好的方式就是使用virtual sequence。virtual sequence不发送transaction,它只是控制其他的sequence,起统一调度的作用。为了使用virtual sequence,一般需要一个virtual sequencer,其里面包含指向其他真实sequencer的指针。
(2)一般来说。只在最顶层的virtual sequence中控制objection。
(1)在sequence中获取参数
sequence的路径:uvm_test_topenvi_agtsqrcase0_sequence
uvm_config_db#(int)::set(this, "envi_agtsqr", "count", 9);
因为sequence在实例化时名字一般是不固定的,而且有时时未知的(比如使用default_sequence启动的sequence的名字就是未知的),所i使用通配符。
uvm_config_db#(int)::get(null, get_full_name(), "count", count));
在get函数原型中,第一个参数必须是component,而sequence不是一个component,所以这里不能使用this指针,只能使用null或uvm_root::get()。
(2)在sequence中设置参数
uvm_config_db#(bit)::set(uvm_root::get(), "uvm_test_topenv0scb", "cmp_en", 0);
uvm_config_db#(bit)::set(uvm_root::get(), "uvm_test_topv_sqr", "first_start", 0);
(3)一个sequence是在task phase中运行的,当其设置一个参数的时候,起事件往往是不固定的。针对这种不固定的设置参数的方式,UVM提供了wait_modified任务。当它检测当第三个参数的值被更新过后,它就返回,否则一直等待在那里:
uvm_config_db#(bit)::wait_modified(this, "", "cmp_en");
(1)在driver中,
rsp = new("rsp");
rspset_id_info(req);
seq_item_portput_response(rsp);
seq_item_portitem_done();
or
rsp = new("rsp");
rspset_id_info(req);
seq_item_portitem_done(rsp);
在sequence中,
virtual task body();
get_response(rsp);
(1)随机选择sequence
class simple_seq_library extends uvm_sequence_library #(my_transaction);
function new(string name = "simple_seq_library");
suprenew(name);
init_sequence_library();
endfunction
`uvm_object_utils(simple_seq_library)
`uvm_sequence_library_utils(simple_seq_library);
endclass
一个sequence在定义时使用宏uvm_add_to_seq_lib(seq0, simple_seq_library)来将其加入某个sequence library中。一个sequence可以加入多个sequence library中。
(2)控制选择算法
typedef enum {UVM_SEQ_LIB_RAND, UVM_SEQ_LIB_RANDC, UVM_SEQ_LIB_ITEM, UVM_SEQ_LIB_USER} uvm_sequence_lib_mode;
UVM_SEQ_LIB_RAND:完全随机。
UVM_SEQ_LIB_RANDC:将加入其中的sequence随机排一个顺序,然后按照此顺序执行,可以保证每个sequence执行一遍。配置方式:
uvm_config_db#(uvm_sequence_lib_mode)::set(this, "envi_agtsqrmain_phase", "default_sequenceselection_mode", UVM_SEQ_LIB_RANDC);
UVM_SEQ_LIB_ITEM:sequence library并不执行其sequence队列中的sequence,而是自己产生transaction。
UVM_SEQ_LIB_USER:用户自定义选择的算法。此时需要用户重载select_sequence参数:
virtual function int unsigned select_sequence(int unsigned max);
endfunction
(3)控制执行次数
min_random_count, max_random_count
(4)UVM提供了一个类uvm_sequence_library_cfg来对sequence library进行配置:
uvm_sequence_library_cfg cfg;
superbuild_phase(phase);
cfg = new("cfg", UVM_SEQ_LIB_RANDC, 5, 20);
uvm_config_db#(uvm_object_wrapper)::set(this, "envi_agtsqrmain_phase", "default_sequence", simple_seq_library::type_id::get());
uvm_config_db#(uvm_sequence_library_cfg)::set(this "envi_agtsqrmain_phase", "default_sequenceconfig", cfg);
or
simple_seq_library seq_lib;
superbuild_phase(phase);
seq_lib = new("seq_lib");
seq_libselection_mode = UVM_SEQ_LIB_RANDC;
seq_libmin_random_count = 10;
seq_libmax_random_count = 15;
uvm_config_db#(uvm_sequence_base)::set(this, "envi_agtsqrmain_phase", "default_sequence", seq_lib);
sequence 是 pg 自带的高效的自增id工具(也叫序列)。sequence 使用了轻量级锁的方式来做到高效自增id的,所以会比 UPDATE 行锁快。sequence 的返回数据类型默认是64位的整数,pg 10 可以自定 smallint, integer 或者是 bigint。
sequence 是可以保证自增数据不重复的,也就是说每次自增后都会持久化保存,那么为了继续提高性能,可以加上 CACHE 参数(默认为1),每个进程(连接)可以缓存一个子序列在当前进程内存里面,当子序列用完了才会去原序列取新的子序列。
这个用个例子简单说一下,创建 sequence temp_seq3 时用了 CACHE 10,A session 可以获取到的值是 110,B session 可以获取到的值是 1120,那么获取顺序可能是 (A, A, B, A),返回值是 (1, 2, 11, 3),这个不是严格自增的序列,但可以保证回次返回都是唯一的,用了 CYCLE 参数的除外。
根据文档和源码( link 第80行),缓存在内存里面的最大值(cached)是每个进程都不一样的,所以如果要求严格自增的服务不能用 CACHE。
这里写三种用 pg 做自增id的方式
测试命令,在 MacOS 上用 docker 开一个 pg 在里面运行一下 pgbench 脚本,其中 sqlsql 的内容替换成对应的压测脚本。
TPS: 986
TPS: 7332
TPS: 7451
看看微信的分布式id生成器,原理都差不多,"实际应用中每次提升的步长为10000" = "CACHE 10000"。 link
以上优化已经是用在友好速搭电商系统的订单号和优惠券号生成服务中,为商家提供更快更可靠的服务。
利用UCSC的Table Browser页面可以非常简单的单独或批量获取gene中的各类序列,使用方法:
goto >
题目
实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。
如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。
必须 原地 修改,只允许使用额外常数空间。
以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1
题意分析
看具体例子,一个排列为124653,如何找到它的下一个排列,因为下一个排列一定与124653有尽可能长的前缀,所以,脑洞大开一下,从后面往前看这个序列,如果后面的若干个数字有下一个排列,问题就得到了解决。
第一步:找最后面1个数字的下一个全排列。
124653,显然最后1个数字3不具有下一个全排列。
第二步:找最后面2个数字的下一个全排列。
124653,显然最后2个数字53不具有下一个全排列。
第三步:找最后面3个数字的下一个全排列。
124653,显然最后3个数字653不具有下一个全排列。
------插曲:到这里相信大家已经看出来,如果一个序列是递减的,那么它不具有下一个排列。
第四步:找最后面4个数字的下一个全排列。
124653,我们发现显然最后4个数字4653具有下一个全排列。因为它不是递减的,例如6453,5643这些排列都在4653的后面。
我们总结上面的 *** 作,并总结出重复上面 *** 作的两种终止情况:
1:从后向前比较相邻的两个元素,直到前一个元素小于后一个元素,停止
2:如果已经没有了前一个元素,则说明这个排列是递减的,所以这个排列是没有下一个排列的。
124653这个排列终止情况是上面介绍的第一种,从后向前比较相邻的2个元素,遇到4<6的情况停止。
并且我们可以知道:
1:124653和它的下一个排列的公共前缀为12(因为4653存在下一个排列,所以前面的数字12保持不变)
2:4后面的元素是递减的(上面介绍的终止条件是前一个元素小于后一个元素,这里是4<6)
现在,我们开始考虑如何找到4653的下个排列,首先明确4后面的几个数字中至少有一个大于4
4肯定要和653这3个数字中大于4的数字中(6,5)的某一个进行交换。这里就是4要和6,5中的某一个交换,很明显要和5交换,如果找到这样的元素呢,因为我们知道4后面的元素是递减的,所以在653中从后面往前查找,找到第一个大于4的数字,这就是需要和4进行交换的数字。这里我们找到了5,交换之后得到的临时序列为5643,交换后得到的643也是一个递减序列。
所以得到的4653的下一个临时序列为5643,但是既然前面数字变大了(4653--->5643),后面的自然要变为升序才行,变换5643得到5346
所以124653的下一个序列为125346
看一个permutation,比如
125430
从末尾开始,找到decreasing subsequence,5430,因为来调5330无论怎么调,都不可能有比它更小的,数也被自然的分成两部分(1,2) 和 (5,4,3,0)
下一步是找这个sequence里面第一个比前面部分,比2大的,3,也很容易理解,因为下一个必定是(1,3)打头
交换 3和2 ,变成 (1,3,5,4,2,0),再把后面的部分reverse,得到后面部分可得到的最小的
这个时候,得到下一个sequence 130245`
思路
暴力法,从后向前搜索,直到出现满足交换的数。
) 建立序列命令
CREATE SEQUENCE [user ]sequence_name
[increment by n]
[start with n]
[maxvalue n | nomaxvalue]
[minvalue n | nominvalue];
INCREMENT BY 指定序列号之间的间隔 该值可为正的或负的整数 但不可为 序列为升序 忽略该子句时 缺省值为
START WITH 指定生成的第一个序列号 在升序时 序列可从比最小值大的值开始 缺省值为序列的最小值 对于降序 序列可由比最大值小的值开始 缺省值为序列的最大值
MAXVALUE 指定序列可生成的最大值
NOMAXVALUE 为升序指定最大值为 为降序指定最大值为
MINVALUE 指定序列的最小值
NOMINVALUE 为升序指定最小值为 为降序指定最小值为
) 更改序列命令
ALTERSEQUENCE [user ]sequence_name
[INCREMENT BY n]
[MAXVALUE n| NOMAXVALUE ]
[MINVALUE n | NOMINVALUE]
修改序列可以
修改未来序列值的增量
设置或撤消最小值或最大值
改变缓冲序列的数目
指定序列号是否是有序
) 删除序列命令
DROP SEQUENCE [user ]sequence_name
从数据库中删除一序列
创建一个序列号的语句
CREATE SEQUENCE EXAM_NO_SEQ
START WITH
MAXVALUE
MINVALUE
CYCLE
CACHE
NOORDER;
PB中取序列号的用法
string v_exam_no
//获取申请序号
SELECT exam_no_seq nextval INTO :v_exam_no FROM dual
using ghis_database;
if ghis_database SQLCODE<> then
messagebox( 取检查序号出错 )
return
end if
其他版本
oracle中没有自增类型的字段的 所以通常情况下需要定义一个sequence来作为自动增长类型字段的数据
于是记录了一些关于oracle sequence的资料 已备查用!
Oracle中的序列(sequence)
: 如何定义一个序列
仅向前的数字变量(和SQL中的自动编号有点像 identity( ) )
格式:
create sequence <序列名称>
start with <起始数>
increment by <增长量>
[maxvalue 值]
[minvalue 值]
[cycle 当到达最大值的时候 将继续从头开始]
[Nocycle 一直累加 不循环]
[Cache ]
注意
第一次NEXTVAL返回的是初始值;随后的NEXTVAL会自动增加你定义的INCREMENT BY值 然后返回增加后的值 CURRVAL 总是返回当前SEQUENCE的值 但是在第一次NEXTVAL初始化之后才能使用CURRVAL 否则会出错 一次NEXTVAL会增加一次SEQUENCE的值
如果指定CACHE值 ORACLE就可以预先在内存里面放置一些sequence 这样存取的快些 cache里面的取完后 oracle自动再取一组到cache 使用cache或许会跳号 比如数据库突然不正常down掉(shutdown abort) cache中的sequence就会丢失 所以可以在create sequence的时候用nocache防止这种情况
example:
create sequence mySeq
start with
increment by
maxvalue
minvalue
cycle
:怎么去取序列数据:
currval >curenvalue
nextVal >NextVlaue
example:
select mySeq nextVal from dual
注意一点:currval只有当nextVal执行一次以后才可以用
在创建表的时候 可以使用序列
具体例子:
create table 公司基本信息表
(
ComPID int
CompName varchar ( )
)
insert into 公司基本信息表 values(mySeq nextVal AA )
:如何修改序列
修改前提是sequence 的owner 或者有ALTER ANY SEQUENCE 权限才能改动sequence 可以alter除start至以外的所有sequence参数 如果想要改变start值 必须 drop sequence 再 re create
Alter sequence 的例子
ALTER SEQUENCE emp_sequence
INCREMENT BY
MAXvalue
CYCLE 到 后从头开始
NOCACHE
影响Sequence的初始化参数
SEQUENCE_CACHE_ENTRIES =设置能同时被cache的sequence数目
也可以这样
alter sequence mySeq maxvalue
注意 不能改start with 其他随便改(设置minvalue值的时候不能大于当前值)
:如何查看删除某个表空间所有序列
查看
select from user_sequences
如何删除:
drop sequence 序列名称
sequence属于什么对象
sequence不属于某个表 也不属于某个字段 sequence仅仅属于某个用户
lishixinzhi/Article/program/Oracle/201311/17518
以上就是关于Swift中的Sequence基本的使用全部的内容,包括:Swift中的Sequence基本的使用、sequence的意思、第六章 UVM中的sequence等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)