Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
601e093d
Commit
601e093d
authored
Feb 05, 2015
by
Chris Toshok
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add richards.py and deltablue.py minibenchmarks
parent
c250a77e
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1054 additions
and
0 deletions
+1054
-0
minibenchmarks/deltablue.py
minibenchmarks/deltablue.py
+632
-0
minibenchmarks/richards.py
minibenchmarks/richards.py
+422
-0
No files found.
minibenchmarks/deltablue.py
0 → 100644
View file @
601e093d
"""
deltablue.py
============
Ported for the PyPy project.
Contributed by Daniel Lindsley
This implementation of the DeltaBlue benchmark was directly ported
from the `V8's source code`_, which was in turn derived
from the Smalltalk implementation by John Maloney and Mario
Wolczko. The original Javascript implementation was licensed under the GPL.
It's been updated in places to be more idiomatic to Python (for loops over
collections, a couple magic methods, ``OrderedCollection`` being a list & things
altering those collections changed to the builtin methods) but largely retains
the layout & logic from the original. (Ugh.)
.. _`V8's source code`: (http://code.google.com/p/v8/source/browse/branches/bleeding_edge/benchmarks/deltablue.js)
"""
from
__future__
import
print_function
# The JS variant implements "OrderedCollection", which basically completely
# overlaps with ``list``. So we'll cheat. :D
class
OrderedCollection
(
list
):
pass
class
Strength
(
object
):
REQUIRED
=
None
STRONG_PREFERRED
=
None
PREFERRED
=
None
STRONG_DEFAULT
=
None
NORMAL
=
None
WEAK_DEFAULT
=
None
WEAKEST
=
None
def
__init__
(
self
,
strength
,
name
):
super
(
Strength
,
self
).
__init__
()
self
.
strength
=
strength
self
.
name
=
name
@
classmethod
def
stronger
(
cls
,
s1
,
s2
):
return
s1
.
strength
<
s2
.
strength
@
classmethod
def
weaker
(
cls
,
s1
,
s2
):
return
s1
.
strength
>
s2
.
strength
@
classmethod
def
weakest_of
(
cls
,
s1
,
s2
):
if
cls
.
weaker
(
s1
,
s2
):
return
s1
return
s2
@
classmethod
def
strongest
(
cls
,
s1
,
s2
):
if
cls
.
stronger
(
s1
,
s2
):
return
s1
return
s2
def
next_weaker
(
self
):
strengths
=
{
0
:
self
.
__class__
.
WEAKEST
,
1
:
self
.
__class__
.
WEAK_DEFAULT
,
2
:
self
.
__class__
.
NORMAL
,
3
:
self
.
__class__
.
STRONG_DEFAULT
,
4
:
self
.
__class__
.
PREFERRED
,
# TODO: This looks like a bug in the original code. Shouldn't this be
# ``STRONG_PREFERRED? Keeping for porting sake...
5
:
self
.
__class__
.
REQUIRED
,
}
return
strengths
[
self
.
strength
]
# This is a terrible pattern IMO, but true to the original JS implementation.
Strength
.
REQUIRED
=
Strength
(
0
,
"required"
)
Strength
.
STONG_PREFERRED
=
Strength
(
1
,
"strongPreferred"
)
Strength
.
PREFERRED
=
Strength
(
2
,
"preferred"
)
Strength
.
STRONG_DEFAULT
=
Strength
(
3
,
"strongDefault"
)
Strength
.
NORMAL
=
Strength
(
4
,
"normal"
)
Strength
.
WEAK_DEFAULT
=
Strength
(
5
,
"weakDefault"
)
Strength
.
WEAKEST
=
Strength
(
6
,
"weakest"
)
class
Constraint
(
object
):
def
__init__
(
self
,
strength
):
super
(
Constraint
,
self
).
__init__
()
self
.
strength
=
strength
def
add_constraint
(
self
):
global
planner
self
.
add_to_graph
()
planner
.
incremental_add
(
self
)
def
satisfy
(
self
,
mark
):
global
planner
self
.
choose_method
(
mark
)
if
not
self
.
is_satisfied
():
if
self
.
strength
==
Strength
.
REQUIRED
:
print
(
'Could not satisfy a required constraint!'
)
return
None
self
.
mark_inputs
(
mark
)
out
=
self
.
output
()
overridden
=
out
.
determined_by
if
overridden
is
not
None
:
overridden
.
mark_unsatisfied
()
out
.
determined_by
=
self
if
not
planner
.
add_propagate
(
self
,
mark
):
print
(
'Cycle encountered'
)
out
.
mark
=
mark
return
overridden
def
destroy_constraint
(
self
):
global
planner
if
self
.
is_satisfied
():
planner
.
incremental_remove
(
self
)
else
:
self
.
remove_from_graph
()
def
is_input
(
self
):
return
False
class
UrnaryConstraint
(
Constraint
):
def
__init__
(
self
,
v
,
strength
):
super
(
UrnaryConstraint
,
self
).
__init__
(
strength
)
self
.
my_output
=
v
self
.
satisfied
=
False
self
.
add_constraint
()
def
add_to_graph
(
self
):
self
.
my_output
.
add_constraint
(
self
)
self
.
satisfied
=
False
def
choose_method
(
self
,
mark
):
if
self
.
my_output
.
mark
!=
mark
and
\
Strength
.
stronger
(
self
.
strength
,
self
.
my_output
.
walk_strength
):
self
.
satisfied
=
True
else
:
self
.
satisfied
=
False
def
is_satisfied
(
self
):
return
self
.
satisfied
def
mark_inputs
(
self
,
mark
):
# No-ops.
pass
def
output
(
self
):
# Ugh. Keeping it for consistency with the original. So much for
# "we're all adults here"...
return
self
.
my_output
def
recalculate
(
self
):
self
.
my_output
.
walk_strength
=
self
.
strength
self
.
my_output
.
stay
=
not
self
.
is_input
()
if
self
.
my_output
.
stay
:
self
.
execute
()
def
mark_unsatisfied
(
self
):
self
.
satisfied
=
False
def
inputs_known
(
self
,
mark
):
return
True
def
remove_from_graph
(
self
):
if
self
.
my_output
is
not
None
:
self
.
my_output
.
remove_constraint
(
self
)
self
.
satisfied
=
False
class
StayConstraint
(
UrnaryConstraint
):
def
__init__
(
self
,
v
,
string
):
super
(
StayConstraint
,
self
).
__init__
(
v
,
string
)
def
execute
(
self
):
# The methods, THEY DO NOTHING.
pass
class
EditConstraint
(
UrnaryConstraint
):
def
__init__
(
self
,
v
,
string
):
super
(
EditConstraint
,
self
).
__init__
(
v
,
string
)
def
is_input
(
self
):
return
True
def
execute
(
self
):
# This constraint also does nothing.
pass
class
Direction
(
object
):
# Hooray for things that ought to be structs!
NONE
=
0
FORWARD
=
1
BACKWARD
=
-
1
class
BinaryConstraint
(
Constraint
):
def
__init__
(
self
,
v1
,
v2
,
strength
):
super
(
BinaryConstraint
,
self
).
__init__
(
strength
)
self
.
v1
=
v1
self
.
v2
=
v2
self
.
direction
=
Direction
.
NONE
self
.
add_constraint
()
def
choose_method
(
self
,
mark
):
if
self
.
v1
.
mark
==
mark
:
if
self
.
v2
.
mark
!=
mark
and
Strength
.
stronger
(
self
.
strength
,
self
.
v2
.
walk_strength
):
self
.
direction
=
Direction
.
FORWARD
else
:
self
.
direction
=
Direction
.
BACKWARD
if
self
.
v2
.
mark
==
mark
:
if
self
.
v1
.
mark
!=
mark
and
Strength
.
stronger
(
self
.
strength
,
self
.
v1
.
walk_strength
):
self
.
direction
=
Direction
.
BACKWARD
else
:
self
.
direction
=
Direction
.
NONE
if
Strength
.
weaker
(
self
.
v1
.
walk_strength
,
self
.
v2
.
walk_strength
):
if
Strength
.
stronger
(
self
.
strength
,
self
.
v1
.
walk_strength
):
self
.
direction
=
Direction
.
BACKWARD
else
:
self
.
direction
=
Direction
.
NONE
else
:
if
Strength
.
stronger
(
self
.
strength
,
self
.
v2
.
walk_strength
):
self
.
direction
=
Direction
.
FORWARD
else
:
self
.
direction
=
Direction
.
BACKWARD
def
add_to_graph
(
self
):
self
.
v1
.
add_constraint
(
self
)
self
.
v2
.
add_constraint
(
self
)
self
.
direction
=
Direction
.
NONE
def
is_satisfied
(
self
):
return
self
.
direction
!=
Direction
.
NONE
def
mark_inputs
(
self
,
mark
):
self
.
input
().
mark
=
mark
def
input
(
self
):
if
self
.
direction
==
Direction
.
FORWARD
:
return
self
.
v1
return
self
.
v2
def
output
(
self
):
if
self
.
direction
==
Direction
.
FORWARD
:
return
self
.
v2
return
self
.
v1
def
recalculate
(
self
):
ihn
=
self
.
input
()
out
=
self
.
output
()
out
.
walk_strength
=
Strength
.
weakest_of
(
self
.
strength
,
ihn
.
walk_strength
)
out
.
stay
=
ihn
.
stay
if
out
.
stay
:
self
.
execute
()
def
mark_unsatisfied
(
self
):
self
.
direction
=
Direction
.
NONE
def
inputs_known
(
self
,
mark
):
i
=
self
.
input
()
return
i
.
mark
==
mark
or
i
.
stay
or
i
.
determined_by
==
None
def
remove_from_graph
(
self
):
if
self
.
v1
is
not
None
:
self
.
v1
.
remove_constraint
(
self
)
if
self
.
v2
is
not
None
:
self
.
v2
.
remove_constraint
(
self
)
self
.
direction
=
Direction
.
NONE
class
ScaleConstraint
(
BinaryConstraint
):
def
__init__
(
self
,
src
,
scale
,
offset
,
dest
,
strength
):
self
.
direction
=
Direction
.
NONE
self
.
scale
=
scale
self
.
offset
=
offset
super
(
ScaleConstraint
,
self
).
__init__
(
src
,
dest
,
strength
)
def
add_to_graph
(
self
):
super
(
ScaleConstraint
,
self
).
add_to_graph
()
self
.
scale
.
add_constraint
(
self
)
self
.
offset
.
add_constraint
(
self
)
def
remove_from_graph
(
self
):
super
(
ScaleConstraint
,
self
).
remove_from_graph
()
if
self
.
scale
is
not
None
:
self
.
scale
.
remove_constraint
(
self
)
if
self
.
offset
is
not
None
:
self
.
offset
.
remove_constraint
(
self
)
def
mark_inputs
(
self
,
mark
):
super
(
ScaleConstraint
,
self
).
mark_inputs
(
mark
)
self
.
scale
.
mark
=
mark
self
.
offset
.
mark
=
mark
def
execute
(
self
):
if
self
.
direction
==
Direction
.
FORWARD
:
self
.
v2
.
value
=
self
.
v1
.
value
*
self
.
scale
.
value
+
self
.
offset
.
value
else
:
self
.
v1
.
value
=
(
self
.
v2
.
value
-
self
.
offset
.
value
)
/
self
.
scale
.
value
def
recalculate
(
self
):
ihn
=
self
.
input
()
out
=
self
.
output
()
out
.
walk_strength
=
Strength
.
weakest_of
(
self
.
strength
,
ihn
.
walk_strength
)
out
.
stay
=
ihn
.
stay
and
self
.
scale
.
stay
and
self
.
offset
.
stay
if
out
.
stay
:
self
.
execute
()
class
EqualityConstraint
(
BinaryConstraint
):
def
execute
(
self
):
self
.
output
().
value
=
self
.
input
().
value
class
Variable
(
object
):
def
__init__
(
self
,
name
,
initial_value
=
0
):
super
(
Variable
,
self
).
__init__
()
self
.
name
=
name
self
.
value
=
initial_value
self
.
constraints
=
OrderedCollection
()
self
.
determined_by
=
None
self
.
mark
=
0
self
.
walk_strength
=
Strength
.
WEAKEST
self
.
stay
=
True
def
__repr__
(
self
):
# To make debugging this beast from pdb easier...
return
'<Variable: %s - %s>'
%
(
self
.
name
,
self
.
value
)
def
add_constraint
(
self
,
constraint
):
self
.
constraints
.
append
(
constraint
)
def
remove_constraint
(
self
,
constraint
):
self
.
constraints
.
remove
(
constraint
)
if
self
.
determined_by
==
constraint
:
self
.
determined_by
=
None
class
Planner
(
object
):
def
__init__
(
self
):
super
(
Planner
,
self
).
__init__
()
self
.
current_mark
=
0
def
incremental_add
(
self
,
constraint
):
mark
=
self
.
new_mark
()
overridden
=
constraint
.
satisfy
(
mark
)
while
overridden
is
not
None
:
overridden
=
overridden
.
satisfy
(
mark
)
def
incremental_remove
(
self
,
constraint
):
out
=
constraint
.
output
()
constraint
.
mark_unsatisfied
()
constraint
.
remove_from_graph
()
unsatisfied
=
self
.
remove_propagate_from
(
out
)
strength
=
Strength
.
REQUIRED
# Do-while, the Python way.
repeat
=
True
while
repeat
:
for
u
in
unsatisfied
:
if
u
.
strength
==
strength
:
self
.
incremental_add
(
u
)
strength
=
strength
.
next_weaker
()
repeat
=
strength
!=
Strength
.
WEAKEST
def
new_mark
(
self
):
self
.
current_mark
+=
1
return
self
.
current_mark
def
make_plan
(
self
,
sources
):
mark
=
self
.
new_mark
()
plan
=
Plan
()
todo
=
sources
while
len
(
todo
):
c
=
todo
.
pop
(
0
)
if
c
.
output
().
mark
!=
mark
and
c
.
inputs_known
(
mark
):
plan
.
add_constraint
(
c
)
c
.
output
().
mark
=
mark
self
.
add_constraints_consuming_to
(
c
.
output
(),
todo
)
return
plan
def
extract_plan_from_constraints
(
self
,
constraints
):
sources
=
OrderedCollection
()
for
c
in
constraints
:
if
c
.
is_input
()
and
c
.
is_satisfied
():
sources
.
append
(
c
)
return
self
.
make_plan
(
sources
)
def
add_propagate
(
self
,
c
,
mark
):
todo
=
OrderedCollection
()
todo
.
append
(
c
)
while
len
(
todo
):
d
=
todo
.
pop
(
0
)
if
d
.
output
().
mark
==
mark
:
self
.
incremental_remove
(
c
)
return
False
d
.
recalculate
()
self
.
add_constraints_consuming_to
(
d
.
output
(),
todo
)
return
True
def
remove_propagate_from
(
self
,
out
):
out
.
determined_by
=
None
out
.
walk_strength
=
Strength
.
WEAKEST
out
.
stay
=
True
unsatisfied
=
OrderedCollection
()
todo
=
OrderedCollection
()
todo
.
append
(
out
)
while
len
(
todo
):
v
=
todo
.
pop
(
0
)
for
c
in
v
.
constraints
:
if
not
c
.
is_satisfied
():
unsatisfied
.
append
(
c
)
determining
=
v
.
determined_by
for
c
in
v
.
constraints
:
if
c
!=
determining
and
c
.
is_satisfied
():
c
.
recalculate
()
todo
.
append
(
c
.
output
())
return
unsatisfied
def
add_constraints_consuming_to
(
self
,
v
,
coll
):
determining
=
v
.
determined_by
cc
=
v
.
constraints
for
c
in
cc
:
if
c
!=
determining
and
c
.
is_satisfied
():
# I guess we're just updating a reference (``coll``)? Seems
# inconsistent with the rest of the implementation, where they
# return the lists...
coll
.
append
(
c
)
class
Plan
(
object
):
def
__init__
(
self
):
super
(
Plan
,
self
).
__init__
()
self
.
v
=
OrderedCollection
()
def
add_constraint
(
self
,
c
):
self
.
v
.
append
(
c
)
def
__len__
(
self
):
return
len
(
self
.
v
)
def
__getitem__
(
self
,
index
):
return
self
.
v
[
index
]
def
execute
(
self
):
for
c
in
self
.
v
:
c
.
execute
()
# Main
def
chain_test
(
n
):
"""
This is the standard DeltaBlue benchmark. A long chain of equality
constraints is constructed with a stay constraint on one end. An
edit constraint is then added to the opposite end and the time is
measured for adding and removing this constraint, and extracting
and executing a constraint satisfaction plan. There are two cases.
In case 1, the added constraint is stronger than the stay
constraint and values must propagate down the entire length of the
chain. In case 2, the added constraint is weaker than the stay
constraint so it cannot be accomodated. The cost in this case is,
of course, very low. Typical situations lie somewhere between these
two extremes.
"""
global
planner
planner
=
Planner
()
prev
,
first
,
last
=
None
,
None
,
None
# We need to go up to n inclusively.
for
i
in
range
(
n
+
1
):
name
=
"v%s"
%
i
v
=
Variable
(
name
)
if
prev
is
not
None
:
EqualityConstraint
(
prev
,
v
,
Strength
.
REQUIRED
)
if
i
==
0
:
first
=
v
if
i
==
n
:
last
=
v
prev
=
v
StayConstraint
(
last
,
Strength
.
STRONG_DEFAULT
)
edit
=
EditConstraint
(
first
,
Strength
.
PREFERRED
)
edits
=
OrderedCollection
()
edits
.
append
(
edit
)
plan
=
planner
.
extract_plan_from_constraints
(
edits
)
for
i
in
range
(
100
):
first
.
value
=
i
plan
.
execute
()
if
last
.
value
!=
i
:
print
(
"Chain test failed."
)
def
projection_test
(
n
):
"""
This test constructs a two sets of variables related to each
other by a simple linear transformation (scale and offset). The
time is measured to change a variable on either side of the
mapping and to change the scale and offset factors.
"""
global
planner
planner
=
Planner
()
scale
=
Variable
(
"scale"
,
10
)
offset
=
Variable
(
"offset"
,
1000
)
src
,
dest
=
None
,
None
dests
=
OrderedCollection
()
for
i
in
range
(
n
):
src
=
Variable
(
"src%s"
%
i
,
i
)
dst
=
Variable
(
"dst%s"
%
i
,
i
)
dests
.
append
(
dst
)
StayConstraint
(
src
,
Strength
.
NORMAL
)
ScaleConstraint
(
src
,
scale
,
offset
,
dst
,
Strength
.
REQUIRED
)
change
(
src
,
17
)
if
dst
.
value
!=
1170
:
print
(
"Projection 1 failed"
)
change
(
dst
,
1050
)
if
src
.
value
!=
5
:
print
(
"Projection 2 failed"
)
change
(
scale
,
5
)
for
i
in
range
(
n
-
1
):
if
dests
[
i
].
value
!=
(
i
*
5
+
1000
):
print
(
"Projection 3 failed"
)
change
(
offset
,
2000
)
for
i
in
range
(
n
-
1
):
if
dests
[
i
].
value
!=
(
i
*
5
+
2000
):
print
(
"Projection 4 failed"
)
def
change
(
v
,
new_value
):
global
planner
edit
=
EditConstraint
(
v
,
Strength
.
PREFERRED
)
edits
=
OrderedCollection
()
edits
.
append
(
edit
)
plan
=
planner
.
extract_plan_from_constraints
(
edits
)
for
i
in
range
(
10
):
v
.
value
=
new_value
plan
.
execute
()
edit
.
destroy_constraint
()
# HOORAY FOR GLOBALS... Oh wait.
# In spirit of the original, we'll keep it, but ugh.
planner
=
None
def
delta_blue
():
chain_test
(
100
)
projection_test
(
100
)
# Specific to the PyPy implementation, to run within the main harnass.
def
main
(
n
):
import
time
times
=
[]
for
i
in
range
(
n
):
t1
=
time
.
time
()
delta_blue
()
t2
=
time
.
time
()
times
.
append
(
t2
-
t1
)
return
times
main
(
100
)
minibenchmarks/richards.py
0 → 100644
View file @
601e093d
# based on a Java version:
# Based on original version written in BCPL by Dr Martin Richards
# in 1981 at Cambridge University Computer Laboratory, England
# and a C++ version derived from a Smalltalk version written by
# L Peter Deutsch.
# Java version: Copyright (C) 1995 Sun Microsystems, Inc.
# Translation from C++, Mario Wolczko
# Outer loop added by Alex Jacoby
# Task IDs
I_IDLE
=
1
I_WORK
=
2
I_HANDLERA
=
3
I_HANDLERB
=
4
I_DEVA
=
5
I_DEVB
=
6
# Packet types
K_DEV
=
1000
K_WORK
=
1001
# Packet
BUFSIZE
=
4
BUFSIZE_RANGE
=
range
(
BUFSIZE
)
class
Packet
(
object
):
def
__init__
(
self
,
l
,
i
,
k
):
self
.
link
=
l
self
.
ident
=
i
self
.
kind
=
k
self
.
datum
=
0
self
.
data
=
[
0
]
*
BUFSIZE
def
append_to
(
self
,
lst
):
self
.
link
=
None
if
lst
is
None
:
return
self
else
:
p
=
lst
next
=
p
.
link
while
next
is
not
None
:
p
=
next
next
=
p
.
link
p
.
link
=
self
return
lst
# Task Records
class
TaskRec
(
object
):
pass
class
DeviceTaskRec
(
TaskRec
):
def
__init__
(
self
):
self
.
pending
=
None
class
IdleTaskRec
(
TaskRec
):
def
__init__
(
self
):
self
.
control
=
1
self
.
count
=
10000
class
HandlerTaskRec
(
TaskRec
):
def
__init__
(
self
):
self
.
work_in
=
None
self
.
device_in
=
None
def
workInAdd
(
self
,
p
):
self
.
work_in
=
p
.
append_to
(
self
.
work_in
)
return
self
.
work_in
def
deviceInAdd
(
self
,
p
):
self
.
device_in
=
p
.
append_to
(
self
.
device_in
)
return
self
.
device_in
class
WorkerTaskRec
(
TaskRec
):
def
__init__
(
self
):
self
.
destination
=
I_HANDLERA
self
.
count
=
0
# Task
class
TaskState
(
object
):
def
__init__
(
self
):
self
.
packet_pending
=
True
self
.
task_waiting
=
False
self
.
task_holding
=
False
def
packetPending
(
self
):
self
.
packet_pending
=
True
self
.
task_waiting
=
False
self
.
task_holding
=
False
return
self
def
waiting
(
self
):
self
.
packet_pending
=
False
self
.
task_waiting
=
True
self
.
task_holding
=
False
return
self
def
running
(
self
):
self
.
packet_pending
=
False
self
.
task_waiting
=
False
self
.
task_holding
=
False
return
self
def
waitingWithPacket
(
self
):
self
.
packet_pending
=
True
self
.
task_waiting
=
True
self
.
task_holding
=
False
return
self
def
isPacketPending
(
self
):
return
self
.
packet_pending
def
isTaskWaiting
(
self
):
return
self
.
task_waiting
def
isTaskHolding
(
self
):
return
self
.
task_holding
def
isTaskHoldingOrWaiting
(
self
):
return
self
.
task_holding
or
(
not
self
.
packet_pending
and
self
.
task_waiting
)
def
isWaitingWithPacket
(
self
):
return
self
.
packet_pending
and
self
.
task_waiting
and
not
self
.
task_holding
tracing
=
False
layout
=
0
def
trace
(
a
):
global
layout
layout
-=
1
if
layout
<=
0
:
print
layout
=
50
print
a
,
TASKTABSIZE
=
10
class
TaskWorkArea
(
object
):
def
__init__
(
self
):
self
.
taskTab
=
[
None
]
*
TASKTABSIZE
self
.
taskList
=
None
self
.
holdCount
=
0
self
.
qpktCount
=
0
taskWorkArea
=
TaskWorkArea
()
class
Task
(
TaskState
):
def
__init__
(
self
,
i
,
p
,
w
,
initialState
,
r
):
self
.
link
=
taskWorkArea
.
taskList
self
.
ident
=
i
self
.
priority
=
p
self
.
input
=
w
self
.
packet_pending
=
initialState
.
isPacketPending
()
self
.
task_waiting
=
initialState
.
isTaskWaiting
()
self
.
task_holding
=
initialState
.
isTaskHolding
()
self
.
handle
=
r
taskWorkArea
.
taskList
=
self
taskWorkArea
.
taskTab
[
i
]
=
self
def
fn
(
self
,
pkt
,
r
):
raise
NotImplementedError
def
addPacket
(
self
,
p
,
old
):
if
self
.
input
is
None
:
self
.
input
=
p
self
.
packet_pending
=
True
if
self
.
priority
>
old
.
priority
:
return
self
else
:
p
.
append_to
(
self
.
input
)
return
old
def
runTask
(
self
):
if
self
.
isWaitingWithPacket
():
msg
=
self
.
input
self
.
input
=
msg
.
link
if
self
.
input
is
None
:
self
.
running
()
else
:
self
.
packetPending
()
else
:
msg
=
None
return
self
.
fn
(
msg
,
self
.
handle
)
def
waitTask
(
self
):
self
.
task_waiting
=
True
return
self
def
hold
(
self
):
taskWorkArea
.
holdCount
+=
1
self
.
task_holding
=
True
return
self
.
link
def
release
(
self
,
i
):
t
=
self
.
findtcb
(
i
)
t
.
task_holding
=
False
if
t
.
priority
>
self
.
priority
:
return
t
else
:
return
self
def
qpkt
(
self
,
pkt
):
t
=
self
.
findtcb
(
pkt
.
ident
)
taskWorkArea
.
qpktCount
+=
1
pkt
.
link
=
None
pkt
.
ident
=
self
.
ident
return
t
.
addPacket
(
pkt
,
self
)
def
findtcb
(
self
,
id
):
t
=
taskWorkArea
.
taskTab
[
id
]
if
t
is
None
:
raise
Exception
(
"Bad task id %d"
%
id
)
return
t
# DeviceTask
class
DeviceTask
(
Task
):
def
__init__
(
self
,
i
,
p
,
w
,
s
,
r
):
Task
.
__init__
(
self
,
i
,
p
,
w
,
s
,
r
)
def
fn
(
self
,
pkt
,
r
):
d
=
r
assert
isinstance
(
d
,
DeviceTaskRec
)
if
pkt
is
None
:
pkt
=
d
.
pending
if
pkt
is
None
:
return
self
.
waitTask
()
else
:
d
.
pending
=
None
return
self
.
qpkt
(
pkt
)
else
:
d
.
pending
=
pkt
if
tracing
:
trace
(
pkt
.
datum
)
return
self
.
hold
()
class
HandlerTask
(
Task
):
def
__init__
(
self
,
i
,
p
,
w
,
s
,
r
):
Task
.
__init__
(
self
,
i
,
p
,
w
,
s
,
r
)
def
fn
(
self
,
pkt
,
r
):
h
=
r
assert
isinstance
(
h
,
HandlerTaskRec
)
if
pkt
is
not
None
:
if
pkt
.
kind
==
K_WORK
:
h
.
workInAdd
(
pkt
)
else
:
h
.
deviceInAdd
(
pkt
)
work
=
h
.
work_in
if
work
is
None
:
return
self
.
waitTask
()
count
=
work
.
datum
if
count
>=
BUFSIZE
:
h
.
work_in
=
work
.
link
return
self
.
qpkt
(
work
)
dev
=
h
.
device_in
if
dev
is
None
:
return
self
.
waitTask
()
h
.
device_in
=
dev
.
link
dev
.
datum
=
work
.
data
[
count
]
work
.
datum
=
count
+
1
return
self
.
qpkt
(
dev
)
# IdleTask
class
IdleTask
(
Task
):
def
__init__
(
self
,
i
,
p
,
w
,
s
,
r
):
Task
.
__init__
(
self
,
i
,
0
,
None
,
s
,
r
)
def
fn
(
self
,
pkt
,
r
):
i
=
r
assert
isinstance
(
i
,
IdleTaskRec
)
i
.
count
-=
1
if
i
.
count
==
0
:
return
self
.
hold
()
elif
i
.
control
&
1
==
0
:
i
.
control
/=
2
return
self
.
release
(
I_DEVA
)
else
:
i
.
control
=
i
.
control
/
2
^
0xd008
return
self
.
release
(
I_DEVB
)
# WorkTask
A
=
ord
(
'A'
)
class
WorkTask
(
Task
):
def
__init__
(
self
,
i
,
p
,
w
,
s
,
r
):
Task
.
__init__
(
self
,
i
,
p
,
w
,
s
,
r
)
def
fn
(
self
,
pkt
,
r
):
w
=
r
assert
isinstance
(
w
,
WorkerTaskRec
)
if
pkt
is
None
:
return
self
.
waitTask
()
if
w
.
destination
==
I_HANDLERA
:
dest
=
I_HANDLERB
else
:
dest
=
I_HANDLERA
w
.
destination
=
dest
pkt
.
ident
=
dest
pkt
.
datum
=
0
for
i
in
BUFSIZE_RANGE
:
# xrange(BUFSIZE)
w
.
count
+=
1
if
w
.
count
>
26
:
w
.
count
=
1
pkt
.
data
[
i
]
=
A
+
w
.
count
-
1
return
self
.
qpkt
(
pkt
)
import
time
def
schedule
():
t
=
taskWorkArea
.
taskList
while
t
is
not
None
:
pkt
=
None
if
tracing
:
print
"tcb ="
,
t
.
ident
if
t
.
isTaskHoldingOrWaiting
():
t
=
t
.
link
else
:
if
tracing
:
trace
(
chr
(
ord
(
"0"
)
+
t
.
ident
))
t
=
t
.
runTask
()
class
Richards
(
object
):
def
run
(
self
,
iterations
):
for
i
in
xrange
(
iterations
):
taskWorkArea
.
holdCount
=
0
taskWorkArea
.
qpktCount
=
0
IdleTask
(
I_IDLE
,
1
,
10000
,
TaskState
().
running
(),
IdleTaskRec
())
wkq
=
Packet
(
None
,
0
,
K_WORK
)
wkq
=
Packet
(
wkq
,
0
,
K_WORK
)
WorkTask
(
I_WORK
,
1000
,
wkq
,
TaskState
().
waitingWithPacket
(),
WorkerTaskRec
())
wkq
=
Packet
(
None
,
I_DEVA
,
K_DEV
)
wkq
=
Packet
(
wkq
,
I_DEVA
,
K_DEV
)
wkq
=
Packet
(
wkq
,
I_DEVA
,
K_DEV
)
HandlerTask
(
I_HANDLERA
,
2000
,
wkq
,
TaskState
().
waitingWithPacket
(),
HandlerTaskRec
())
wkq
=
Packet
(
None
,
I_DEVB
,
K_DEV
)
wkq
=
Packet
(
wkq
,
I_DEVB
,
K_DEV
)
wkq
=
Packet
(
wkq
,
I_DEVB
,
K_DEV
)
HandlerTask
(
I_HANDLERB
,
3000
,
wkq
,
TaskState
().
waitingWithPacket
(),
HandlerTaskRec
())
wkq
=
None
;
DeviceTask
(
I_DEVA
,
4000
,
wkq
,
TaskState
().
waiting
(),
DeviceTaskRec
());
DeviceTask
(
I_DEVB
,
5000
,
wkq
,
TaskState
().
waiting
(),
DeviceTaskRec
());
schedule
()
if
taskWorkArea
.
holdCount
==
9297
and
taskWorkArea
.
qpktCount
==
23246
:
pass
else
:
return
False
return
True
def
entry_point
(
iterations
):
r
=
Richards
()
startTime
=
time
.
time
()
result
=
r
.
run
(
iterations
)
endTime
=
time
.
time
()
return
result
,
startTime
,
endTime
def
main
(
entry_point
=
entry_point
,
iterations
=
10
):
print
"Richards benchmark (Python) starting... [%r]"
%
entry_point
result
,
startTime
,
endTime
=
entry_point
(
iterations
)
if
not
result
:
print
"Incorrect results!"
return
-
1
print
"finished."
total_s
=
endTime
-
startTime
print
"Total time for %d iterations: %.2f secs"
%
(
iterations
,
total_s
)
print
"Average time per iteration: %.2f ms"
%
(
total_s
*
1000
/
iterations
)
return
42
if
__name__
==
'__main__'
:
import
sys
if
len
(
sys
.
argv
)
>=
2
:
main
(
iterations
=
int
(
sys
.
argv
[
1
]))
else
:
main
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment