Discrepancies in time when using DispatchQueue in Swift - swift

I've got a code which must be executed every half a second and I'm using the Xcode playground. I used this top answer and got a code like this:
for (index, item) in array.enumerated() {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(index), execute: {
print("\(index) - \(df.string(from: Date()))"
//play sound every second
})
}
This code is executed every second (I know that I have to divide it by 2 to get half a second but wanted to see the results). I used the DateFormatter to figure out times because I couldn't figure out why sounds are not played evenly.
let df = DateFormatter()
df.dateFormat = "ss.SSSS"
The result is that it is not triggered exactly every 1 second.
0 - 17.4800
1 - 18.5770 // even though it's not called exactly after 1s it's acceptable
2 - 19.6750
3 - 20.7770
4 - 21.8780
5 - 22.9760
6 - 24.0710
7 - 25.1690
8 - 26.2720
9 - 27.3640
10 - 28.4760
11 - 28.7580 //0.3s of difference
12 - 30.4800
13 - 30.5060 // 0.1s of difference
14 - 32.4800
15 - 32.5030 // less than 0.1s of difference

Here you execute your Print statement asynchronous so you do not get your printed data after half a second(or one second).If you execute it synchronously then you get your printed data 1 second interval.To know more about dispatch queue follow this link.Let me know if you have any problem.

Related

Swift String rare crash

In my app I have a logger that writes errors and status messages to a string. It's not written to a file, it's just handy to have something to look at when a bug happens without an attached debug session.
The addLog() method is called approx. 0-10 times every 3 seconds and is fairly simple:
every call adds the new addition to the beginning of the string along with the second it has happened
to prevent the string from blowing up in terms of size, if it exceeds 2kb, it will successively cut the "oldest" 100 log characters until it's smaller than 2kb again
The code looks as following:
var logString = ""
func addLog(s : String){
let date = Date()
logString = "\(date.second)\(s).\n\(logString)"
while(logString.count>2000){
logString=String(logString.dropLast(100))
}
}
I've never seen anything wrong with it until today when I received a crash log:
Thread 5 name:
Thread 5 Crashed:
0 libsystem_kernel.dylib 0x00000001c00f5414 __pthread_kill + 8
1 libsystem_pthread.dylib 0x00000001ddc50b50 pthread_kill + 272 (pthread.c:1392)
2 libsystem_c.dylib 0x000000019b5d3b74 abort + 104 (abort.c:110)
3 libsystem_malloc.dylib 0x00000001a1faf49c malloc_vreport + 560 (malloc_printf.c:183)
4 libsystem_malloc.dylib 0x00000001a1faf740 malloc_zone_error + 104 (malloc_printf.c:219)
5 libsystem_malloc.dylib 0x00000001a1f99ed8 free_small_botch + 40 (magazine_small.c:2215)
6 libswiftCore.dylib 0x00000001961103d8 _swift_release_dealloc + 40 (HeapObject.cpp:648)
7 APPNAME 0x00000001046b56a0 AppDelegate.addLog(s:) + 960 (AppDelegate.swift:0)
What's weird about the log itself is that the addLog() function is not in line 0 of my AppDelegate but maybe that's normal to have the wrong line in the crash report.
The only possible explanation for this issue that I can come up with is that there is an issue with thread safety in my function, or that I have missed something regarding the garbage collection in swift. It's very likely that the function is called from different threads at the same time, could that be an issue? Or do I have to get into the objective-c times retain etc. again to resolve this? What can I make out of this crash log?
You must handle all changes in serial queue. The simple modification:
private let queue = DispatchQueue(label: "addlog.queue")
private var logString = ""
func addLog(s : String) {
queue.async { [weak self] in
guard let self = self else { return }
let date = Date()
self.logString = String("\(date.second)\(s).\n\(self.logString)".prefix(2000))
}
}
In your case you can read and write the "logString" parameter from different threads, using serial DispatchQueue for handle all actions with parameter make unavailable to read and write parameter at one moment of time

How do I calculate the number of ticks per measure from a MIDI file

