I am maintaining and developing two Akka Scala applications that interface with a Serial device to gather sensor information. The main difference between the two is that one (My CO2 sensor application) uses 1% CPU while the other (My Power sensor application) uses 250% CPU. This is both the case on a Linux machine (Raspberry Pi 3) as well as on my Windows Desktop PC. Code-wise the main difference is that CO2 uses the Serial library (http://fazecast.github.io/jSerialComm/) directly, while the Power sensor app goes through a layer of middleware to convert the In/OutputStreams of the Serial library to Akka Source/Sink as such:
val port = SerialPort.getCommPort(comPort)
port.setBaudRate(baudRate)
port.setFlowControl(flowControl)
port.setComPortParameters(baudRate, dataBits, stopBits, parity)
port.setComPortTimeouts(timeoutMode, timeout, timeout)
val isOpen = port.openPort()
if(!isOpen) {
error(s"Port $comPort could not opened. Use the following documentation for troubleshooting: https://github.com/Fazecast/jSerialComm/wiki/Troubleshooting")
throw new Exception("Port could not be opened")
}
(reactive.streamSource(port.getInputStream), reactive.streamSink(port.getOutputStream))
When I saw this high CPU usage I immediately slapped a Profiler (VisualVM) against it which told me the following:
After googling for Unsafe.park I found the following answer: https://stackoverflow.com/a/29414580/1122834 - Using this information I checked the amount of context switching WITH and WITHOUT my Power sensor app, and the results were very clear about the root cause of the issue:
pi#dex:~ $ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
10 0 32692 80144 71228 264356 0 0 0 5 7 8 38 5 55 2 0
1 0 32692 80176 71228 264356 0 0 0 76 12932 18856 59 6 35 0 0
1 0 32692 80208 71228 264356 0 0 0 0 14111 20570 60 8 32 0 0
1 0 32692 80208 71228 264356 0 0 0 0 13186 16095 65 6 29 0 0
1 0 32692 80176 71228 264356 0 0 0 0 14008 23449 56 6 38 0 0
3 0 32692 80208 71228 264356 0 0 0 0 13528 17783 65 6 29 0 0
1 0 32692 80208 71228 264356 0 0 0 28 12960 16588 63 6 31 0 0
pi#dex:~ $ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 32692 147320 71228 264332 0 0 0 5 7 8 38 5 55 2 0
0 0 32692 147296 71228 264332 0 0 0 84 963 1366 0 0 98 2 0
0 0 32692 147296 71228 264332 0 0 0 0 962 1347 1 0 99 0 0
0 0 32692 147296 71228 264332 0 0 0 0 947 1318 1 0 99 0 0
As you can see, the amount of context switches went down by ~12000 a second just by killing my application. I continued by checking which exact threads were doing this, and it seems Akka is really eager to do stuff:
Both a comment here and on another SO question point towards tweaking the parallelism settings of Akka. I added the following to my application.conf - to no result.
akka {
log-config-on-start = "on"
actor{
default-dispatcher {
# Dispatcher is the name of the event-based dispatcher
type = Dispatcher
# What kind of ExecutionService to use
executor = "fork-join-executor"
# Configuration for the fork join pool
default-executor {
fallback = "fork-join-executor"
}
fork-join-executor {
# Min number of threads to cap factor-based parallelism number to
parallelism-min = 1
# Parallelism (threads) ... ceil(available processors * factor)
parallelism-factor = 1.0
# Max number of threads to cap factor-based parallelism number to
parallelism-max = 1
}
# Throughput defines the maximum number of messages to be
# processed per actor before the thread jumps to the next actor.
# Set to 1 for as fair as possible.
throughput = 1
}
}
stream{
default-blocking-io-dispatcher {
type = PinnedDispatcher
executor = "fork-join-executor"
throughput = 1
thread-pool-executor {
core-pool-size-min = 1
core-pool-size-factor = 1.0
core-pool-size-max = 1
}
fork-join-executor {
parallelism-min = 1
parallelism-factor = 1.0
parallelism-max = 1
}
}
}
}
This seems to improve the CPU usage (100% -> 65%) but still, the CPU usage is unnecessarily high.
UPDATE 21-11-'16
It would appear the problem is inside my graph. When not running the graph the CPU usage goes down immediately to normal levels. The graph is the following:
val streamGraph = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder =>
import GraphDSL.Implicits._
val responsePacketSource = serialSource
.via(Framing.delimiter(ByteString(frameDelimiter), maxFrameLength, allowTruncation = true))
.via(cleanPacket)
.via(printOutput("Received: ",debug(_)))
.via(byteStringToResponse)
val packetSink = pushSource
.via(throttle(throttle))
val zipRequestStickResponse = builder.add(Zip[RequestPacket, ResponsePacket])
val broadcastRequest = builder.add(Broadcast[RequestPacket](2))
val broadcastResponse = builder.add(Broadcast[ResponsePacket](2))
packetSink ~> broadcastRequest.in
broadcastRequest.out(0) ~> makePacket ~> printOutput("Sent: ",debug(_)) ~> serialSink
broadcastRequest.out(1) ~> zipRequestStickResponse.in0
responsePacketSource ~> broadcastResponse.in
broadcastResponse.out(0).filter(isStickAck) ~> zipRequestStickResponse.in1
broadcastResponse.out(1).filter(!isStickAck(_)).map (al => {
val e = completeRequest(al)
debug(s"Sinking: $e")
e
}) ~> Sink.ignore
zipRequestStickResponse.out.map { case(request, stickResponse) =>
debug(s"Mapping: request=$request, stickResponse=$stickResponse")
pendingPackets += stickResponse.sequenceNumber -> request
request.stickResponse trySuccess stickResponse
} ~> Sink.ignore
ClosedShape
})
streamGraph.run()
When removing the filters from broadcastResponse, the CPU usage goes down to normal levels. This leads me to believe that the zip never happens, and therefore, the graph goes into an incorrect state.
The problem is that Fazecast's jSerialComm library has a number of different time-out modes.
static final public int TIMEOUT_NONBLOCKING = 0x00000000;
static final public int TIMEOUT_READ_SEMI_BLOCKING = 0x00000001;
static final public int TIMEOUT_WRITE_SEMI_BLOCKING = 0x00000010;
static final public int TIMEOUT_READ_BLOCKING = 0x00000100;
static final public int TIMEOUT_WRITE_BLOCKING = 0x00001000;
static final public int TIMEOUT_SCANNER = 0x00010000;
Using the non blocking read() method (TIMEOUT_NONBLOCKING) results in a very high CPU usage when combined with the Akka Stream's InputStreamPublisher. To prevent this simply use TIMEOUT_READ_SEMI_BLOCKING or TIMEOUT_READ_BLOCKING.
Related
I am downloading the signed documents using the docusign getDocument API, but the downloaded file is coming in a weird format(json as per the Content-type header). What format is this and how can I convert it to a viewable/readable format.
Here is a snippet from the response -
%PDF-1.5\n%ûüýþ\n%Writing objects...\n4 0 obj\n<<\n/Type /Page\n/Resources 5 0 R\n/Parent 3 0 R\n/MediaBox [0 0 595.32000 841.92000 ]\n/Contents [6 0 R 7 0 R 8 0 R ]\n/Group <<\n/Type /Group\n/S /Transparency\n/CS /DeviceRGB\n>>\n/Tabs /S\n/StructParents 0\n>>\nendobj\n5 0 obj\n<<\n/Font <<\n/F1 9 0 R\n/F2 10 0 R\n/F3 11 0 R\n/F4 12 0 R\n/F5 13 0 R\n>>\n/ExtGState <<\n/GS7 14 0 R\n/GS8 15 0 R\n>>\n/ProcSet [/PDF /Text /ImageB /ImageC /ImageI ]\n/XObject <<\n/X0 16 0 R\n>>\n>>\nendobj\n2 0 obj\n<<\n/Producer (PDFKit.NET 21.1.200.20790)\n/CreationDate (D:20210429103256-07'00')\n/ModDate (D:20210429103256-07'00')\n/Author ()\n/Creator ()\n/Keywords <>\n/Subject ()\n/Title ()\n>>\nendobj\n6 0 obj\n<<\n/Length 4\n>>\nstream\n\n q \nendstream\nendobj\n7 0 obj\n<<\n/Filter /FlateDecode\n/Length 7326\n>>\nstream\nxœ½]ëo\u001c7’ÿnÀÿCã\u0016¸›YDm¾šd\u0007A\u0000É’\u001dçüZ[Þà\u0010ï\u0007Å’ma-É‘FÉæ¿?
What language are you using, and are you using one of the DocuSign SDKs or a raw API call?
When I make a GetDocument call (specifically {{vx}}/accounts/{{accountid}}/envelopes/{{envelopeId}}/documents/combined, for example), the response headers have Content-Type: application/pdf and Content-Dispostion: file; filename=file.pdf, and the body of the response is the binary of the PDF file itself.
A snippet of mine begins with this:
%PDF-1.5
%����
%Writing objects...
4 0 obj
<<
/Type /Page
/Parent 3 0 R
/Resources 10 0 R
/MediaBox [0 0 612 792 ]
/Contents [11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R 17 0 R ]
/Group <<
/Type /Group
/S /Transparency
/CS /DeviceRGB
So it looks like whatever system you have picking up the response is including \n newlines and potentially other control characters.
You'll want to look at how your tools handle the API response: if you can dump the raw output from DocuSign to a PDF file, that would work, but with the extra formatting being injected it's no longer valid.
I used this piece of code to save the response from DocuSign getDocument API to a PDF document-
envelopesApi.getDocument(ACCOUNT_ID, envelope_id, 'combined', function (error, document, response) {
if (document) {
var filename = ‘docusign.pdf';
fs.writeFile(filename, new Buffer(document, 'binary'), function (err) {
if (err) console.log('Error: ' + err);
});
}
});
I am trying to fragment 120 bytes IP payload by 100 bytes. However, in output I got two packets one with 138 bytes and other with 50 bytes (Ethernet and IP header size are 14 and 20 bytes respectively). In first packet data offset starts from 0 to 103 and for second packet data offset starts from 104 to 119. Firstly I cannot understand why it works in this way. In order to understand I tried to look to source of defined fragment function in layers/inet.py line 552.
Scapy recalculates fragmentation size as follows:
def fragment(self, fragsize=1480):
"""Fragment IP datagrams"""
fragsize = (fragsize + 7) // 8 * 8 # <- RECALCULATION OF FRAGMENT SIZE
lst = []
fnb = 0
fl = self
while fl.underlayer is not None:
fnb += 1
fl = fl.underlayer
for p in fl:
s = raw(p[fnb].payload)
nb = (len(s) + fragsize - 1) // fragsize
for i in range(nb):
q = p.copy()
del(q[fnb].payload)
del(q[fnb].chksum)
del(q[fnb].len)
if i != nb - 1:
q[fnb].flags |= 1
q[fnb].frag += i * fragsize // 8
r = conf.raw_layer(load=s[i * fragsize:(i + 1) * fragsize])
r.overload_fields = p[fnb].payload.overload_fields.copy()
q.add_payload(r)
lst.append(q)
return lst
Can somebody explain why it is doing so?
N.B:
Ethernet header size 14 byte
IPv4 header size 20 byte
See https://github.com/secdev/scapy/issues/2424#issuecomment-576879663
From https://www.rfc-editor.org/rfc/rfc791#section-3.2 (page 25, top):
If an internet datagram is fragmented, its data portion must be broken on 8 octet boundaries.
To answer your question, fragment size must be a multiple of 8.
104 is a multiple of 8, not 100
I have a large data sheet (see below) in .csv format. I want to replace the numbers in each column and row with zero if it is smaller than a certain value, let's say 0.1.
Could anyone give me a hand? Thanks a lot.
I guess it can be done with sed as in this example
BCC_ACR_CR BCC_ACR_CU BCC_ACR_FE BCC_ACR_MN BCC_ACR_MO
0.2826027 3.89E-12 0.58420346 2.23E-13 0.2105587
0.27986588 3.80E-12 0.58501168 2.27E-13 0.20890705
0.27986588 3.80E-12 0.58501168 2.27E-13 0.20890705
0.27986588 3.80E-12 0.58501168 2.27E-13 0.20890705
0.28038733 3.81E-12 0.58196375 5.88E-05 0.21239142
0.26855376 3.27E-12 0.60364524 2.06E-13 0.11205138
0.27220042 3.28E-12 0.60349573 2.08E-13 0.11530944
0.36294869 3.14E-12 0.50515464 1.64E-13 3.12E-12
0.36294869 3.14E-12 0.50515464 1.64E-13 3.12E-12
0.40837234 3.07E-12 0.47202708 1.73E-13 3.03E-12
0.3643896 3.25E-12 0.50431576 1.63E-13 3.14E-12
0.3643896 3.25E-12 0.50431576 1.63E-13 3.14E-12
0.35885258 3.21E-12 0.50978952 1.64E-13 3.12E-12
Here is one for GNU awk. Field separator is assumed to be a run of space so empty fields are not allowed:
$ gawk -v value=0.1 ' # give treshold values as parameter
BEGIN { RS="( +\n?|\n)" } # every field is considered a record
{
ORS=RT # RT stores actualized RS
if($0<value) # comparison
$0=sprintf("0%-" length()-1 "s","") # format data to fit the field
}1' file # output
Output:
BCC_ACR_CR BCC_ACR_CU BCC_ACR_FE BCC_ACR_MN BCC_ACR_MO
0.2826027 0 0.58420346 0 0.2105587
0.27986588 0 0.58501168 0 0.20890705
0.27986588 0 0.58501168 0 0.20890705
0.27986588 0 0.58501168 0 0.20890705
0.28038733 0 0.58196375 0 0.21239142
0.26855376 0 0.60364524 0 0.11205138
0.27220042 0 0.60349573 0 0.11530944
0.36294869 0 0.50515464 0 0
0.36294869 0 0.50515464 0 0
0.40837234 0 0.47202708 0 0
0.3643896 0 0.50431576 0 0
0.3643896 0 0.50431576 0 0
0.35885258 0 0.50978952 0 0
I am trying to understand why the assert in this model isn't triggered.
ltl { !A#wa U B#sb && !B#wb U A#sa }
byte p = 0
byte q = 0
int x = 0
inline signal(sem) { sem++ }
inline wait (sem) { atomic { sem > 0 ; sem-- } }
proctype A() {
x = 10*x + 1
signal(p)
sa: wait(q)
wa: x = 10*x + 2
}
proctype B() {
x = 10*x + 3
signal(q)
sb: wait(p)
wb: x = 10*x + 4
}
init {
atomic { run A(); run B() }
_nr_pr == 1
assert(x != 1324)
}
Clearly, there is an order of operations that produces the final value x = 1324:
Initially x = 0
A sets x = 10*0 + 1 = 1
B sets x = 10*1 + 3 = 13
A and B allow each other to proceed
A sets x = 10*13 + 2 = 132
B sets x = 10*132 + 4 = 1324
The assertion isn't triggered because it is "never reached" when the solver proves that the property
ltl { !A#wa U B#sb && !B#wb U A#sa }
is true.
Take a look at the output that is given by the solver, it clearly states that:
it is checking any assertion, but only if within the scope of the claim:
Full statespace search for:
never claim + (ltl_0)
assertion violations + (if within scope of claim)
the assertion isn't reached:
unreached in init
t.pml:27, state 5, "assert((x!=1324))"
t.pml:28, state 6, "-end-"
(2 of 6 states)
You can use the option -noclaim so to check the model only for the assertion, which is then easily proven false:
~$ spin -search -noclaim t.pml
ltl ltl_0: ((! ((A#wa))) U ((B#sb))) && ((! ((B#wb))) U ((A#sa)))
pan:1: assertion violated (x!=1324) (at depth 13)
pan: wrote t.pml.trail
(Spin Version 6.4.8 -- 2 March 2018)
Warning: Search not completed
+ Partial Order Reduction
Full statespace search for:
never claim - (not selected)
assertion violations +
cycle checks - (disabled by -DSAFETY)
invalid end states +
State-vector 36 byte, depth reached 15, errors: 1
48 states, stored
6 states, matched
54 transitions (= stored+matched)
1 atomic steps
hash conflicts: 0 (resolved)
Stats on memory usage (in Megabytes):
0.003 equivalent memory usage for states (stored*(State-vector + overhead))
0.286 actual memory usage for states
128.000 memory used for hash table (-w24)
0.534 memory used for DFS stack (-m10000)
128.730 total actual memory usage
pan: elapsed time 0 seconds
I want to open Learn_full_data.txt extract some rows from it and write them on a new file called All_Data.txt using a foor loop.
Learn_full_data.txt Table:
vp run trial img_order mimg perc_aha_norm perc_gen_norm moon_onset moon_pulse moon_pulse_time answer_time answer_pulse answer_pulse_time fix_time fix_pulse fixpulse_time flash_onset flash_pulse flash_pulse_time_(flash_onset) tar_time_(greyscale) tar_pulse tarpulse_time answer RT_answer aha RT_aha condition solved_testphase RT_solvedtest oldnew RT_oldnew remknow RT_remknow
1 1 1 70 mimg433 0,4375 0,5625 18066 6 20029 20083 7 22029 22099 8 24029 24116 8 24029 24633 10 28029 nicht_erkannt 1055 Aha 1145 exp 0 0 old 2030 know 381
1 1 2 146 mimg665 0,6 0,4 30666 12 32029 32683 13 34029 34699 16 40028 40716 16 40028 41233 18 44028 erkannt 990 keinAha 1240 exp 1 2758 old 634 rem 1063
2 1 1 130 mimg640 0,666667 1 17366 5 19328 19383 6 21328 21399 8 25328 25416 8 25328 25933 10 29328 erkannt 871 keinAha 2121 base 1 2891 old 3105 know 533
2 1 2 83 mimg500 0,454545 0,272727 33966 13 35328 35983 14 37328 37999 15 39328 40016 15 39328 40533 17 43328 nicht_erkannt 1031 Aha 1153 exp 0 0 new 2358 kA 2358
The row Vp has two subjects, so I created a list with the subjects from the row Vp (there are many more, but I've just pasted an excerpt from it):
list = ['1','2']
Now I want to iterate over the list with this code (if the item in the list is the same as Vp, than write on All_Data.txt some rows from Learn_full_data.txt):
Learn = open('Learn_full_data.txt','r')
file = open('All_Data.txt','w')
file.write('Vp\tImg\tDescription\tPerc_gen_norm\tPerc_aha_norm\tCond\tGen\tRt_Gen\tRt_Solved\tInsight\tRt_Insight\tOldNew\tRt_OldNew\tRemKnow\tRt_RemKnow\n')
for i in list:
for splitted in Learn:
splitted = splitted.split()
Vp = splitted[0]
Img = str(splitted[4])
Perc_gen_norm = splitted[6]
Perc_aha_norm = splitted[5]
Cond = splitted[26]
Gen = splitted[22]
Rt_Gen = splitted[23]
Insight = splitted[24]
Rt_Insight = splitted[25]
Rt_Solved = splitted[28]
OldNew = splitted[29]
Rt_OldNew = splitted[30]
RemKnow = splitted[31]
Rt_Remknow = splitted[32]
if i == str(Vp):
file.write(str(Vp)+'\t'+str(Img)+'\t'+'Description'+'\t'+str(Perc_gen_norm)+'\t'+str(Perc_aha_norm)+'\t'+str(Cond)+'\t'+str(Gen)+'\t'+str(Rt_Gen)+'\t'+str(Insight)+'\t'+str(Rt_Insight)+'\t'+str(Rt_Solved)+'\t'+str(OldNew)+'\t'+str(Rt_OldNew)+'\t'+str(RemKnow)+'\t'+str(Rt_Remknow)+'\n’)
The Code output is just the first iteration from the list. I was expecting it to continue iterating:
Vp Img Description Perc_gen_norm Perc_aha_norm Cond Gen Rt_Gen Rt_Solved Insight Rt_Insight OldNew Rt_OldNew RemKnow Rt_RemKnow
1 mimg433 Description 0,5625 0,4375 exp nicht_erkannt 1055 Aha 1145 0 old 2030 know 381
1 mimg665 Description 0,4 0,6 exp erkannt 990 keinAha 1240 2758 old 634 rem 1063
The second iteration designated on the list doesn't happen. The second item of the list is '2' and the Vp item is also '2', so the second iteration should return the same for Vp '2' as it did for Vp '1'. Why does the for loop stop in Vp '1'?
The problem is that you iterate through all the lines in your code in the first iteration of your for i in list loop. In the second iteration, e.g. i = 2, the read cursor is still at the end of the file. You have to set it to the first line in each iteration. This can be done with Learn.seek(0):
for i in list:
Learn.seek(0)
for splitted in Learn:
splitted = splitted.split('\t')
Vp = splitted[0]
Img = str(splitted[4])
Perc_gen_norm = splitted[6]
Perc_aha_norm = splitted[5]
Cond = splitted[26]
Gen = splitted[22]
Rt_Gen = splitted[23]
Insight = splitted[24]
Rt_Insight = splitted[25]
Rt_Solved = splitted[28]
OldNew = splitted[29]
Rt_OldNew = splitted[30]
RemKnow = splitted[31]
Rt_Remknow = splitted[32]
if i == str(Vp):
file.write(str(Vp)+'\t'+str(Img)+'\t'+'Description'+'\t'+str(Perc_gen_norm)+'\t'+str(Perc_aha_norm)+'\t'+str(Cond)+'\t'+str(Gen)+'\t'+str(Rt_Gen)+'\t'+str(Insight)+'\t'+str(Rt_Insight)+'\t'+str(Rt_Solved)+'\t'+str(OldNew)+'\t'+str(Rt_OldNew)+'\t'+str(RemKnow)+'\t'+str(Rt_Remknow))