How to speed up program?

I’m supposed to measure the time in seconds but not constantly access it. I’m supposed to set a new alarm each time a previous one goes off. My program computes prime numbers to a text file and displays the most recent prime. It also measures the time in seconds from the beginning of the run. However, my code is too slow. How would i set a new alarm each time a previous one goes off? Any help is appreciated :)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <math.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
#include <signal.h>

long int prime;

void ALARMhandler(int sig) {
    signal(SIGALRM, SIG_IGN);
    printf("Signal %d recieved \n", sig);
    if (sig == SIGUSR1) {
        printf("The most recent prime %ld.\n", prime);
    }
    signal(SIGALRM, ALARMhandler);
}

int main(int argc, const char *argv[])
{
    clock_t timer1, start = clock();
    int count1 = 2, index = 2;
    int seconds;
    prime = 2;
    bool command_2 = false;

    if (argc < 2) {
        printf("Usage: %s filename integer\n", argv[0]);
        exit(1);
    }
    FILE *file = fopen(argv[1], "w");
    if (file == 0) {
        printf("Failed to open\n");
        exit(1);
    }

    int timerAlarm = atoi(argv[2]);
    if (argc > 2)
    {
        seconds = atoi(argv[3]);
        command_2 = true;
    }
    if (signal(SIGUSR1, alarmHandler) == SIG_ERR) {
        perror("signal");
        return 1;
    }
    else {
        alarm(timerAlarm);
    }
    
    while (true)
    {
        for (int i = 2; i * i <= count1; i++)
        {
            timer1 = clock() - start;
            if (index < argc && timer1 >= atoi(argv[index]))
            {
                raise(SIGUSR1);
                index++;
            }
            if (command_2 == i)
            {
                raise(SIGUSR1);
                index++;
            }
            if (count1 % i == 0) {
                break;
            }
            else if (i + 1 > sqrt(count1))
            {
                prime = count1;
                fprintf(file, " %ld\n", prime);
                fflush(file);
                sleep(1);
            }
        }
        count1++;
    }
    fclose(file);
    return 0;
}
Last edited on
You code doen't compile. What the 3rd parameter used for? You've changed the name of your signal handler.

What are you asking here, to improve the speed of the prime thing, or how to measure it?
> However, my code is too slow.
Well having sleep(1) in the middle of your code is doing you no favours at all!

Also, sleep() and alarm() may be incompatible.

NOTES
alarm() and setitimer(2) share the same timer; calls to one will interfere with use of the other.

Alarms created by alarm() are preserved across execve(2) and are not inherited by children created via fork(2).

sleep(3) may be implemented using SIGALRM; mixing calls to alarm() and sleep(3) is a bad idea.


Nor can you call printf() in signal handlers.

Here's an example of using alarm to print things at periodic intervals.
Yes, I'm assuming that a long int can be read and written atomically.
And the computing of primes is intentionally wasteful just to make it take some actual seconds to show something happening.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <signal.h>


// See https://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler
/* async-signal-safe implementation of integer to string conversion.
 *
 * Null terminates the output string.
 *
 * The input buffer size must be large enough to contain the output,
 * the caller must calculate it properly.
 *
 * @param[out] value  Input integer value to convert.
 * @param[out] result Buffer to output to.
 * @param[in]  base   Base to convert to.
 * @return     Pointer to the end of the written string.
 */
char *itoa_safe(intmax_t value, char *result, int base) {
    intmax_t tmp_value;
    char *ptr, *ptr2, tmp_char;
    if (base < 2 || base > 36) {
        return NULL;
    }

    ptr = result;
    do {
        tmp_value = value;
        value /= base;
        *ptr++ = "ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210"
                 "123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[35 + (tmp_value - value * base)];
    } while (value);
    if (tmp_value < 0)
        *ptr++ = '-';
    ptr2 = result;
    result = ptr;
    *ptr-- = '\0';
    while (ptr2 < ptr) {
        tmp_char = *ptr;
        *ptr--= *ptr2;
        *ptr2++ = tmp_char;
    }
    return result;
}

long int prime;
unsigned int interval;

// See http://man7.org/linux/man-pages/man7/signal-safety.7.html
// There is a restrictive list of functions that can be called
// in signal handers, and printf() isn't one of them.
// http://man7.org/linux/man-pages/man2/sigaction.2.html is preferred over signal()
void writeString(int fd, const char *buff) {
    write(fd,buff,strlen(buff));
}

void ALARMhandler(int sig) {
    if (sig == SIGALRM) {
        char buff[200];
        writeString(1,"The most recent prime ");
        itoa_safe(prime,buff,10);
        writeString(1,buff);
        writeString(1,"\n");
        signal(SIGALRM, ALARMhandler);
        alarm(interval);
    }
}

int isPrime(int n) {
    int limit = (int)ceil(sqrt(n));
    int result = 1;
    if ( n == 2 ) return result;
    if ( n % 2 == 0 ) return !result;
    for ( int i = 3 ; i <= limit ; i += 2 ) {
        if ( n % i == 0 ) {
            result = 0;
            break;
        }
    }
    return result;
}

long int computeNthPrime(int n) {
    long int p = 3;
    for ( int i = 1 ; i <= n ; i++, p += 2 ) {
        while ( !isPrime(p) ) p += 2;
    }
    return p;
}

int main(int argc, const char *argv[])
{
    if (argc < 2) {
        printf("Usage: %s filename integer\n", argv[0]);
        exit(1);
    }
    FILE *file = fopen(argv[1], "w");
    if (file == 0) {
        printf("Failed to open\n");
        exit(1);
    }

    interval = atoi(argv[2]);
    signal(SIGALRM, ALARMhandler);
    alarm(interval);

    for ( int i = 1 ; i < 10000 ; i++ ) {
        prime = computeNthPrime(i);
        fprintf(file, " %ld\n", prime);
        fflush(file);
    }
    fclose(file);
    return 0;
}



$ gcc foo.c -lm
$ ./a.out tmp 5
The most recent prime 56991
The most recent prime 78651
The most recent prime 94653


Adding clock() stuff to measure elapsed time is left as an exercise for the reader.
Topic archived. No new replies allowed.