Hello,
I am William Wilcox, a private financial consultant
/Account portfolio manager. I happen to have managed a
particular account for a Resident Foreigner, here in
the United Kingdom, who accidentally died Interstate,
leaving in our care a reasonable amount in a
Domiciliary United States Dollars Account. The
Highly confidential nature of our client and our
Business Confidential disposition on Client to client
Basis did not warrant us to have an easily
identifiable next of Kin to this particular Client. I
have made several enquiries to locate any of my
client_s relatives immediate and extended, this has
proved unsuccessful. Hence, I am contacting you. I
need you to assist in securing the money and property
left behind by my client before they get confiscated
or declared unserviceable by the Finance House here in
the United Kingdom where his deposits were lodged. The
Finance House has issued Government Mandatory
Formality, notice to provide the Next of Kin or have
the account confiscated within the next one month.
Since I have been unsuccessful in locating any of his
relatives for over two years and convinced that no one
is coming up and having satisfied the mandatory legal
requirement of Beneficiary/next of kin Notification, I
now seek a Reliable and Trustworthy person,
with your consent and perfect understanding, to
present you as the next of kin of the deceased so that
the proceeds of this account valued at Twenty One
Million, Three Hundred And Twenty Thousand United
States Dollars, interest Inclusive, can be paid into
an account to be provided by you( preferably outside
the United Kingdom Financial Institutions or its
Isles), as the perceived Next Of Kin Legally and
Otherwise.
I have all necessary documents to back up these claims
as Next of Kin on your behalf. All I require is your
honest cooperation and confidence in me, which I
believe that it is not easy, as we have not done
similar transaction before and not by reference. Hence
the reason I choose to call this a Deal, as it will be
based on trust to enable us see this transaction
through. I guarantee that this will be executed under
a legitimate arrangement that will protect you from
any breach of the law. I would advise that you give
this a positive consideration and get back to me soon
I would be very flexible as well as considerate in
percentage share that will be given to you for your
assistance.
Upon receipt of your response l will send to you my
private number so that you can reach me for further
discussion regarding this project.
Please send mail to my private email for security reasons
<EMAIL_ADDRESS>Fax: + 44<PHONE_NUMBER>
Best regards,
William Wilcox.


My Web Development starting point
"How you do anything is how you do everything"
Cultural blogs
Reflection
Habbits
Emotional intelligence
Meditation process
Daily mindfulness
Self confidence
Emotional control
Technical blogs
Part 1
Part 2
Part 3
Part 4
Part 5
Part 6


data class DisallowablePlaybackAction
Maps a playback action to whether the user is disallowed from doing it
(common, js, jvm)
<init> |
Maps a playback action to whether the user is disallowed from doing it <init>(action: PlaybackAction, disallowed: Boolean) |
(common, js, jvm)
action |
The PlaybackAction for which the explicit setting is provided val action: PlaybackAction |
(common, js, jvm)
disallowed |
Whether the action is not allowed. val disallowed: Boolean |


Galactic Import
问题描述 :
Each galaxy contains at least one and at most 26 planets. Each planet within a galaxy is identified by a unique letter from A to Z.
Each planet specializes in the production and export of one good. Different planets within the same galaxy export different goods.
Some pairs of planets are connected by hyperspace shipping lines. If planets A and B are connected, they can trade goods freely. If planet C is connected to B but not to A, then A and C can still trade goods with each other through B, but B keeps 5% of the shipment as a shipping fee. (Thus A only receives 95% of what C shipped, and C receives only 95% of what A shipped.) In general, any two planets can trade goods as long as they are connected by some set of shipping lines, but each intermediate planet along the shipping route keeps 5% of what it shipped (which is not necessarily equal to 5% of the original shipment).
At least one planet in each galaxy is willing to open a ThrustoZoom shipping line to Earth. A ThrustoZoom line is the same as any other shipping line within the galaxy, as far as business is concerned. For example, if planet K opens a ThrustoZoom line to Earth, then the Earth can trade goods freely with K, or it can trade goods with any planet connected to K, subject to the usual shipping fees.
HyperCommodities has assigned a relative value (a positive real number less than 10) to each planet’s chief export. The higher the number, the more valuable the product. More valuable products can be resold with a higher profit margin in domestic markets. The problem is to determine which planet has the most valuable export when shipping fees are taken into account.
输入:
1) The letter used to represent the planet.
2) A space.
3) The relative value of the planet’s export, in the form d.dd.
4) A space.
5) A string containing letters and/or the character `*’; a letter indicates a shipping line to that planet, and a `*’ indicates a willingness to open a ThrustoZoom shipping line to Earth.
输出:
样例输入:
1 F 0.81 * 5 E 0.01 *A D 0.01 A* C 0.01 *A A 1.00 EDCB B 0.01 A* 10 S 2.23 Q* A 9.76 C K 5.88 MI E 7.54 GC M 5.01 OK G 7.43 IE I 6.09 KG C 8.42 EA O 4.55 QM Q 3.21 SO
样例输出:
Import from F Import from A Import from A
被归在最短路径下面，其实完全可以用bfs解决，要说bfs也算是dijkstra的一种特殊情况吧。
这道题的最大的难度不是解决问题的过程，而是读题的过程，题意叙述可够难为人的，英文啊英文。。。
星球间运送货物（双向的），每个星球都有独特的资源。如果不能直接到达的话中间星球要收取费用5%，问运送到地球可以达到最大价值的是从哪个星球运送的，不要管那个星号“*”所描述的乱七八糟的东西，就是星球与地球有直接的连接。单终点最短路径转化为单源最短路径（当然若果你不用bfs的话）。
#include<iostream> #include<cstring> #include<queue> using namespace std; int main(void) { int n; char c; int k,t,e,mark; int i,j,from,to; int dist[27]; int mat[27][27]; double max,value[27]; queue<int> q; while( cin >> n ) { getchar(); for( i = 0; i <= 26; i++ ) for( j = 0; j <= 26; j++ ) mat[i][j] = 0; for( i = 0; i <= 26; i++ ) dist[i] = value[i] = 0; //以上为初始化 for( i = 1; i <= n; i++ ) { c = getchar(); from = c - 'A'; cin >> value[from]; getchar(); while( (c=getchar()) != '/n') { if( c == '*') to = 26; else to = c- 'A'; mat[from][to] = mat[to][from] = 1; } } //以上为图的输入过程 dist[26] = 1; q.push(26); while( !q.empty() ) { e = q.front(); q.pop(); for( j = 0; j < 26; j++) { k = mat[e][j]; if( k == 1 && dist[j] == 0) { dist[j] = dist[e] + 1; q.push(j); } } } //以上为bfs的过程 for( i = 0,max = -1; i < 26; i++ ) { if( dist[i] > 2 ) { t = dist[i] - 2; while( t--) value[i] *= 0.95; } else if( dist[i] != 2) value[i] = 0; if( value[i] > max ) max = value[mark = i]; } cout << "Import from " << (char)(mark+'A') << endl; } return 0; }
解题报告转自：http://blog.csdn.net/dangwenliang/article/details/5797289
目测会火
51行错了，改为：void Union(struct subset subsets[], int x, int y)
为什么暴力求解方法循环到sqrt(n) 就可以了呢
We do not harbor that I couldn’t remove other individuals’ problems whenever this arrived at.
第63行是不是漏了 return 1 + dis_right; ?
第一段代码中：
next = next ;
明显不对吧，应该是 next =j;才对
感觉第二种方法其实也不是很好，不过的确要比第一种方法要好一点。
全是智力分析的题
妈呀！这个Dijkstra模板好长OwQ！
正在练习，很有帮助
一开始就规定不相邻节点颜色相同，可能得不到最优解。我想个类似的算法，也不确定是否总能得到最优解：先着一个点，随机挑一个相邻点，着第二色，继续随机选一个点，但必须至少有一个边和已着点相邻，着上不同色，当然尽量不增加新色，直到完成。我还找不到反例验证他的错误。。希望LZ也帮想想, 有想法欢迎来邮件。谢谢
秒！~
给力，赞一个