I am trying to calculate the number of ticks per measure (bar) from a MIDI file, but I am a bit stuck.
I have a MIDI file from which I can extract the following information (provided in meta messages):
#0: Time signature: 4/4, Metronome pulse: 24 MIDI clock ticks per click, Number of 32nd notes per beat: 8
There are two tempo messages, which I'm not sure are relevant:
#0: Microseconds per quarternote: 400000, Beats per minute: 150.0
#1800: Microseconds per quarternote: 441176, Beats per minute: 136.0001450668214
From trial and error, looking at the Note On messages, and looking at the MIDI file in Garageband, I can 'guess' that the number of ticks per measure is 2100, with a quarternote 525 ticks.
My question is: can I arrive at the 2100 number using the tempo information that was provided above, and if so how? Or have I not parsed enough information from the MIDI file and is there some other control message that I need to look at?
Use the following Java 11 code to extract the ticks per measure. This assumes 4 quarter notes per bar.
public MidiFile(String filename) throws Exception {
var file = new File(filename);
var sequence = MidiSystem.getSequence(file);
System.out.println("Tick length: " + sequence.getTickLength());
System.out.println("Division Type: " + sequence.getDivisionType());
System.out.println("Resolution (PPQ if division = " + javax.sound.midi.Sequence.PPQ + "): " + sequence.getResolution());
System.out.println("Ticks per measure: " + (4 * sequence.getResolution()));
}

Marathon backoff - is it really exponential?