" />
" />
{include file="common/header"/}
total()){foreach($list as $row){ ?>
..
人阅读
暂无记录
';} ?>
total()){foreach($list as $row){ ?>
{include file="common/footer"/}


Stone: Dead-Simple Data Persistence
Get Version
0.1.2→ ‘stone’
Sections
Getting Up and Running Usage ContactWhat
For small applications, a database can be overkill for storing your data in a consistent and organized manner. Therefore, Stone was built to provide plug-and-play data persistence for any application or framework. It is fast, and it is easy… therefore it is good.
You can check out an application that uses Merb+Stone here.
The source for that blog is here.
Installing
sudo gem install stone
Up and Running
Rails
- Create a new file in
config/initializers
calledstone.rb
- Add the following code to your new file:
require 'stone' Stone.start(Dir.pwd, Dir.glob(File.join(Dir.pwd,"app/models/*")), :rails)
- Open your
environment.rb
file and look for the following lines:# Skip frameworks you're not going to use (only works if using vendor/rails). # To use Rails without a database, you must remove the Active Record framework # config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
- Uncomment the last of those lines, and leave only active_record,
so that it looks like this:
# Skip frameworks you're not going to use (only works if using vendor/rails). # To use Rails without a database, you must remove the Active Record framework config.frameworks -= [ :active_record ]
- Create some models! We’ll use an Author as an example:
stone-gen model Author name:string
Merb
- Add the following code to your
init.rb
file:dependency 'stone' # add this in the Merb::BootLoader.after_app_loads block # at the bottom of init.rb Stone.start(Dir.pwd, Dir.glob(File.join(Dir.pwd,"app/models/*")), :merb)
- Create some models! We’ll use an Author as an example:
stone-gen model Author name:string
Everywhere Else
Stone was designed to provide easy data storage management for any app, not just web ones.
- Wherever you load your app, add the following:
require 'stone' # replace path/to/models/ with wherever your models/resources may be Stone.start(Dir.pwd, Dir.glob(File.join(Dir.pwd,"path/to/models/*")))
- Create some models! See Models.
That’s it! Remember, there are no databases to install with Stone. Instead,
your data gets persisted to files within myapp/datastore/
.
Usage
Model Files
Models are really easy to create. Here is an example:
class Person include Stone::Resource # gives you access to persistence methods # defines an attribute called "name" of type String field :name, String # defines an attribute called "email" of type String. # Since :unique => true is set, "email" must be unique. field :email, String, :unique => true # Notifies Stone of a relationship between People and Jewels. # This allows for @person.jewels retrieval. has_many :jewels # both name and email must be present or errors will be added validates_presence_of :name, :email end
For more validation methods, see here.
Get, Post, Put, and Delete
- Getting
Author.get(some_id) # gets Author with some_id Author[some_id] # same as get() # brings back first author whose name is "Nick DeMonner" Author.first(:name => "Nick DeMonner") # brings back first author whose name contains "Nick" Author.first(:name.includes => 'Nick') # brings back all authors whose email contains "gmail.com", and who # were created before today Author.all(:email.includes => "gmail.com", :created_at.lt => DateTime.now) # brings back all Authors created before today, and orders them descending # from most recent to least Author.all(:created_at.lt => DateTime.now, :order => {:created_at => :desc})
- Posting
author = Author.new author.name = "Nick DeMonner" author.save # calls Author.post after validations
- Putting
author = Author[some_id] # gets Author with id of some_id # updates name and calls Resource.save (which in turn calls Resource.put # because this resource is being updated, not created) author.update_attributes(:name => "Bob Bobberson")
- Deleting
Author.delete(some_id) # deletes Author at some_id
A Word About Finding Stuff
Stone uses a series of unique methods (à la DataMapper) to finding objects. You may use the following methods when searching:
- Matches all objects whose
field
is greater thanthing
:field.gt => thing
- Matches all objects whose
field
is greater than or equal tothing
:field.gte => thing
- Matches all objects whose
field
is less thanthing
:field.lt => thing
- Matches all objects whose
field
is less than or equal tothing
:field.lte => thing
- Matches all objects whose
field
includesthing
:field.includes => thing
- Matches all objects whose
field
is equal tothing
:field.equals => thing
- Matches all objects whose
field
Regexp matchesthing
:field.matches => regexp
- Matches all objects whose
field
does not equalthing
:field.not => thing
License
This code is free to use under the terms of the MIT license.
Contributing
PLEASE. Stone is extremely immature at this point—“stable” is the watchword for the moment.
- You can grab the source using Git:
git clone git://github.com/ndemonner/stone.git
The code is pretty well specced out, so make sure you don’t break anything
by running rake ok
every once in a while.
Please add specs for any new functionality you might add, and hit me up to commit. =D
Contact
Comments are welcome. Join me in the IRC channel #stone on freenode.
Nick DeMonner, 17th April 2008
Theme extended from Paul Battley


{% extends "layouts/error.html" %}
{% block title %}Server Error{% endblock %}
{% block subtitle %}An unexpected application error has occured{% endblock %}
{% block body %}
The application erred while trying to respond to your request.
This could be due to a number of factors such as high load, availability issues, issues with third-party services.
{% endblock %}


Total reports:
{{episodeStats.reports.total | number}}
Offenses:
{{episodeStats.reports.offense | number}}
Citations/Warnings:
{{episodeStats.reports.uttAndWarnings | number}}
CJIS Reports:
{{episodeStats.reports.cjis | number}}
Field Contacts:
{{episodeStats.reports.fcc | number}}
Trespasses:
{{episodeStats.reports.trespass | number}}
Crashes:
{{episodeStats.reports.crash | number}}
Area Patrol:
{{episodeStats.reports.ap | number}}


When you have parired observations: (x_1, y_1), (x_2, y_2), ..., (x_n, y_n). You want to creeate a scatter plot of the pairs.
If your data are held in two parallel vectors, x and y, then use them as arguments of plot():
plot(x,y)If your data is held in a (two-column) data frame, plot the data frame:
plot(cars)
# Assign three variables
a <- 1
b <- -3
# print variable 'a' without 'print' function
# display variable 'b' by using 'print' function
# Assign three variables
a <- 1
b <- -3
# print variable 'a' without 'print' function
a
# display variable 'b' by using 'print' function
print(b)
test_object("a", undefined_msg = "Make sure to define a variable `a`.",
incorrect_msg = "Make sure that you assign the correct value to `a`.")
test_object("b", undefined_msg = "Make sure to define a variable `b`.",
incorrect_msg = "Make sure that you assign the correct value to `b`.")
test_output_contains("a", incorrect_msg = "Make sure that you should type a to print out value in variable 'a'.")
test_output_contains("print(b)", incorrect_msg = "Make sure that you should use print function to print out value in variable 'b'.")
test_function("print"")
success_msg("Great! Head over to the next exercise.")


Topics
This topic describes how to control Ansible settings.
Certain settings in Ansible are adjustable via a configuration file (ansible.cfg). The stock configuration should be sufficient for most users, but there may be reasons you would want to change them. Paths where configuration file is searched are listed in reference documentation.
If installing Ansible from a package manager, the latest ansible.cfg
file should be present in /etc/ansible
, possibly
as a .rpmnew
file (or other) as appropriate in the case of updates.
If you installed Ansible from pip or from source, you may want to create this file in order to override default settings in Ansible.
An example file is available on GitHub.
For more details and a full listing of available configurations go to configuration_settings. Starting with Ansible version 2.4, you can use the ansible-config command line utility to list your available options and inspect the current values.
For in-depth details, see Ansible Configuration Settings.
Ansible also allows configuration of settings using environment variables. If these environment variables are set, they will override any setting loaded from the configuration file.
You can get a full listing of available environment variables from Ansible Configuration Settings.
Not all configuration options are present in the command line, just the ones deemed most useful or common. Settings in the command line will override those passed through the configuration file and the environment.
The full list of options available is in ansible-playbook and ansible.


I’m A Celeb fans in hysterics as Martin Kemp ‘gets revenge’ on son Roman
Roman mocked his singing on Monday's show
by Rebecca CarterMartin Kemp has admitted he voted for his son Roman to do the Bushtucker eating trial on I'm A Celebrity.
Capital FM DJ Roman will take on the challenge tonight (November 20) alongside campmate Adele Roberts.
On Monday's show, Roman had mocked his dad's singing and it seems Martin had the perfect revenge.
Read more: I'm A Celebrity: Roman Kemp and Adele Roberts' spat over Jane McDonald
Martin tweeted last night: "Just voted for my boy to eat Kangaroo [Expletive]. That’ll show him!! @romankemp."
Fans were in hysterics over Martin's tweet.
One person said: "Not a sentence I expected to ever see but I’m not disappointed either."
Another wrote: "Brilliant that’s what I would do to my kids."
A third added: "Parenting at its best right there!!! He’s great."
It comes after Roman poked fun at his dad as he said Martin "couldn't even sing or play an instrument" when he first started in Spandau Ballet in the late seventies.
He cheekily added: "He still can't. He still hasn't realised his mic wasn't on for Live Aid!"
But the conversation then turned serious as Roman continued: "When they went back on tour, post brain tumour and stuff like that, he forgot everything. So he forgot how to play and he forgot all the songs.
"He knew how to play but he didn't know any of the songs. So I had to learn them and then teach him. I learnt all the Spandau songs and then retaught them to him.
"All it did was make us like this [close]. Like super close. How can my dad not be my hero through all of that. We're a proper unit."
Roman will take on tonight's Bushtucker trial, Just Desserts, alongside Adele.
In a preview clip released by ITV, Adele is seen being served up pig's uterus as she exclaims: "Oh my Goodness! What even is that?!"
Read more: I'm A Celebrity: Roman Kemp's impressions of Ant and Dec steal the show
As she puts the whole thing into her mouth, Roman tells her: "That's it, well done. Think of all that amazing food we're going to have tonight. Don't worry about it. Swallow the juices, focus on the chew."
I'm A Celebrity continues tonight at 9pm on ITV.
Are you looking forward to watching the trial? Leave us a comment on our Facebook page @EntertainmentDailyFix and let us know.


| EventName | Description |
|---|---|
| ARITH.CYCLES_DIV_BUSY | Cycles the divider is busy |
| ARITH.DIV | Divide Operations executed |
| ARITH.MUL | Multiply operations executed |
| BACLEAR.BAD_TARGET | BACLEAR asserted with bad target address |
| BACLEAR.CLEAR | BACLEAR asserted, regardless of cause |
| BACLEAR_FORCE_IQ | Instruction queue forced BACLEAR |
| BPU_CLEARS.EARLY | Early Branch Prediciton Unit clears |
| BPU_CLEARS.LATE | Late Branch Prediction Unit clears |
| BPU_MISSED_CALL_RET | Branch prediction unit missed call or return |
| BR_INST_DECODED | Branch instructions decoded |
| BR_INST_EXEC.ANY | Branch instructions executed |
| BR_INST_EXEC.COND | Conditional branch instructions executed |
| BR_INST_EXEC.DIRECT | Unconditional branches executed |
| BR_INST_EXEC.DIRECT_NEAR_CALL | Unconditional call branches executed |
| BR_INST_EXEC.INDIRECT_NEAR_CALL | Indirect call branches executed |
| BR_INST_EXEC.INDIRECT_NON_CALL | Indirect non call branches executed |
| BR_INST_EXEC.NEAR_CALLS | Call branches executed |
| BR_INST_EXEC.NON_CALLS | All non call branches executed |
| BR_INST_EXEC.RETURN_NEAR | Indirect return branches executed |
| BR_INST_EXEC.TAKEN | Taken branches executed |
| BR_INST_RETIRED.ALL_BRANCHES | Retired branch instructions (Precise Event) |
| BR_INST_RETIRED.CONDITIONAL | Retired conditional branch instructions (Precise Event) |
| BR_INST_RETIRED.NEAR_CALL | Retired near call instructions (Precise Event) |
| BR_INST_RETIRED.NEAR_CALL_R3 | Retired near call instructions Ring 3 only(Precise Event) |
| BR_MISP_EXEC.ANY | Mispredicted branches executed |
| BR_MISP_EXEC.COND | Mispredicted conditional branches executed |
| BR_MISP_EXEC.DIRECT | Mispredicted unconditional branches executed |
| BR_MISP_EXEC.DIRECT_NEAR_CALL | Mispredicted non call branches executed |
| BR_MISP_EXEC.INDIRECT_NEAR_CALL | Mispredicted indirect call branches executed |
| BR_MISP_EXEC.INDIRECT_NON_CALL | Mispredicted indirect non call branches executed |
| BR_MISP_EXEC.NEAR_CALLS | Mispredicted call branches executed |
| BR_MISP_EXEC.NON_CALLS | Mispredicted non call branches executed |
| BR_MISP_EXEC.RETURN_NEAR | Mispredicted return branches executed |
| BR_MISP_EXEC.TAKEN | Mispredicted taken branches executed |
| BR_MISP_RETIRED.NEAR_CALL | Mispredicted near retired calls (Precise Event) |
| CACHE_LOCK_CYCLES.L1D | Cycles L1D locked |
| CACHE_LOCK_CYCLES.L1D_L2 | Cycles L1D and L2 locked |
| CPU_CLK_UNHALTED.REF | Reference cycles when thread is not halted (fixed counter) |
| CPU_CLK_UNHALTED.REF_P | Reference base clock (133 Mhz) cycles when thread is not halted (programmable counter) |
| CPU_CLK_UNHALTED.THREAD | Cycles when thread is not halted (fixed counter) |
| CPU_CLK_UNHALTED.THREAD_P | Cycles when thread is not halted (programmable counter) |
| CPU_CLK_UNHALTED.TOTAL_CYCLES | Total CPU cycles |
| DTLB_LOAD_MISSES.ANY | DTLB load misses |
| DTLB_LOAD_MISSES.PDE_MISS | DTLB load miss caused by low part of address |
| DTLB_LOAD_MISSES.STLB_HIT | DTLB second level hit |
| DTLB_LOAD_MISSES.WALK_COMPLETED | DTLB load miss page walks complete |
| DTLB_MISSES.ANY | DTLB misses |
| DTLB_MISSES.STLB_HIT | DTLB first level misses but second level hit |
| DTLB_MISSES.WALK_COMPLETED | DTLB miss page walks |
| ES_REG_RENAMES | ES segment renames |
| FP_ASSIST.ALL | X87 Floating point assists (Precise Event) |
| FP_ASSIST.INPUT | X87 Floating poiint assists for invalid input value (Precise Event) |
| FP_ASSIST.OUTPUT | X87 Floating point assists for invalid output value (Precise Event) |
| FP_COMP_OPS_EXE.MMX | MMX Uops |
| FP_COMP_OPS_EXE.SSE_DOUBLE_PRECISION | SSE* FP double precision Uops |
| FP_COMP_OPS_EXE.SSE_FP | SSE and SSE2 FP Uops |
| FP_COMP_OPS_EXE.SSE_FP_PACKED | SSE FP packed Uops |
| FP_COMP_OPS_EXE.SSE_FP_SCALAR | SSE FP scalar Uops |
| FP_COMP_OPS_EXE.SSE_SINGLE_PRECISION | SSE* FP single precision Uops |
| FP_COMP_OPS_EXE.SSE2_INTEGER | SSE2 integer Uops |
| FP_COMP_OPS_EXE.X87 | Computational floating-point operations executed |
| FP_MMX_TRANS.ANY | All Floating Point to and from MMX transitions |
| FP_MMX_TRANS.TO_FP | Transitions from MMX to Floating Point instructions |
| FP_MMX_TRANS.TO_MMX | Transitions from Floating Point to MMX instructions |
| ILD_STALL.ANY | Any Instruction Length Decoder stall cycles |
| ILD_STALL.IQ_FULL | Instruction Queue full stall cycles |
| ILD_STALL.LCP | Length Change Prefix stall cycles |
| ILD_STALL.MRU | Stall cycles due to BPU MRU bypass |
| ILD_STALL.REGEN | Regen stall cycles |
| INST_DECODED.DEC0 | Instructions that must be decoded by decoder 0 |
| INST_QUEUE_WRITE_CYCLES | Cycles instructions are written to the instruction queue |
| INST_QUEUE_WRITES | Instructions written to instruction queue. |
| INST_RETIRED.ANY | Instructions retired (fixed counter) |
| INST_RETIRED.ANY_P | Instructions retired (Programmable counter and Precise Event) |
| INST_RETIRED.MMX | Retired MMX instructions (Precise Event) |
| INST_RETIRED.TOTAL_CYCLES | Total cycles (Precise Event) |
| INST_RETIRED.X87 | Retired floating-point operations (Precise Event) |
| IO_TRANSACTIONS | I/O transactions |
| ITLB_FLUSH | ITLB flushes |
| ITLB_MISS_RETIRED | Retired instructions that missed the ITLB (Precise Event) |
| ITLB_MISSES.ANY | ITLB miss |
| ITLB_MISSES.WALK_COMPLETED | ITLB miss page walks |
| L1D.M_EVICT | L1D cache lines replaced in M state |
| L1D.M_REPL | L1D cache lines allocated in the M state |
| L1D.M_SNOOP_EVICT | L1D snoop eviction of cache lines in M state |
| L1D.REPL | L1 data cache lines allocated |
| L1D_ALL_REF.ANY | All references to the L1 data cache |
| L1D_ALL_REF.CACHEABLE | L1 data cacheable reads and writes |
| L1D_CACHE_LD.E_STATE | L1 data cache read in E state |
| L1D_CACHE_LD.I_STATE | L1 data cache read in I state (misses) |
| L1D_CACHE_LD.M_STATE | L1 data cache read in M state |
| L1D_CACHE_LD.MESI | L1 data cache reads |
| L1D_CACHE_LD.S_STATE | L1 data cache read in S state |
| L1D_CACHE_LOCK.E_STATE | L1 data cache load locks in E state |
| L1D_CACHE_LOCK.HIT | L1 data cache load lock hits |
| L1D_CACHE_LOCK.M_STATE | L1 data cache load locks in M state |
| L1D_CACHE_LOCK.S_STATE | L1 data cache load locks in S state |
| L1D_CACHE_LOCK_FB_HIT | L1D load lock accepted in fill buffer |
| L1D_CACHE_PREFETCH_LOCK_FB_HIT | L1D prefetch load lock accepted in fill buffer |
| L1D_CACHE_ST.E_STATE | L1 data cache stores in E state |
| L1D_CACHE_ST.M_STATE | L1 data cache stores in M state |
| L1D_CACHE_ST.S_STATE | L1 data cache stores in S state |
| L1D_PREFETCH.MISS | L1D hardware prefetch misses |
| L1D_PREFETCH.REQUESTS | L1D hardware prefetch requests |
| L1D_PREFETCH.TRIGGERS | L1D hardware prefetch requests triggered |
| L1D_WB_L2.E_STATE | L1 writebacks to L2 in E state |
| L1D_WB_L2.I_STATE | L1 writebacks to L2 in I state (misses) |
| L1D_WB_L2.M_STATE | L1 writebacks to L2 in M state |
| L1D_WB_L2.MESI | All L1 writebacks to L2 |
| L1D_WB_L2.S_STATE | L1 writebacks to L2 in S state |
| L1I.CYCLES_STALLED | L1I instruction fetch stall cycles |
| L1I.HITS | L1I instruction fetch hits |
| L1I.MISSES | L1I instruction fetch misses |
| L1I.READS | L1I Instruction fetches |
| L2_DATA_RQSTS.ANY | All L2 data requests |
| L2_DATA_RQSTS.DEMAND.E_STATE | L2 data demand loads in E state |
| L2_DATA_RQSTS.DEMAND.I_STATE | L2 data demand loads in I state (misses) |
| L2_DATA_RQSTS.DEMAND.M_STATE | L2 data demand loads in M state |
| L2_DATA_RQSTS.DEMAND.MESI | L2 data demand requests |
| L2_DATA_RQSTS.DEMAND.S_STATE | L2 data demand loads in S state |
| L2_DATA_RQSTS.PREFETCH.E_STATE | L2 data prefetches in E state |
| L2_DATA_RQSTS.PREFETCH.I_STATE | L2 data prefetches in the I state (misses) |
| L2_DATA_RQSTS.PREFETCH.M_STATE | L2 data prefetches in M state |
| L2_DATA_RQSTS.PREFETCH.MESI | All L2 data prefetches |
| L2_DATA_RQSTS.PREFETCH.S_STATE | L2 data prefetches in the S state |
| L2_LINES_IN.ANY | L2 lines allocated |
| L2_LINES_IN.E_STATE | L2 lines allocated in the E state |
| L2_LINES_IN.S_STATE | L2 lines allocated in the S state |
| L2_LINES_OUT.ANY | L2 lines evicted |
| L2_LINES_OUT.DEMAND_CLEAN | L2 lines evicted by a demand request |
| L2_LINES_OUT.DEMAND_DIRTY | L2 modified lines evicted by a demand request |
| L2_LINES_OUT.PREFETCH_CLEAN | L2 lines evicted by a prefetch request |
| L2_LINES_OUT.PREFETCH_DIRTY | L2 modified lines evicted by a prefetch request |
| L2_RQSTS.IFETCH_HIT | L2 instruction fetch hits |
| L2_RQSTS.IFETCH_MISS | L2 instruction fetch misses |
| L2_RQSTS.IFETCHES | L2 instruction fetches |
| L2_RQSTS.LD_HIT | L2 load hits |
| L2_RQSTS.LD_MISS | L2 load misses |
| L2_RQSTS.LOADS | L2 requests |
| L2_RQSTS.MISS | All L2 misses |
| L2_RQSTS.PREFETCH_HIT | L2 prefetch hits |
| L2_RQSTS.PREFETCH_MISS | L2 prefetch misses |
| L2_RQSTS.PREFETCHES | All L2 prefetches |
| L2_RQSTS.REFERENCES | All L2 requests |
| L2_RQSTS.RFO_HIT | L2 RFO hits |
| L2_RQSTS.RFO_MISS | L2 RFO misses |
| L2_RQSTS.RFOS | L2 RFO requests |
| L2_TRANSACTIONS.ANY | All L2 transactions |
| L2_TRANSACTIONS.FILL | L2 fill transactions |
| L2_TRANSACTIONS.IFETCH | L2 instruction fetch transactions |
| L2_TRANSACTIONS.L1D_WB | L1D writeback to L2 transactions |
| L2_TRANSACTIONS.LOAD | L2 Load transactions |
| L2_TRANSACTIONS.PREFETCH | L2 prefetch transactions |
| L2_TRANSACTIONS.RFO | L2 RFO transactions |
| L2_TRANSACTIONS.WB | L2 writeback to LLC transactions |
| L2_WRITE.LOCK.E_STATE | L2 demand lock RFOs in E state |
| L2_WRITE.LOCK.HIT | All demand L2 lock RFOs that hit the cache |
| L2_WRITE.LOCK.I_STATE | L2 demand lock RFOs in I state (misses) |
| L2_WRITE.LOCK.M_STATE | L2 demand lock RFOs in M state |
| L2_WRITE.LOCK.MESI | All demand L2 lock RFOs |
| L2_WRITE.LOCK.S_STATE | L2 demand lock RFOs in S state |
| L2_WRITE.RFO.HIT | All L2 demand store RFOs that hit the cache |
| L2_WRITE.RFO.I_STATE | L2 demand store RFOs in I state (misses) |
| L2_WRITE.RFO.M_STATE | L2 demand store RFOs in M state |
| L2_WRITE.RFO.MESI | All L2 demand store RFOs |
| L2_WRITE.RFO.S_STATE | L2 demand store RFOs in S state |
| LARGE_ITLB.HIT | Large ITLB hit |
| LOAD_DISPATCH.ANY | All loads dispatched |
| LOAD_DISPATCH.MOB | Loads dispatched from the MOB |
| LOAD_DISPATCH.RS | Loads dispatched that bypass the MOB |
| LOAD_DISPATCH.RS_DELAYED | Loads dispatched from stage 305 |
| LOAD_HIT_PRE | Load operations conflicting with software prefetches |
| LONGEST_LAT_CACHE.MISS | Longest latency cache miss |
| LONGEST_LAT_CACHE.REFERENCE | Longest latency cache reference |
| LSD.ACTIVE | Cycles when uops were delivered by the LSD |
| LSD.INACTIVE | Cycles no uops were delivered by the LSD |
| LSD_OVERFLOW | Loops that can't stream from the instruction queue |
| MACHINE_CLEARS.CYCLES | Cycles machine clear asserted |
| MACHINE_CLEARS.MEM_ORDER | Execution pipeline restart due to Memory ordering conflicts |
| MACHINE_CLEARS.SMC | Self-Modifying Code detected |
| MACRO_INSTS.DECODED | Instructions decoded |
| MACRO_INSTS.FUSIONS_DECODED | Macro-fused instructions decoded |
| MEM_INST_RETIRED.LOADS | Instructions retired which contains a load (Precise Event) |
| MEM_INST_RETIRED.STORES | Instructions retired which contains a store (Precise Event) |
| MEM_LOAD_RETIRED.DTLB_MISS | Retired loads that miss the DTLB (Precise Event) |
| MEM_LOAD_RETIRED.HIT_LFB | Retired loads that miss L1D and hit an previously allocated LFB (Precise Event) |
| MEM_LOAD_RETIRED.L1D_HIT | Retired loads that hit the L1 data cache (Precise Event) |
| MEM_LOAD_RETIRED.L2_HIT | Retired loads that hit the L2 cache (Precise Event) |
| MEM_LOAD_RETIRED.LLC_MISS | Retired loads that miss the LLC cache (Precise Event) |
| MEM_LOAD_RETIRED.LLC_UNSHARED_HIT | Retired loads that hit valid versions in the LLC cache (Precise Event) |
| MEM_LOAD_RETIRED.OTHER_CORE_L2_HIT_HITM | Retired loads that hit sibling core's L2 in modified or unmodified states (Precise Event) |
| MEM_STORE_RETIRED.DTLB_MISS | Retired stores that miss the DTLB (Precise Event) |
| OFFCORE_REQUESTS.L1D_WRITEBACK | Offcore L1 data cache writebacks |
| OFFCORE_REQUESTS_SQ_FULL | Offcore requests blocked due to Super Queue full |
| PARTIAL_ADDRESS_ALIAS | False dependencies due to partial address aliasing |
| RAT_STALLS.ANY | All RAT stall cycles |
| RAT_STALLS.FLAGS | Flag stall cycles |
| RAT_STALLS.REGISTERS | Partial register stall cycles |
| RAT_STALLS.ROB_READ_PORT | ROB read port stalls cycles |
| RAT_STALLS.SCOREBOARD | Scoreboard stall cycles |
| RESOURCE_STALLS.ANY | Resource related stall cycles |
| RESOURCE_STALLS.FPCW | FPU control word write stall cycles |
| RESOURCE_STALLS.LOAD | Load buffer stall cycles |
| RESOURCE_STALLS.MXCSR | MXCSR rename stall cycles |
| RESOURCE_STALLS.OTHER | Other Resource related stall cycles |
| RESOURCE_STALLS.ROB_FULL | ROB full stall cycles |
| RESOURCE_STALLS.RS_FULL | Reservation Station full stall cycles |
| RESOURCE_STALLS.STORE | Store buffer stall cycles |
| SB_DRAIN.ANY | All Store buffer stall cycles |
| SEG_RENAME_STALLS | Segment rename stall cycles |
| SIMD_INT_128.PACK | 128 bit SIMD integer pack operations |
| SIMD_INT_128.PACKED_ARITH | 128 bit SIMD integer arithmetic operations |
| SIMD_INT_128.PACKED_LOGICAL | 128 bit SIMD integer logical operations |
| SIMD_INT_128.PACKED_MPY | 128 bit SIMD integer multiply operations |
| SIMD_INT_128.PACKED_SHIFT | 128 bit SIMD integer shift operations |
| SIMD_INT_128.SHUFFLE_MOVE | 128 bit SIMD integer shuffle/move operations |
| SIMD_INT_128.UNPACK | 128 bit SIMD integer unpack operations |
| SIMD_INT_64.PACK | SIMD integer 64 bit pack operations |
| SIMD_INT_64.PACKED_ARITH | SIMD integer 64 bit arithmetic operations |
| SIMD_INT_64.PACKED_LOGICAL | SIMD integer 64 bit logical operations |
| SIMD_INT_64.PACKED_MPY | SIMD integer 64 bit packed multiply operations |
| SIMD_INT_64.PACKED_SHIFT | SIMD integer 64 bit shift operations |
| SIMD_INT_64.SHUFFLE_MOVE | SIMD integer 64 bit shuffle/move operations |
| SIMD_INT_64.UNPACK | SIMD integer 64 bit unpack operations |
| SNOOP_RESPONSE.HIT | Thread responded HIT to snoop |
| SNOOP_RESPONSE.HITE | Thread responded HITE to snoop |
| SNOOP_RESPONSE.HITM | Thread responded HITM to snoop |
| SQ_FULL_STALL_CYCLES | Super Queue full stall cycles |
| SQ_MISC.SPLIT_LOCK | Super Queue lock splits across a cache line |
| SSEX_UOPS_RETIRED.PACKED_DOUBLE | SIMD Packed-Double Uops retired (Precise Event) |
| SSEX_UOPS_RETIRED.PACKED_SINGLE | SIMD Packed-Single Uops retired (Precise Event) |
| SSEX_UOPS_RETIRED.SCALAR_DOUBLE | SIMD Scalar-Double Uops retired (Precise Event) |
| SSEX_UOPS_RETIRED.SCALAR_SINGLE | SIMD Scalar-Single Uops retired (Precise Event) |
| SSEX_UOPS_RETIRED.VECTOR_INTEGER | SIMD Vector Integer Uops retired (Precise Event) |
| STORE_BLOCKS.AT_RET | Loads delayed with at-Retirement block code |
| STORE_BLOCKS.L1D_BLOCK | Cacheable loads delayed with L1D block code |
| TWO_UOP_INSTS_DECODED | Two Uop instructions decoded |
| UOP_UNFUSION | Uop unfusions due to FP exceptions |
| UOPS_DECODED.ESP_FOLDING | Stack pointer instructions decoded |
| UOPS_DECODED.ESP_SYNC | Stack pointer sync operations |
| UOPS_DECODED.MS_CYCLES_ACTIVE | Uops decoded by Microcode Sequencer |
| UOPS_DECODED.STALL_CYCLES | Cycles no Uops are decoded |
| UOPS_EXECUTED.CORE_ACTIVE_CYCLES | Cycles Uops executed on any port (core count) |
| UOPS_EXECUTED.CORE_ACTIVE_CYCLES_NO_PORT5 | Cycles Uops executed on ports 0-4 (core count) |
| UOPS_EXECUTED.CORE_STALL_COUNT | Uops executed on any port (core count) |
| UOPS_EXECUTED.CORE_STALL_COUNT_NO_PORT5 | Uops executed on ports 0-4 (core count) |
| UOPS_EXECUTED.CORE_STALL_CYCLES | Cycles no Uops issued on any port (core count) |
| UOPS_EXECUTED.CORE_STALL_CYCLES_NO_PORT5 | Cycles no Uops issued on ports 0-4 (core count) |
| UOPS_EXECUTED.PORT0 | Uops executed on port 0 |
| UOPS_EXECUTED.PORT015 | Uops issued on ports 0, 1 or 5 |
| UOPS_EXECUTED.PORT015_STALL_CYCLES | Cycles no Uops issued on ports 0, 1 or 5 |
| UOPS_EXECUTED.PORT1 | Uops executed on port 1 |
| UOPS_EXECUTED.PORT2_CORE | Uops executed on port 2 (core count) |
| UOPS_EXECUTED.PORT234_CORE | Uops issued on ports 2, 3 or 4 |
| UOPS_EXECUTED.PORT3_CORE | Uops executed on port 3 (core count) |
| UOPS_EXECUTED.PORT4_CORE | Uops executed on port 4 (core count) |
| UOPS_EXECUTED.PORT5 | Uops executed on port 5 |
| UOPS_ISSUED.ANY | Uops issued |
| UOPS_ISSUED.CORE_STALL_CYCLES | Cycles no Uops were issued on any thread |
| UOPS_ISSUED.CYCLES_ALL_THREADS | Cycles Uops were issued on either thread |
| UOPS_ISSUED.FUSED | Fused Uops issued |
| UOPS_ISSUED.STALL_CYCLES | Cycles no Uops were issued |
| UOPS_RETIRED.ACTIVE_CYCLES | Cycles Uops are being retired |
| UOPS_RETIRED.ANY | Uops retired (Precise Event) |
| UOPS_RETIRED.MACRO_FUSED | Macro-fused Uops retired (Precise Event) |
| UOPS_RETIRED.RETIRE_SLOTS | Retirement slots used (Precise Event) |
| UOPS_RETIRED.STALL_CYCLES | Cycles Uops are not retiring (Precise Event) |
| UOPS_RETIRED.TOTAL_CYCLES | Total cycles using precise uop retired event (Precise Event) |
| BR_INST_RETIRED.ALL_BRANCHES_PS | Retired branch instructions (Precise Event) |
| BR_INST_RETIRED.CONDITIONAL_PS | Retired conditional branch instructions (Precise Event) |
| BR_INST_RETIRED.NEAR_CALL_PS | Retired near call instructions (Precise Event) |
| BR_INST_RETIRED.NEAR_CALL_R3_PS | Retired near call instructions Ring 3 only(Precise Event) |
| BR_MISP_RETIRED.NEAR_CALL_PS | Mispredicted near retired calls (Precise Event) |
| FP_ASSIST.ALL_PS | X87 Floating point assists (Precise Event) |
| FP_ASSIST.INPUT_PS | X87 Floating poiint assists for invalid input value (Precise Event) |
| FP_ASSIST.OUTPUT_PS | X87 Floating point assists for invalid output value (Precise Event) |
| INST_RETIRED.ANY_P_PS | Instructions retired (Programmable counter and Precise Event) |
| INST_RETIRED.MMX_PS | Retired MMX instructions (Precise Event) |
| INST_RETIRED.TOTAL_CYCLES_PS | Total cycles (Precise Event) |
| INST_RETIRED.X87_PS | Retired floating-point operations (Precise Event) |
| ITLB_MISS_RETIRED_PS | Retired instructions that missed the ITLB (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_0 | Memory instructions retired above 0 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_1024 | Memory instructions retired above 1024 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_128 | Memory instructions retired above 128 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16 | Memory instructions retired above 16 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_16384 | Memory instructions retired above 16384 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_2048 | Memory instructions retired above 2048 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_256 | Memory instructions retired above 256 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32 | Memory instructions retired above 32 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_32768 | Memory instructions retired above 32768 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4 | Memory instructions retired above 4 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_4096 | Memory instructions retired above 4096 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_512 | Memory instructions retired above 512 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_64 | Memory instructions retired above 64 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8 | Memory instructions retired above 8 clocks (Precise Event) |
| MEM_INST_RETIRED.LATENCY_ABOVE_THRESHOLD_8192 | Memory instructions retired above 8192 clocks (Precise Event) |
| MEM_INST_RETIRED.LOADS_PS | Instructions retired which contains a load (Precise Event) |
| MEM_INST_RETIRED.STORES_PS | Instructions retired which contains a store (Precise Event) |
| MEM_LOAD_RETIRED.DTLB_MISS_PS | Retired loads that miss the DTLB (Precise Event) |
| MEM_LOAD_RETIRED.HIT_LFB_PS | Retired loads that miss L1D and hit an previously allocated LFB (Precise Event) |
| MEM_LOAD_RETIRED.L1D_HIT_PS | Retired loads that hit the L1 data cache (Precise Event) |
| MEM_LOAD_RETIRED.L2_HIT_PS | Retired loads that hit the L2 cache (Precise Event) |
| MEM_LOAD_RETIRED.LLC_MISS_PS | Retired loads that miss the LLC cache (Precise Event) |
| MEM_LOAD_RETIRED.LLC_UNSHARED_HIT_PS | Retired loads that hit valid versions in the LLC cache (Precise Event) |
| MEM_LOAD_RETIRED.OTHER_CORE_L2_HIT_HITM_PS | Retired loads that hit sibling core's L2 in modified or unmodified states (Precise Event) |
| MEM_STORE_RETIRED.DTLB_MISS_PS | Retired stores that miss the DTLB (Precise Event) |
| SSEX_UOPS_RETIRED.PACKED_DOUBLE_PS | SIMD Packed-Double Uops retired (Precise Event) |
| SSEX_UOPS_RETIRED.PACKED_SINGLE_PS | SIMD Packed-Single Uops retired (Precise Event) |
| SSEX_UOPS_RETIRED.SCALAR_DOUBLE_PS | SIMD Scalar-Double Uops retired (Precise Event) |
| SSEX_UOPS_RETIRED.SCALAR_SINGLE_PS | SIMD Scalar-Single Uops retired (Precise Event) |
| SSEX_UOPS_RETIRED.VECTOR_INTEGER_PS | SIMD Vector Integer Uops retired (Precise Event) |
| UOPS_RETIRED.ACTIVE_CYCLES_PS | Cycles Uops are being retired |
| UOPS_RETIRED.ANY_PS | Uops retired (Precise Event) |
| UOPS_RETIRED.MACRO_FUSED_PS | Macro-fused Uops retired (Precise Event) |
| UOPS_RETIRED.RETIRE_SLOTS_PS | Retirement slots used (Precise Event) |
| UOPS_RETIRED.STALL_CYCLES_PS | Cycles Uops are not retiring (Precise Event) |
| UOPS_RETIRED.TOTAL_CYCLES_PS | Total cycles using precise uop retired event (Precise Event) |
| UNC_M_ZLATENCY_CNT_EN.ALL | TBD |
| UNC_M_ZLATENCY_CNT_EN.SPRWR_BCMD | TBD |
| UNC_M_ZLATENCY_CNT_EN.F2B_BCMD | TBD |
| UNC_M_ZLATENCY_CNT_EN.F2V_BCMD | TBD |
| UNC_M_ZLATENCY_CNT_EN.V2V_BCMD | TBD |
| UNC_M_ZLATENCY_CNT_EN.V2F_BCMD | TBD |
| UNC_M_ZLATENCY_CNT_EN.MRG_BCMD | TBD |
| UNC_M_ZLATENCY_CNT_EN.WR_BCMD | TBD |
| UNC_M_ZLATENCY_CNT_EN.RD_BCMD | TBD |
| UNC_M_LATENCY_CNT_EN | TBD |
| UNC_M_OPNCLS_CNT_EN.OPEN | TBD |
| UNC_M_OPNCLS_CNT_EN.CLOSED | TBD |
| UNC_M_STARVED_CNT_EN | TBD |
| UNC_M_ZFULL_CNT_EN | TBD |
| UNC_M_TT_CNT_EN | TBD |
| UNC_M_SCHED_MODE_CNT_EN.READ_MAJOR | TBD |
| UNC_M_SCHED_MODE_CNT_EN.WRITE_MAJOR | TBD |
| UNC_M_SCHED_MODE_CNT_EN.TRADEOFF | TBD |
| UNC_M_SCHED_MODE_CNT_EN.ADAPTIVE | TBD |
| UNC_M_DSP_FULL_CNT_EN.RDQ_FULL | TBD |
| UNC_M_DSP_FULL_CNT_EN.WRQ_FULL | TBD |
| UNC_M_DSP_FULL_CNT_EN.RDQ_EMPTY | TBD |
| UNC_M_DSP_FULL_CNT_EN.WRQ_EMPTY | TBD |
| UNC_M_ZERO | TBD |
| UNC_M_ADDR_MATCH0 | TBD |
| UNC_M_Z_INFLIGHT_CMD | TBD |
| UNC_M_SCHED_INFLIGHT_CMD | TBD |
| UNC_M_TIME_STAMP_TICK | TBD |
| UNC_M_B_CMD.SPRWR_BCMD | TBD |
| UNC_M_B_CMD.F2B_BCMD | TBD |
| UNC_M_B_CMD.F2V_BCMD | TBD |
| UNC_M_B_CMD.V2V_BCMD | TBD |
| UNC_M_B_CMD.V2F_BCMD | TBD |
| UNC_M_B_CMD.MRG_BCMD | TBD |
| UNC_M_B_CMD.WR_BCMD | TBD |
| UNC_M_B_CMD.RD_BCMD | TBD |
| UNC_M_TT_CMD | TBD |
| UNC_M_FVID_RACE | TBD |
| UNC_M_MULTICAS | TBD |
| UNC_M_OPN2CLS.OPN2CLS | TBD |
| UNC_M_OPN2CLS.CLS2OPN | TBD |
| UNC_M_AUTO_CLS | TBD |
| UNC_M_PAGE_HIT | TBD |
| UNC_M_PAGE_MISS | TBD |
| UNC_M_PAGE_EMPTY | TBD |
| UNC_M_TRANS_CMD | TBD |
| UNC_M_PATROL_TXNS | TBD |
| UNC_M_FVC_EVNT4 | TBD |
| UNC_M_FVC_EVNT3 | TBD |
| UNC_M_FVC_EVNT2 | TBD |
| UNC_M_FVC_EVNT1 | TBD |
| UNC_M_MA_PAR_ERR | TBD |
| UNC_M_RETRY | TBD |
| UNC_M_RETRY.FVID | TBD |
| UNC_M_DRAM_CMD.PREALL_SCMD | TBD |
| UNC_M_DRAM_CMD.RAS_SCMD | TBD |
| UNC_M_DRAM_CMD.CAS_RD_SCMD | TBD |
| UNC_M_DRAM_CMD.CAS_WR_SCMD | TBD |
| UNC_M_DRAM_CMD.CASPRE_RD_SCMD | TBD |
| UNC_M_DRAM_CMD.CASPRE_WR_SCMD | TBD |
| UNC_M_DRAM_CMD.MRS_SCMD | TBD |
| UNC_M_DRAM_CMD.EMRS_SCMD | TBD |
| UNC_M_DRAM_CMD.RFR_SCMD | TBD |
| UNC_M_DRAM_CMD.ENSR_SCMD | TBD |
| UNC_M_DRAM_CMD.EXSR_SCMD | TBD |
| UNC_M_DRAM_CMD.NOP_SCMD | TBD |
| UNC_M_DRAM_CMD.EMRS2_SCMD | TBD |
| UNC_M_DRAM_CMD.EMRS3_SCMD | TBD |
| UNC_M_DRAM_CMD.GENDRM_SCMD | TBD |
| UNC_M_DRAM_CMD.TRKL_SCMD | TBD |
| UNC_M_DRAM_CMD.PRE_SCMD | TBD |
| UNC_M_DRAM_CMD.SYNC_SCMD | TBD |
| UNC_M_DRAM_CMD.POLL_SCMD | TBD |
| UNC_M_DRAM_CMD.CKEH_SCMD | TBD |
| UNC_M_DRAM_CMD.CKEL_SCMD | TBD |
| UNC_M_DRAM_CMD.IBD_SCMD | TBD |
| UNC_M_DRAM_CMD.SFT_RST_SCMD | TBD |
| UNC_M_DRAM_CMD.NOWPE_SCMD | TBD |
| UNC_M_DRAM_CMD.PREALL_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.RAS_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CAS_RD_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CAS_WR_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CASPRE_RD_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CASPRE_WR_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.MRS_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.EMRS_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.RFR_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.ENSR_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.EXSR_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.NOP_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.EMRS2_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.EMRS3_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.GENDRM_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.TRKL_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.PRE_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.SYNC_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.POLL_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CKEH_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CKEL_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.IBD_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.SFT_RST_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.NOWPE_SCMD.READMAJORMODE | TBD |
| UNC_M_DRAM_CMD.PREALL_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.RAS_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CAS_RD_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CAS_WR_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CASPRE_RD_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CASPRE_WR_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.MRS_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.EMRS_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.RFR_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.ENSR_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.EXSR_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.NOP_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.EMRS2_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.EMRS3_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.GENDRM_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.TRKL_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.PRE_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.SYNC_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.POLL_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CKEH_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.CKEL_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.IBD_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.SFT_RST_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.NOWPE_SCMD.WRITEMAJORMODE | TBD |
| UNC_M_DRAM_CMD.PREALL_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.RAS_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.CAS_RD_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.CAS_WR_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.CASPRE_RD_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.CASPRE_WR_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.MRS_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.EMRS_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.RFR_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.ENSR_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.EXSR_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.NOP_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.EMRS2_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.EMRS3_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.GENDRM_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.TRKL_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.PRE_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.SYNC_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.POLL_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.CKEH_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.CKEL_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.IBD_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.SFT_RST_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.NOWPE_SCMD.TRADEOFFMODE | TBD |
| UNC_M_DRAM_CMD.PREALL_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.RAS_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.CAS_RD_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.CAS_WR_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.CASPRE_RD_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.CASPRE_WR_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.MRS_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.EMRS_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.RFR_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.ENSR_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.EXSR_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.NOP_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.EMRS2_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.EMRS3_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.GENDRM_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.TRKL_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.PRE_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.SYNC_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.POLL_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.CKEH_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.CKEL_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.IBD_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.SFT_RST_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_DRAM_CMD.NOWPE_SCMD.ADAPTIVEMODE | TBD |
| UNC_M_FRM_TYPE.1CMD | TBD |
| UNC_M_FRM_TYPE.NOP | TBD |
| UNC_M_FRM_TYPE.CHNL | TBD |
| UNC_M_FRM_TYPE.SYNC | TBD |
| UNC_M_FRM_TYPE.WDAT | TBD |
| UNC_M_FRM_TYPE.3CMD | TBD |
| UNC_M_ISS_SCHED | TBD |
| UNC_M_REFRESH_CONFLICT | TBD |
| UNC_M_REFRESH | TBD |
| UNC_M_TT_TRP_DN | TBD |
| UNC_M_TT_TRP_UP | TBD |
| UNC_M_STARVED_RETRY | TBD |
| UNC_M_ZFULL_RETRY | TBD |
| UNC_M_ZFULL | TBD |
| UNC_M_DSP_FILL.RDQ_FULL | TBD |
| UNC_M_DSP_FILL.WRQ_FULL | TBD |
| UNC_M_DSP_FILL.RDQ_EMPTY | TBD |
| UNC_M_DSP_FILL.WRQ_EMPTY | TBD |
| UNC_R_OUT_NULL_IDLE_EN | Counts Output port sends NULL flit |
| UNC_R_FLT_SENT_EN | Counts Output port sends NULL flit |
| UNC_R_TARGET_AVAILABLE | Times target available at output port |
| UNC_R_INP_RCVD_VN_MSGC_SEL.ANY.DRS | ANY Data Response Messages |
| UNC_W_CLOCKTICKS | uncore clock frequency |


Preface
After spending almost three years as the lead designer of the Corinna object system for the Perl core , I’m delighted that work on including this in the Perl language will start soon. Until it’s there, our company still does a lot of work with clients, fixing their object-oriented code (OOP) and we’ve seen some very common causes of failures. Some say that our recommendations are too strict, and for personal projects, they might be. But we work with large-scale codebases, often written in Perl, and often containing over a million lines of code. When you’re working at that scale, especially when coordinating with many developers who may not know your code well, you need to be more rigorous.
This is not a tutorial on OOP design. That in itself is a complex topic (and perhaps one of the strongest arguments against OOP). So we’ll assume you need to fix an existing OOP codebase rather than design a new one.
Note: while these examples are in Perl, many of these problems apply to codebases we’ve worked on in other OO languages.
Warning: whenever we link to a module on the CPAN, please read the documentation of that module if you decide to use it. There are often caveats, such as with the “strict constructor” modules we mention later.
What’s an Object?
First and foremost, we must keep in mind what an object is. This is covered more in other articles, but for this one, just keep in mind that an object is an expert about a particular topic. Forget all of those other explanations about objects being “structs with behavior”, or “a reference to a data type that knows what class it belongs to.” Those are implementation details that don’t tell you objects are for. In my opinion, they even hinder people’s understanding of objects because they keep you focused on the wrong thing. Objects are experts on a particular problem space, that’s all.
Recommendations
We could talk about SOLID , GRASP , the Liskov substitution principle , the Law of Demeter , and so on, but while those are important, you can read about those on your own. Instead, we’ll cover recommendations and common problems. You’ll need to use your best judgment to decide how (or if) they apply to your codebase.
Note: if this article makes your eyes glaze over, but you love the Moose OOP system, you might skip ahead to Dr. Frankenstein to see a small module built on top of Moose that implements some of the recommendations in this article.
Immutable Objects
I’ve written before why immutable objects are good, so I won’t go into too much detail. Sometimes it’s not practical to have immutable objects (e.g., caches), but immutability should be your default position. In most languages, objects are passed by reference, not value. The more widely used an instance of your object is, if it’s mutable, the more likely that code “A” will change the state in a way that code “B” didn’t expect.
Recommendation
Even if you’re not convinced, try writing and using immutable objects. Like anything new, it can take some getting used to, but there’s a payoff there. Just don’t insist that everything be immutable.
Note that if your object must return references to data, those are often mutable. However, you can declare those as immutable, too.
package Some::Class {
use Const::Fast 'const';
# set up data here
sub get_data_structure {
my $self = shift;
const my %hash => (
name => $self->name,
giggity => $self->_something_else,
);
return \%hash;
}
}
In the above, the get_data_structure
method returns an immutable data
structure. Attempts to access unknown hash keys or change any of the values is a
fatal error (use exists
to test hash keys, of course). Some people call it
overkill. Others call it safety. Your mileage may vary.
If you prefer, you can deeply clone the data structure before returning it. By presenting a copy, different consumers calling that method will always have the same results, but if the returned reference itself is shared, you could have issues. That being said, this is an issue with all code, not just OOP.
Small Interfaces and Encapsulation
The interface that your class presents is your “contract” with everyone who uses your class. You should design that interface with care, but you shouldn’t expose what you don’t need to. Using one of my “go to” examples of the Corinna OOP system that will be available in upcoming releases (but not in the immediate future), here’s a basic LRU (least recently used) cache:
class Cache::LRU {
use Hash::Ordered;
field $cache :handles(exists) { Hash::Ordered->new };
field $max_size :param :reader { 20 };
method set ( $key, $value ) {
if ( $cache->exists($key) ) {
$cache->delete($key);
}
elsif ( $cache->keys >= $max_size ) {
$cache->shift;
}
$cache->set( $key, $value ); # add to front
}
method get ($key) {
if ( $cache->exists($key) ) {
my $value = $cache->get($key);
$self->set( $key, $value ); # add to front
return $value;
}
return;
}
}
With the popular Moose OOP system for Perl, that would look something like this (skipping the sub bodies):
package Cache::LRU {
use Moose;
use Hash::Ordered;
use namespace::autoclean;
has '_cache' => (
is => 'ro',
init_arg => undef,
default => sub { Hash::Ordered->new },
);
has 'max_size' => ( is => 'ro', default => 20 );
sub set {
...
}
sub get {
...
}
__PACKAGE__->meta->make_immutable;
}
For raw Perl, it might even look like this:
package Cache::LRU;
use strict;
use warnings;
use Hash::Ordered;
sub new {
my ( $class, $max_size ) = @_;
$max_size //= 20;
return bless {
max_size => $max_size,
_cache => Hash::Ordered->new,
}, $class;
}
# more code here
For both Moose and core Perl, it’s hard to encapsulate your objects and minimize
your interface. For both of those, you can call $object->{_cache}
to get the
underlying cache. For Moose, you can also call $object->_cache
(it’s very
cumbersome in Moose or Moo to not expose methods for what should be private
data). This means that you have exposed that data, no matter how nicely you’ve
asked people to “stay out of the kitchen.” This means that if someone is
accessing your “private” data, if you want to switch your internal cache to use
Redis, SQLite, or something else, you can easily break the code of others who
are relying on it.
We almost always see $object->_private_method
or $object->{private_data}
in
client codebases and that’s one of the first things we try to fix, if we have
time. As a class author, you need to know you can safely change the internals of
your object.
Recommendation
Keep your classes as small as you can and stop making accessors public by
default. For now, this means prefixing methods with an underscore to make them
“private by convention.” With Corinna, you simply don’t provide :reader
or
:writer
attributes:
class Cache::LRU {
use Hash::Ordered;
field $cache { Hash::Ordered->new };
field $max_size :param :reader { 20 };
...
In the above, you can read (but not write) the max size, but there’s no direct
access possible to the $cache
(this will be possible via the MOP, the
meta-object protocol, but we do not want violating encapsulation to be a natural
default. Hitting the MOP to violate encapsulation will stand out like a coal
pile in a ballroom in code reviews).
Note: some Perl developers use “inside-out” objects to enforce encapsulation. The CPAN has Object::InsideOut and Class::InsideOut , amongst others. While it’s easy to use instances of these classes, they were cumbersome to write and sometimes buggy. As a result, we do not experience them often in client code.
Type Library
As systems grow, it’s very easy to have this problem:
sub get_part_by_id ($self, $id) {
return $self->_inventory_schema->resultset('Part')->find($id);
}
Most of the time that works, but sometimes you get no result. What happened? Maybe your primary key is a UUID but you’ve supplied an integer? Oops. So now you have to rewrite that:
sub get_part_by_id ($self, $id) {
unless ( $id =~ qr/^[0-9a-f]{8}(?:-[0-9a-f]{4}){2}-[0-9a-f]{12}$/is ) {
croak("ID ($id) does not look like a UUID.");
}
return $self->_inventory_schema->resultset('Part')->find($id);
}
Do you really want to write that? Do you really want to debug that? (there’s a small bug in that example, if you care to look for it). If you use UUIDs frequently, you don’t want to write that again.
If you’ve used Moose, you know how easy it is to use type constraints:
has 'order_items' => (
is => 'ro',
isa => 'ArrayRef[HashRef]',
writer => '_set_order_items',
);
Of course, if you spell the isa
as ArrayRef[HasRef]
, you won’t find out
until runtime that you’ve misspelled it. For these and other situations, just
create a type library as a centralized place to put your types and share them
across your codebase as needed. If there’s too much code, focus on critical
paths first.
Recommendation
Creating a type library for the first time can be daunting. Here’s a simple one, based on the excellent Type::Tiny by Toby Inkster. It will cover most of your basic needs and you can extend it later with custom types, if needed.
package My::Personal::Types;
use strict;
use warnings;
use Type::Library -base;
use Type::Utils -all;
use Type::Params; # this gets us compile and compile_named
our @EXPORT_OK;
BEGIN {
# this gets us most of our types
extends qw(
Types::Standard
Types::Common::Numeric
Types::Common::String
Types::UUID
);
push @EXPORT_OK => (
'compile',
'compile_named',
);
}
1;
Using it is simple.
use My::Personal::Types qw(compile UUID);
sub get_part_by_id ($self, $id) {
state $check = compile(UUID);
($id) = $check->($id);
return $self->_inventory_schema->resultset('Part')->find($id);
}
In Moose, use these constraints to turn misspelled types into compile-time failures (and to get a much richer set of allowed types):
use My::Personal::Types qw(ArrayRef HashRef);
has 'order_items' => (
is => 'ro',
isa => ArrayRef [HashRef],
writer => '_set_order_items',
);
Despite the Type::Tiny
name, the manual is quite
extensive .
Go there for more information.
Subclassing
A subclass of a class is intended to be a more specialized version of that
class. A Car isa Vehicle
, or a Human isa Mammal
. However, it’s easy to get
this wrong under the pressure of deadlines, complex code bases, or just plain
not paying attention. Is Item isa Product
correct? Or is Product isa Item
more correct?
Ultimately, the problem manifests itself in what I call the “person/invoice
problem”: Person isa Invoice
. That makes absolutely no sense, but your
software doesn’t know that. Your software only does what you tell it to do. It
can’t evaluate semantics (at least, not yet), and if you write code that runs,
but doesn’t make sense, that’s too bad.
In fact, inheritance is so problematic that some OOP languages disallow it altogether, favoring composition instead. Some only allow single inheritance, but provide alternatives (mixins, interfaces, traits, etc.). As a general rule, we recommend you use roles instead of parent classes:
- Role::Tiny (for any OO code)
- Moose::Role (for Moose)
- Moo::Role (for Moo)
There’s also my own Role::Basic which
can be used where Role::Tiny
is appropriate, but the philosophy of that
module is
different
and presents somewhat different features.
Sometimes inheritance is the right thing to do. For example, in the
Test::Class::Moose xUnit
framework, we have “test control methods” which run code before the class is
instantiated, before each method is run, after each method is run, and after the
test class has finished running. A test_setup
method might look like this:
sub test_setup {
my $test = shift;
$test->next::method;
$test->load_fixtures(qw/Customer Orders/);
}
In the above example, the $test->next::method
is used to call the parent
test_setup
to ensure that all setup is ready before you try to handle this
class’s setup. In fact, you might have your test_setup
call a parent
test_setup
which in turns calls its parent test_setup
. This is common in
xUnit testing and the order in which events fire is important. With roles, this
is often done with method modifiers, but the order in which they fire is often
dependent on their load order and that is not guaranteed. If you find yourself
frequently using method modifiers in roles, you might want to think about
inheritance to ensure that you have complete control over the sequencing of
commands.
Recommendation
We should prefer composition or roles over inheritance. Composition is good when you clearly have an object to delegate to. Roles are good when you have some behavior which might apply to unrelated classes (such as serialization to JSON or XML).
There’s much more we could say about roles, but a full tutorial is beyond the scope of this article.
Performance
Don’t stress about performance, really. It’s not the code. It’s the database. It’s always the database. Unless it’s the network. Or it’s disk I/O. Or, or, or ...
Steve McConnell, in his fantastic book Code Complete, 2nd edition, writes:
It’s almost impossible to identify performance bottlenecks before a program is working completely. Programmers are very bad at guessing which four percent of the code accounts for 50 percent of the execution time, and so programmers who optimize as they go will, on average, spend 96 percent of their time optimizing code that doesn’t need to be optimized. That leaves little time to optimize the four percent that really counts.
Unless you know, at design time, you’ll have performance critical code (don’t write ray-tracing software in Perl, folks!), design a great system and worry about performance only when it’s proven to be an actual problem. Devel::NYTProf is your friend here. Be aware that benchmarking can be an arcane art.
But when we talk about performance, whose performance are we talking about? The software or the software developer? Here’s a little benchmark for you:
#!/usr/bin/env perl
use strict;
use warnings;
use Benchmark 'cmpthese';
sub use_a_loop {
my @numbers;
foreach my $i ( 0 .. 9 ) {
$numbers[$i] = $i / ( $i + 1 );
}
return \@numbers;
}
sub direct_assignment {
my @numbers;
$numbers[0] = 0 / 1;
$numbers[1] = 1 / 2;
$numbers[2] = 2 / 3;
$numbers[3] = 3 / 4;
$numbers[4] = 4 / 5;
$numbers[5] = 5 / 6;
$numbers[6] = 6 / 7;
$numbers[7] = 7 / 8;
$numbers[8] = 8 / 9;
$numbers[9] = 9 / 10;
return \@numbers;
}
cmpthese(
1_000_000,
{
'use_a_loop' => \&use_a_loop,
'direct_assignment' => \&direct_assignment,
}
);
Do you think the loop or the direct assignment is faster? Do you really care? Well, it should be pretty clear that the loop is much easier to maintain. The direct assignment, however ...
Rate use_a_loop direct_assignment
use_a_loop 970874/s -- -50%
direct_assignment 1923077/s 98% --
Whoa! Directly assigning the data is twice as fast as the loop! If something like that is at the bottom of a tight loop and benchmarking shows that it’s a performance issue, then yes, switching from a loop to direct assignment might be an idea, but that would kill developer performance when it comes to maintaining that code. If you must do that, document it carefully, perhaps including a snippet of the code that this replaces.
Recommendation
Design the system well and don’t worry about performance while building it. Doing so runs the risk of optimizing code that doesn’t need to be optimized and possibly makes the code harder to maintain, raising long-term costs.
Instead, if your code is suffering performance issues, benchmark your code and find out where the real problems are. Here’s a video of Tim Bunce explaining how to profile your code:
Problems
The above were general recommendations for OO code, but now let’s talk about common problems we encounter with our clients.
Too Many Responsibilities
For our Project 500 contract, our client was providing online credit card services for a major, well-publicized event. However, they had a serious problem: their code could only handle 39 credit card transactions per second per server. For this event, they had a contractual obligation to improve performance by an order of magnitude. That’s right; they were required to have their code run at least ten times faster. We had two weeks to develop a proof of concept (spoiler: we succeeded).
In digging in, it turns out that they had developed an in-house OO system and an in-house ORM. We quickly discovered that a single “charge $x to the credit card” transaction generated almost 200 calls to the database! This was one of their major bottlenecks.
For our client’s ORM, every time a request was made it would gather a bunch of metadata, check permissions, make decisions based on whether or not it was using Oracle or PostgreSQL, check to see if the data was cached, and then check to see if the data was in the database. Instantiating every object was very slow, even if there was no data available. And the code was creating—and throwing away without using—hundreds of these objects per request.
We considered using a “pre-flight” check to see if the data was in the database before creating the objects, but there was so much business logic embedded in the ORM layer that this was not a practical solution given our time constrain. And we couldn’t simply fetch the data directly because, again, the ORM had too many non-ORM responsibilities built into it.
On another system, we had an immutable object (yay!) that had disk I/O and heavy data validation every time it was instantiated. Yet that data never changed between releases, so I was tasked with caching the object data. I restructured to class to separate the validation of instance data and the setting of instance data. Then I added a few lines of code to the class to handle this and it worked like a charm, but my tests missed an edge case where some data wasn’t cached properly because one bit of data was set during validation. I had made the classic mistake of putting too much logic in that class.
To address this, I built a simple class to properly cache objects on web server restart and it cached the object for me. Not only did it work right this time, I now had a flexible in-memory cache for other objects. Further, because the cache internals were encapsulated, if we want to switch the cache out for Redis or something else, it becomes trivial. .
Recommendation
Don’t have your objects try to do too much. The “single-responsibility” principle generally means there should only be a single reason to change a class. In the real-world, this is easy to miss, but it will save you much grief if you get this right.
Use Methods for Attribute Data
In old-school OOP code for Perl, you might see something like this:
package Customer;
use strict;
use warnings;
use Carp 'croak';
sub new {
my ( $class, $name, $title ) = @_;
croak("Name required") unless defined $name;
return bless {
name => $name,
title => $title,
}, $class;
}
sub name { $_[0]->{name} }
sub title { $_[0]->{title} }
# more code here
1;
So far, so good. But the business rules state that if the customer has a title, they must always be referred to by both their title and name, never just one or the other. Developers keep forgetting (or don’t know) this business rule, but remember: your object is supposed to be the expert here and it won’t get it wrong, so the object should handle this responsibility.
Now you’re rewritten the class to remover the title
accessor and to provide a
name
method to encapsulate this logic:
package Customer;
use strict;
use warnings;
use Carp 'croak';
sub new {
my ( $class, $name, $title ) = @_;
croak("Name required") unless defined $name;
return bless {
name => $name,
title => $title,
}, $class;
}
# always prefix their name with a title if it exists
sub name {
my $self = shift;
return $self->{title}
? "$self->{title} $self->{name}"
: $self->{name};
}
# more code here
1;
Again, this code looks correct, but by eliminating the accessor for our title
attribute, if we were forced to subclass this, how do we override it, especially
if it’s used elsewhere in the class? We could just overwrite the name
and
title
values in the blessed hash of the subclass and that might be good
enough, but if we need to convert an attribute to a method—as we did with name
we can’t easily do that now.
Recommendation
This is one of the advantages of Moose and Moo. You automatically get method
accessors for data attributes, so users of those OO systems will rarely notice
this unless they also get in the bad habit of doing $self->{title}
.
Otherwise, if you’re writing core Perl, just include simple accessors/mutators for your data (prefacing them with a leading underscore if they should be private):
sub title ($self) {
return $self->{title};
}
sub set_title ($self, $title) {
$self->{title} = $title;
}
Whether you prefer to overload a method to be both an accessor and a mutator, or to return the invocant on mutation are arguments that are far beyond the scope of this article, so we would recommend following the current style of your codebase. If it doesn’t exist, define it and stick to it (predictable interfaces are fantastic!).
Confusing Subroutines and Methods
Your Moose/Moo classes should generally resemble the following:
package Some::Class {
use Moose;
use namespace::autoclean;
# class definition here
# make_immutable is a significant performance boost
__PACKAGE__->meta->make_immutable;
}
I was writing some client software that could cache some objects (it’s a
coincidence that I’ve had to do this so often) and for one edge case,
it was good if we could clone the objects first. Many things cannot be easily
cloned, so if the object provides its own clone
method, we used that instead
of simply returning the object from the cache. It looked sort of like this:
sub fetch ( $class, %arg_for ) {
my $object = $class->_fetch_for_identifier(
$arg_for{identifier}
);
if ($object) {
return $object->can('clone')
? $object->clone
: $object;
}
else {
return $class->_instantiate_and_cache($arg_for);
}
}
That failed miserably because some objects were importing a clone
subroutine
and because Perl doesn’t have a distinction because subroutines and methods
(though it will when Corinna is implemented), clone
was in the
namespace and the can('clone')
method returned true. We tried to call a
subroutine as a method, even though it wasn’t.
Recommendation
Using namespace::autoclean or namespace::clean will remove the imported subroutines from the namespace and make it much harder for code to call subroutines as methods. Read the documentation for each to decide which will work better for you.
Note that as of this writing, there is an outstanding RFC for Perl to allow a lexical importing mechanism which should make this less of a problem in the future if it’s adopted.
Inconsistent Return Types
This isn’t just an OOP problem, but it’s a common issue we see in code in dynamic languages, so it’s worth mentioning here. If you’re going to return an array reference or a hash reference, you usually want to ensure that’s all you return. For example:
my $results = $object->get_results;
if ($results) {
foreach my $result ($result->@*) {
# do something
}
}
But what if you forget the if
?
my $results = $object->get_results;
foreach my $result ($result->@*) {
# do something
}
If get_results
returns undef
when there are no results, the code blows up.
However, if it returns an empty array reference, the loop is simply skipped.
You don’t have to remember to check the return value type (unless returning
nothing is an actual error). This is easy to fix in methods, but be wary of a
similar trap with attributes:
has 'results' => (
is => 'ro',
isa => Maybe[ ArrayRef ],
);
Recommendation
There are several ways to handle this, including defining coerced types, but one of the simplest and safest:
has 'results' => (
is => 'ro',
isa => ArrayRef,
default => sub { [] },
);
In the above, we drop the Maybe
and default to an array reference if no
argument is supplied to the constructor. With that, if they pass an arrayref of
hashrefs for results
, it works. If they don’t pass results
at all, it
still works.
However, if they pass anything else for results
, including undef
, it fails.
That’s great safety because while you want the types you return to be
predictable, it’s also good to allow the types you pass in to be predictable.
There are definitely exceptions to this, but they should be used with care.
Ignored Constructor Arguments
Going back to our results
example:
package Some::Class;
use Moose;
has 'results' => (
is => 'ro',
isa => ArrayRef,
default => sub { [] },
);
What happens if we do my $object = Some::Class->new( result => $result );
.
No matter what the type of $result
is, the value is thrown away because by
default, Moose and Moo simply discard unknown arguments to the constructor. If
you misspell a constructor argument, this can be a frustrating source of errors.
Recommendation
Fortunately, the fix for this is simple, too:
MooseX::StrictConstructor .
(Or MooX::StrictConstructor
for Moo):
package Some::Class;
use Moose;
use MooseX::StrictConstructor;
has 'results' => (
is => 'ro',
isa => ArrayRef,
default => sub { [] },
);
Now, passing unknown arguments is a fatal error.
If you’re using traditional bless
syntax, you’ll have to manually validate the
arguments to the constructor yourself, but the type library we outlined above
can be used.
Leftovers
There’s a huge amount more we can say, including useful design patters, being cautious with method modifiers in roles, when to use abstract classes instead of roles, but we’re starting to get into the long tail of code smells in object-oriented code bases, so perhaps those are good for another article.
Dr. Frankenstein
If you’ve gotten this far, congrats! One thing very helpful with OO code is to develop a set of guidelines on how you’ll build OO code and stick to it. We’re going to be Dr. Frankenstein and build our own object system out of the parts we have laying around. By ensuring everyone uses this object system, we can have greater consistency in our code.
Let’s pretend you’ve settled on the Moose OOP system as the basis of your own. You’d like to ensure several things are true and you’ve come up with the following list:
- Unknown arguments to the constructor are fatal
- It should be easy to see which attributes are or are not required in the constructor
- Attributes should default to read-only
namespace::autoclean
must always be used- You want signatures and types
- The
Carp
module’scarp
,croak
, andconfess
functions should always be present - You want the C3 MRO (though you should avoid multiple inheritance)
- Your work uses v5.22, so you’ll enforce those features
For this, you’ve decided that param
should replace has
if the parameter is
required in the constructor, and field
should replace has
if the parameter
is not allowed in the constructor. Let’s use
Moose::Exporter to set this up.
We won’t explain how all of this works, so you have some homework to do.
Again, we’re not saying the above is what you should do; we’re just giving an example of what you can do.
package My::Personal::Moose;
use v5.22.0;
use Moose ();
use MooseX::StrictConstructor ();
use Moose::Exporter;
use mro ();
use feature ();
use namespace::autoclean ();
use Import::Into;
use Carp qw/carp croak confess/;
Moose::Exporter->setup_import_methods(
with_meta => [ 'field', 'param' ],
as_is => [ \&carp, \&croak, \&confess ],
also => ['Moose'],
);
sub init_meta {
my ( $class, @args ) = @_;
my %params = @args;
my $for_class = $params{for_class};
Moose->init_meta(@args);
MooseX::StrictConstructor->import( { into => $for_class } );
warnings->unimport('experimental::signatures');
feature->import(qw/signatures :5.22/);
namespace::autoclean->import::into($for_class);
# If we never use multiple inheritance, this should not be needed.
mro::set_mro( scalar caller(), 'c3' );
}
sub field {
my ( $meta, $name, %opts ) = @_;
# default to read-only
$opts{is} //= 'ro';
# "has [@attributes]" versus "has $attribute"
foreach my $attr ( 'ARRAY' eq ref $name ? @$name : $name ) {
my %options = %opts; # copy each time to avoid overwriting
# forbid setting `field` in the constructor
$options{init_arg} = undef;
$meta->add_attribute( $attr, %options );
}
}
sub param {
my ( $meta, $name, %opts ) = @_;
# default to read-only
$opts{is} //= 'ro';
# it's required unless they tell us otherwise
$opts{required} //= 1;
# "has [@attributes]" versus "has $attribute"
foreach my $attr ( 'ARRAY' eq ref $name ? @$name : $name ) {
my %options = %opts; # copy each time to avoid overwriting
if ( exists $options{init_arg} && !defined $options{init_arg} ) {
croak("You may not set init_arg to undef for 'param'");
}
$meta->add_attribute( $attr, %options );
}
}
1;
With that, and the My::Personal::Types
above, here’s a (silly) example of how
to use this:
#!/usr/bin/env perl
use lib 'lib';
use Test::Most;
package My::Names {
use My::Personal::Moose;
use My::Personal::Types qw(
compile
Num
NonEmptyStr
Str
PositiveInt
ArrayRef
);
use List::Util 'sum'; # removed my namespace::autoclean
param _name => ( isa => NonEmptyStr, init_arg => 'name' );
param title => ( isa => Str, required => 0 );
field created => ( isa => PositiveInt, default => sub { time } );
sub name ($self) {
my $title = $self->title;
my $name = $self->_name;
return $title ? "$title $name" : $name;
}
sub add ( $self, $args ) {
state $check = compile( ArrayRef [Num] );
($args) = $check->($args);
carp("no numbers supplied to add()") unless $args->@*;
return sum( $args->@* );
}
__PACKAGE__->meta->make_immutable;
}
my $person = My::Names->new( name => 'Ovid', );
is $person->name, 'Ovid', 'name should be correct';
ok !defined $person->title, '... and no title';
cmp_ok $person->created, '>', 0, '... and a sane default for created';
ok !$person->can('sum'), 'subroutines have been removed from the namespace';
is $person->add( [qw/1 3 5 6/] ), 15, 'Our add() method should work';
throws_ok { My::Names->new( name => 'Ovid', created => 1 ) }
'Moose::Exception',
'Attributes not defined as `param` are illegal in the constructor';
my $doctor = My::Names->new( name => 'Smith', title => 'Dr.' );
is $doctor->name, 'Dr. Smith', 'Titles should show up correctly';
cmp_ok $doctor->created, '>=', $person->created,
'... and their created date should be correct';
done_testing;
Obviously, the above code probably won’t be fit for purpose, but it shows you the basics of how you can build an OO system to fit your company’s needs, rather than allowing everyone to just “do their own thing.”
Hire Us
We do code reviews, development, testing, and design, focused on reliability and scalability. Even if you’re just exploring possibilities, feel free to contact us and let’s see what we can do to make your software better.


A recent CIR that was filled out by {staff_name} regarding client {client_primary} was assessed to be of {risk_assessment} risk. The incident occured on {time_of_incident} and was recorded at {time_of_report_completion}. The score was calculated from the following raw risk scores:


The following outlines an EPICS V4 URI syntax. The syntax includes support for requests for Channel values subject to arguments (as implemented by ChannelRPC). The URI syntax is then used to define a new Normative Type, NTURI, that encodes the same information as the EPICS V4 URI. In this way, the service API is defined as a case of the EPICS V4 API, and both by reference to the IETF standard for accessing resources. Example EPICS V4 URIs are given, and example Java source for constructing an NTURI.
This is a proposal document for a feature addition to a normative work of the EPICS V4 working group.
This is the 1st draft of this proposal.
The terms MUST, MUST NOT, SHOULD, SHOULD NOT, REQUIRED, and MAY when highlighted (through style sheets, and in uppercase in the source) are used in accordance with RFC 2119 [RFC2119]. The term NOT REQUIRED (not defined in RFC 2119) indicates exemption.
As we've known for a year, we need a standard for the API of EPICS V4 services.
With that, Matej and Anton can write general purpose clients, since they'll know how to express a, possibly parameterized, request for data from a PV. I'd like to have a clear association of the resource identification standard URI (IETF RFC 2396) [1] to how EPICS V4 identifies acquirable data in an EPICS network.
That is, when we ask an EPICS V4 agent for data, it should be that what you ask (the PV name and associated parameters) should map to URI semantics (see note 1).
A URI for EPICS V4 should encompasses all channels types, not just RPC channels. Also, by "EPICS V4" I mean to include EPICS V3. The URI standard [1], allows latitude to define a URI's semantics according to the scheme (the part before the "://".
Therefore, below I propose a pvaccess schema URI mapping. Then, given the mapping, describe a new normative type "NTURI" that encodes such a URI.
Additionally, I include a CA schema for illustration, but just for the basics of getting a PV value by name. Gurus invited to make that better.
Looking at the IETF standard (TBL's from 1998!) section 3 gives the syntactic components. The mapping to EPICS V4 RPC agent requests seems uncomplicated. But it does mean we have to agree on where in the syntax to put EPICS V4 channel request parts. Also the scope of the "authority" and "path" parts probably need a normative decision with respect to EPICS V3. Note that there is some latitude in [1], "The URI syntax does not require that the scheme-specific-part have any general structure or set of semantics which is common among all URI."
Generic URI Syntax for representing hierarchical relations [1, part 3]:
<scheme>://<authority>[<path>][?<query>]
In conformance with [1], the path part and query part of an EPICS URI are optional. Proposed Part Assignment for EPICS URI
Proposed URI part semantics for EPICS:
scheme = {pva|ca} authority = Channel name. So the authority MUST be given. The channel may or may not be an RPC channel path = Entity required from RPC channel. If path is given then the authority part MUST give a ChannelRPC channel name query = Arguments to an RPC channel, such as the starttime of an archive data request.
When pvdata request [2] syntax is clarified, the query may also be used to encode the pvData request string.
In [1] a URI "path" part itself includes an optional facility for encoding "params" [1, section 3.3]. Params in a URI path do not necessarily have assigned value (although you can use the "=" character in a path param, so a pvaccess URI processor could be written to interpret URI path params as having assigned value, I suggest we don't use that latitude). URI path params are more like properties of the preceding path, e.g. the archived history of a quad's B field. Or modelling properties like R-matrix, or Twiss.
Path parameters follow the main part of the path, separated from it by a ";".
path param = facet of interest of the PV (optional). E.g. "quad34:bdes;history"
In example 7 below, "history" is given as a path parm. Other params that may be understood by an archive service might be "smoothed", in which the median filter or moving average is returned, or simply "average".
URI fragments are the things after a "#". For instance we use them on our web site to give links to parts of documents, eg http://epics-pvdata.sourceforge.net/pvAccess_Protocol_Specification.html#flowControl.
The URI spec [1, section 4.1] say URI fragments are intended for isolating "partial views" of the data.
So, they're a good fit for specifying the EPICS V4 pvdata request options [2].
fragment = pv field request
For example
powersupply#field(alarm,timeStamp,power.value)
There is a possible issue with this use of fragments, see
Scope and Limitations #2 below.
All examples below are of a "get", none of put or monitor. That's ok, URIs identify a resource, they're agnostic to whether the identification is for put, get or monitor of data.
Still, we want sometimes to put values, and sometimes they're complex or long values (e.g. uploading new gradient setpoints for all magnets in an accelerator section). How that going to be done?
When you upload complex data to a web service through HTTP PUT, the URI doesn't encode the data. It rather refers to the data, typically encoded in XML in an XMLHttpRequest object, which is uploaded on a different port.
Rather than "send out of band" like XmlHttpRequest, NTURI could be defined to include the facility to encode any data, but optionally so. Arbitrary pvData Fields may be added to an NTURI instance at runtime. The interpretation of these is entirely up to the service endpoint.
However, the string form of an NTURI, like
pva://rdbservice/swissfel/in/quads
, should not
attempt to "serialize" those optional fields. Similarly,
pvput is not to be expected to accept such arbitrary fields
on the command line. Note, the difference between pvput and
pvget is fungible for ChannelRPC, since the URI is
identifying a resource, and may be carrying update data.
pva://quad34:bdes
pva://quad34:bdes.val
ca://quad34:bdes
ca://quad34:bdes.lolo
pva://quad34:bdes
Example below is asking a relational db service to get the (table) resulting from the SQL query named "swissfel/in/quads" (Swissfel injector quadrupoles). The relational Db service would know how to translate "swissfel/in/quads" into the appropriate SQL. RdbService presently can do that.
pva://rdbservice/swissfel/in/quads
where:
"rdbservice" = ChannelRPC channel name = URI authority.
"/swissfel/in/quads" = URI path
Example below is asking for the archived history of a quad's B field setpoint, from a start time to an end time.
pva://archiveservice/quad34:bdes;history?starttime=2011-09-16T02.12.55&endtime=2011-09-16T10.01.03
We can't use ":" in URI queries because ":" is a reserved character [1, section 3.4], so "." is used in this example.
The new Normative type, called NTURI (uri:ev4:nt/2012/pwd:NTURI), can encode the above URI syntax.
Additionally, through the optional field-types and field-values, it can encode 'any' data. So NTURI can encode both a reference to a resource, and data for the resource. This is proposed to be the way complex data is sent to a service.
structure NTURI string authority string path opt string fragment opt string scheme opt structure query opt string[] <argument-names> scalar_t[] <argument-values> {<field-type> <field-name>}0+
The following gives an example client of creating a NTURI instance for a channelRPC acquisition for example 7 above:
// Create an NTURI Introspection interface for a ChannelRPC request to // to a notional archive service, taking 2 arguments, start time and end time. // private final static FieldCreate fieldCreate = FieldFactory.getFieldCreate(); private final static Structure queryStructure = fieldCreate.createStructure( new String[] {"starttime", "endtime"}, new Field[] { fieldCreate.createScalar(ScalarType.pvString), fieldCreate.createScalar(ScalarType.pvString)}); private final static Structure uriStructure = fieldCreate.createStructure( "uri:ev4:nt/2012/pwd:NTURI", new String[] { "authority", "path", "query" }, new Field[] {fieldCreate.createScalar(ScalarType.pvString), fieldCreate.createScalar(ScalarType.pvString), queryStructure } ); public static void main(String[] args) throws Throwable { EasyPVA easyPVA = EasyPVAFactory.get(); // Create the data interface and put the request for archive data into it. // PVStructure request = PVDataFactory.getPVDataCreate(). createPVStructure(uriStructure); request.getStringField("authority").put("miniArchiveServiceToDemoServiceInterface"); request.getStringField("path").put("quad45:bdes;history"); request.getStructureField("query").getStringField("starttime").put("2011-09-16T02.12.55"); request.getStructureField("query").getStringField("endtime").put("2011-09-16T10.01.03"); // Issue the ChannelRPC request using EasyPVA // PVStructure result = easyPVA.createChannel("miniArchiveServiceToDemoServiceInterface"). createRPC().request(request); // Print the outgoing NTURI and the returned results // System.out.println("The URI request structure:\n" + request + "\n\nResulted in:\n" + result); }
Running this against a suitable server would result in:
The URI request structure: uri:ev4:nt/2012/pwd:NTURI string authority miniArchiveServiceToDemoServiceInterface string path quad45:bdes;history structure query string starttime 2011-09-16 02:12:55 string endtime 2011-09-16 10:01:03 Resulted in: uri:ev4:nt/2012/pwd:NTTable string[] labels [sampled time,sampled value] structure values string[] times [Fri Sep 16 02:12:56 CEST 2011,Fri Sep 16 04:34:03 CEST 2011,Fri Sep 16 06:08:41 CEST 2011,Fri Sep 16 08:34:42 CEST 2011,Fri Sep 16 10:01:02 CEST 2011] double[] readings [42.2,2.76,45.3,85.3245,35.234]
Let's not try to specify syntax or semantics for EPICS V4 relativeURIs. That is, we should NOT normatively specify the EPICS URI such that "pva://swissfel/gun-to-artemis/magnets/xcors/../:bdes" should be interpreted to mean the "bdes of all the magnets in the gun-to-artemis section of swissfel." AbsoluteURI is enough for us.
Formally, a URI "fragment" is an identifier of a part of the resource *that is isolated by the agent after it has retrieved the resource*. I propose we contravene the spec in that regard. However, there is a possible downside. Imagine a EPICS V4 web service that can get EPICS data over pvaccess in the usual way. A HTTP client like your browser talks to the EPICS web service. You'd want the URI semantics used by the HTTP communication, from your browser to the web service, to be exactly the same as the URI pvaccess scheme semantics. And they could be, except for fragments. Because fragments are intended to be processed client side, the specification of the EPICS record field request probably would never go over the wire. The EPICS V4 web service would probably never see the field request. Still, I think that's ok. The suitability of URI fragments for "partial data" specifications outweighs the incompatibility for web services.
If we can fix these issues, or I see I was mistaken, I can integrate it in the URI. However, one thing I notice straight alway, is you use "," in the syntax, which is a reserved character in the URI query syntax, though not in URI fragment syntax.


BackboneUI
A View with attribute Binding
All changes to the bound model attributes are automatically propagated to the view
ScrollView with ListView
SplitView with a ScrollView and a SlickGridView (SlickGrid)
For more config options look at SlickGrid page


Question 1 Create a array containing five objects with properties { name, age, city, salary } A. Display all the objects in a table B. Create a search functionality for name and city C. Delete button to delete records D. Data is not permanent
| SNo | Name | Age | City | Salary | Actions |
|---|


TrustYou’s Mission is to positively influence travelers’ decisions. We know that customers digest and leverage lots of opinions to make good choices, and we are passionate about better travel, tourism and hospitality experiences.


Exchange - where the messages are published
Queue - where the messages are consumed
Binding - distribution rules from exchanges to queues
There are a lot of client implementations : Java, .Net, PHP, Go, Ruby, Python, Scala, Perl...
In Java, several possibilities :
Official docker image available on Docker Hub
docker run --rm -d --hostname my-rabbit --name rabbit -p 5672:5672 -p 15672:15672 rabbitmq:3-management
Management console : http://localhost:15672
Built on top of Spring Boot and Spring Integration, it is used to build easily message/event-driven microservices.
It supports bindings with RabbitMQ and Apache Kafka brokers.
It allows minimal configuration and connexion code, thanks to annotations, to focus on business code.
@EnableBinding on class declaration
@StreamListener on method declaration to consume messages
@SendTo on method declaration (+ return type) to publish messages
@EnableBinding(Sink.class)
public class MessageHandler {
@StreamListener(Sink.INPUT)
public void handle(MyEvent myEvent) {
// do what you have to do with the message
...
}
}
- Start RabbitMQ ! Play with the UI localhost:15672
- Create the 1st project ShippingService which will consume some order events. (Can use Spring Initializr through https://start.spring.io or directly in IDE)
This one is publisher and consumer : a processor (source + sink)
It should connect to same exchange than shipping-service
You can extend Processor interface...
It needs to code the message sending
@Autowired
private BinderAwareChannelResolver resolver;
...
resolver
.resolveDestination("nameofchannel")
.send(MessageBuilder.withPayload(messagePayload).build());
@StreamListener(target=Processor.INPUT, condition = "headers['bu-id']=='1'")
public void receiveForBu1() {
// ...
}
@StreamListener(target=Processor.INPUT, condition = "headers['bu-id']!='1'")
public void receiveForBuNot1() {
// ...
}
This is not compatible with @SendTo annotation ☹


Points Table
| Events | Marathas | Mauryans | Mughals | Veeras |
| Dance |
| Group Dance | 0 | 0 | 0 | 0 |
| Dance Drama | 36 | 60 | 6 | 18 |
| Battle | 48 | 8 | 80 | 24 |
| Dance Total | 84 | 68 | 86 | 42 |
| Music |
| Band | 0 | 0 | 0 | 0 |
| Pair on Stage | 0 | 0 | 0 | 0 |
| Group Song | 6 | 60 | 36 | 18 |
| Music Total | 6 | 60 | 36 | 18 |
| Fine Arts |
| Backdrop | 0 | 0 | 0 | 0 |
| Live Sketching | 0 | 0 | 0 | 0 |
| Oil Painting | 0 | 0 | 0 | 0 |
| Merge-it-All | 0 | 0 | 0 | 0 |
| Flipbook | 0 | 0 | 0 | 0 |
| Doodle | 0 | 0 | 0 | 0 |
| Fine Arts Total | 0 | 0 | 0 | 0 |
| Dramatics |
| Stage Play | 0 | 0 | 0 | 0 |
| Street Play | 0 | 0 | 0 | 0 |
| Mime | 12 | 40 | 24 | 4 |
| Dramatics Total | 12 | 40 | 24 | 4 |
| Hindi Sahitya Sabha |
| Gupchup | 0 | 0 | 0 | 0 |
| Kathaya | 0 | 0 | 0 | 0 |
| Shabdrang | 0 | 0 | 0 | 0 |
| Kavyanjali | 0 | 0 | 0 | 0 |
| Nirvaak | 0 | 0 | 0 | 0 |
| HSS Total | 0 | 0 | 0 | 0 |
| English Literary Society |
| JAM | 0 | 0 | 0 | 0 |
| Creative Writing | 0 | 0 | 0 | 0 |
| Dumb Charades | 0 | 0 | 0 | 0 |
| Poetry Slam | 0 | 0 | 0 | 0 |
| Word Games | 0 | 0 | 0 | 0 |
| ELS Total | 0 | 0 | 0 | 0 |
| Quiz |
| General Quiz | 0 | 0 | 0 | 0 |
| Mela Quiz | 0 | 0 | 0 | 0 |
| Sports Quiz | 18 | 9 | 30 | 3 |
| India Quiz | 18 | 30 | 9 | 3 |
| Sci-Tech Quiz | 0 | 0 | 0 | 0 |
| Quiz Total | 36 | 39 | 39 | 6 |
| Discusion & Debating Society |
| Aamne Saamne | 0 | 0 | 0 | 0 |
| Parliamentary Debate | 21 | 35 | 3.5 | 10.5 |
| MUN | 0 | 0 | 0 | 0 |
| Debating Total | 21 | 35 | 3.5 | 10.5 |
| Miscellaneous |
| Pool Flag | 6 | 12 | 20 | 2 |
| Galaxy Parade | 48 | 8 | 80 | 24 |
| Dubsmash | 0 | 0 | 0 | 0 |
| Pool Video | 0 | 0 | 0 | 0 |
| Antarakshari | 0 | 0 | 0 | 0 |
| Punctuality | 0 | 0 | 0 | 0 |
| Miscellaneous Total | 54 | 20 | 100 | 26 |
| |
| Total | 213 | 262 | 288.5 | 106.5 |
Standings
| Rank | Team | Points |
| 1. | Mughals | 288.5 |
| 2. | Mauryans | 262 |
| 3. | Marathas | 213 |
| 4. | Veeras | 106.5 |