I'm trying to figure out Marathon's exponential backoff configuration. Here's the documentation:
The backoffSeconds and backoffFactor values are multiplied until they reach the maxLaunchDelaySeconds value. After they reach that value, Marathon waits maxLaunchDelaySeconds before repeating this cycle exponentially. For example, if backoffSeconds: 3, backoffFactor: 2, and maxLaunchDelaySeconds: 3600, there will be ten attempts to launch a failed task, each three seconds apart. After these ten attempts, Marathon will wait 3600 seconds before repeating this cycle.
The way I think of exponential backoff is that the wait periods should be:
3*2^0 = 3
3*2^1 = 6
3*2^2 = 12
3*2^3 = 24 and so on
so every time the app crashes, Marathon will wait a longer period of time before retrying. However, given the description above, Marathon's logic for waiting looks something like this:
int retryCount = 0;
while(backoffSeconds * (backoffFactor ^ retryCount) < maxLaunchDelaySeconds)
{
wait(backoffSeconds);
retryCount++;
}
wait(maxLaunchDelaySeconds);
This matches the explanation in the documentation, since 3*2^x < 3600 for values of x fewer than or equal to 10. However, I really don't see how it can be called an exponential backoff, since the wait time is constant.
Is there a way to make Marathon wait progressively longer times with every restart of the app? Am I misunderstand the doc? Any help would be appreciated!
as far as I understand the code in the RateLimiter.scala, it is like you described, but then capped to the maxLaunchDelay waiting period. Let`s say maxLaunchDelay is one hour (3600s)
3*2^0 = 3
3*2^1 = 6
3*2^2 = 12
3*2^3 = 24
3*2^4 = 48
3*2^5 = 96
3*2^6 = 192
3*2^7 = 384
3*2^8 = 768
3*2^9 = 1536
3*2^10 = 3072
3*2^11 = 3600 (6144)
3*2^12 = 3600 (12288)
3*2^13 = 3600 (24576)
Which brings us a typically 2^n graph, see
You would get a bigger increase, if you would other backoffFactors,
for example backoff factor 10:
or backoff factor 20:
Additionally I saw a re-work of this topic, code review currently open here: https://phabricator.mesosphere.com/D1007
What do you think?
Thanks
Johannes

What is the purpose of Flux::sampleTimeout method in the project-reactor API?

The Java docs say the following:
Emit the last value from this Flux only if there were no new values emitted during the time window provided by a publisher for that particular last value.
However I found the above description confusing. I read in gitter chat that its similar to debounce in RxJava. Can someone please illustrate it with an example? I could not find this anywhere after doing a thorough search.
sampleTimeout lets you associate a companion Flux X' to each incoming value x in the source. If X' completes before the next value is emitted in the source, then value x is emitted. If not, x is dropped.
The same processing is applied to subsequent values.
Think of it as splitting the original sequence into windows delimited by the start and completion of each companion flux. If two windows overlap, the value that triggered the first one is dropped.
On the other side, you have sample(Duration) which only deals with a single companion Flux. It splits the sequence into windows that are contiguous, at a regular time period, and drops all but the last element emitted during a particular window.
(edit): about your use case
If I understand correctly, it looks like you have a processing of varying length that you want to schedule periodically, but you also don't want to consider values for which processing takes more than one period?
If so, it sounds like you want to 1) isolate your processing in its own thread using publishOn and 2) simply need sample(Duration) for the second part of the requirement (the delay allocated to a task is not changing).
Something like this:
List<Long> passed =
//regular scheduling:
Flux.interval(Duration.ofMillis(200))
//this is only to show that processing is indeed started regularly
.elapsed()
//this is to isolate the blocking processing
.publishOn(Schedulers.elastic())
//blocking processing itself
.map(tuple -> {
long l = tuple.getT2();
int sleep = l % 2 == 0 || l % 5 == 0 ? 100 : 210;
System.out.println(tuple.getT1() + "ms later - " + tuple.getT2() + ": sleeping for " + sleep + "ms");
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
return l;
})
//this is where we say "drop if too long"
.sample(Duration.ofMillis(200))
//the rest is to make it finite and print the processed values that passed
.take(10)
.collectList()
.block();
System.out.println(passed);
Which outputs:
205ms later - 0: sleeping for 100ms
201ms later - 1: sleeping for 210ms
200ms later - 2: sleeping for 100ms
199ms later - 3: sleeping for 210ms
201ms later - 4: sleeping for 100ms
200ms later - 5: sleeping for 100ms
201ms later - 6: sleeping for 100ms
196ms later - 7: sleeping for 210ms
204ms later - 8: sleeping for 100ms
198ms later - 9: sleeping for 210ms
201ms later - 10: sleeping for 100ms
196ms later - 11: sleeping for 210ms
200ms later - 12: sleeping for 100ms
202ms later - 13: sleeping for 210ms
202ms later - 14: sleeping for 100ms
200ms later - 15: sleeping for 100ms
[0, 2, 4, 5, 6, 8, 10, 12, 14, 15]
So the blocking processing is triggered approximately every 200ms, and only values that where processed within 200ms are kept.

Instrument for count the number of method calls on iPhone

The Time Profiler can measure the amount of time spent on certain methods. Is there a similar method that measures the number of times a method is called?
DTrace can do this, but only in the iPhone Simulator (it's supported by Snow Leopard, but not yet by iOS). I have two writeups about this technology on MacResearch here and here where I walk through some case studies of using DTrace to look for specific methods and when they are called.
For example, I created the following DTrace script to measure the number of times methods were called on classes with the CP prefix, as well as total up the time spent in those methods:
#pragma D option quiet
#pragma D option aggsortrev
dtrace:::BEGIN
{
printf("Sampling Core Plot methods ... Hit Ctrl-C to end.\n");
starttime = timestamp;
}
objc$target:CP*::entry
{
starttimeformethod[probemod,probefunc] = timestamp;
methodhasenteredatleastonce[probemod,probefunc] = 1;
}
objc$target:CP*::return
/methodhasenteredatleastonce[probemod,probefunc] == 1/
{
this->executiontime = (timestamp - starttimeformethod[probemod,probefunc]) / 1000;
#overallexecutions[probemod,probefunc] = count();
#overallexecutiontime[probemod,probefunc] = sum(this->executiontime);
#averageexecutiontime[probemod,probefunc] = avg(this->executiontime);
}
dtrace:::END
{
milliseconds = (timestamp - starttime) / 1000000;
normalize(#overallexecutiontime, 1000);
printf("Ran for %u ms\n", milliseconds);
printf("%30s %30s %20s %20s %20s\n", "Class", "Method", "Total CPU time (ms)", "Executions", "Average CPU time (us)");
printa("%30s %30s %20#u %20#u %20#u\n", #overallexecutiontime, #overallexecutions, #averageexecutiontime);
}
This generates the following nicely formatted output:
Class Method Total CPU time (ms) Executions Average CPU time (us)
CPLayer -drawInContext: 6995 352 19874
CPPlot -drawInContext: 5312 88 60374
CPScatterPlot -renderAsVectorInContext: 4332 44 98455
CPXYPlotSpace -viewPointForPlotPoint: 3208 4576 701
CPAxis -layoutSublayers 2050 44 46595
CPXYPlotSpace -viewCoordinateForViewLength:linearPlotRange:plotCoordinateValue: 1870 9152
...
While you can create and run DTrace scripts from the command line, probably your best bet would be to create a custom instrument in Instruments and fill in the appropriate D code within that instrument. You can then easily run that against your application in the Simulator.
Again, this won't work on the device, but if you just want statistics on the number of times something is called, and not the duration it runs for, this might do the job.