Shop OBEX P1 Docs P2 Docs Learn Events
Is there such a Thing as a Program Optimizer? — Parallax Forums

Is there such a Thing as a Program Optimizer?

MovieMakerMovieMaker Posts: 502
edited 2009-08-16 20:22 in Robotics
Is there such a Thing as a Program Optimizer?

After you have gotten your program to work fine in what ever language (C for me right now), is there a Second compiler you can put it through that it would search for code that would do the same thing with less code and replace the main code with the shorter code and make things run faster?

It is a silly idea, but it seems it would certainly save some time and be very useful, at least to me.

If they make such an animal, what would it be called?

tongue.gif
·

Comments

  • SRLMSRLM Posts: 5,045
    edited 2009-08-15 20:59
    A compiler.

    Most compilers (for mainstream languages) do all sorts of tricks to optimize for speed or size. Compiler Optimization has everything you may want to know.

    But otherwise, you probably won't find a stand alone program that will take any program in and give any program out that's 'better'.
  • MovieMakerMovieMaker Posts: 502
    edited 2009-08-15 21:00
    Thanks!
  • John R.John R. Posts: 1,376
    edited 2009-08-16 15:36
    One of the better methods is to have another person help look over the code. Just having two brains working can make a huge difference. One sees stuff the other doesn't. If you can get two people who are not "offended" by each others suggestions, you can have a great team. (see "extreme programming" and the like).

    While the compilers can do a lot, they will still follow your basic algorithm. Most of the "big changes" tend to involve a different way of doing things.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    John R.
    Click here to see my Nomad Build Log
  • MovieMakerMovieMaker Posts: 502
    edited 2009-08-16 17:29
    It is my lack of knowlege on c that is making it slow, I guess.

    Thanks~!
  • SRLMSRLM Posts: 5,045
    edited 2009-08-16 17:30
    Try posting the program. I'll take a look at it.
  • MovieMakerMovieMaker Posts: 502
    edited 2009-08-16 17:39
    Here it is: I believe the brow portion is the one that is getting me slow because before I added it everything was fast.

    #include <MegaServo.h>
    MegaServo myservo;
    // Begin Robot Code
    int micVal;
    int cdsVal;
    int irLval; // Left IR
    int irCval; // Center IR
    int irRval; // Right IR
    int irRRval; // Rear IR
    int i; // Generic Counter
    int x; // Generic Counter
    int PLval; // Pulse Width for Left Servo
    int PRval; // Pulse Width for Right Servo
    int cntr; // Generic Counter Used for Determining amt. of Object Detections
    int counter; // Generic Counter
    int clrpth; // amt. of Milliseconds Of Unobstructed Path
    int objdet; // Time an Object was Detected
    int task; // Routine to Follow for Clearest Path
    int pwm; // Pulse Width for Pan Servo
    boolean add; // Whether to Increment or Decrement PW Value for Pan Servo
    int distance; // Distance to Object Detected via Ultrasonic Ranger
    int oldDistance; // Previous Distance Value Read from Ultrasonic Ranger

    float scale = 1.9866666666666666666666666666667; // *Not Currently Used*

    int LeftPin = 6; // Left Servo
    int RightPin = 9; // Right Servo
    int PingServoPin = 5; // Pan Servo
    int irLPin = 0; // Analog 0; Left IR
    int irCPin = 1; // Analog 1; Center IR
    int irRPin = 2; // Analog 2; Right IR
    int irRRPin =3; // Analog 3; Rear IR
    int ultraSoundSignal = 7; // Ultrasound signal pin
    int val = 0; // Used for Ultrasonic Ranger
    int ultrasoundValue = 0; // Raw Distance Val
    int oldUltrasoundValue; // *Not used*
    int pulseCount; // Generic Counter
    int timecount = 0; // Echo counter
    int ledPin = 13; // LED connected to digital pin 13
    int pos = 0;
    int SPKR = 4;

    #define BAUD 9600
    #define CmConstant 1/29.034

    void setup() {
    myservo.attach(11);
    pos = 40;
    myservo.write(pos);
    delay(150);
    myservo.detach();
    Serial.begin(9600);
    pinMode(SPKR, OUTPUT);
    pinMode(ledPin, OUTPUT);
    pinMode(LeftPin, OUTPUT);
    pinMode(RightPin, OUTPUT);
    pinMode(PingServoPin, OUTPUT);
    pinMode(irLPin, INPUT);
    pinMode(irCPin, INPUT);
    pinMode(irRPin, INPUT);
    pinMode(irRRPin, INPUT);
    // Beep!
    {
    for (int i = 0; i<500; i++) { // generate a 1KHz tone for 1/2 second
    digitalWrite(SPKR, HIGH);
    delayMicroseconds(500);
    digitalWrite(SPKR, LOW);
    delayMicroseconds(500);
    }
    for(i = 0; i < 20; i++) {
    digitalWrite(PingServoPin, HIGH);
    delayMicroseconds(655 * 2);
    digitalWrite(PingServoPin, LOW);
    delay(20);
    }
    ultrasoundValue = 600;
    i = 0;
    }
    }
    void loop()
    {
    Look();
    Go();
    }
    void Look() {
    irLval = analogRead(irLPin);
    irCval = analogRead(irCPin);
    irRval = analogRead(irRPin);
    if(irLval > 200) {
    BrowUP();
    PLval = 850;
    PRval = 820;
    x = 5;
    cntr = cntr + 1;
    clrpth = 0;
    objdet = millis();
    }
    else if(irCval > 200) {
    BrowUP();
    PLval = 850;
    PRval = 820;
    x = 10;
    cntr = cntr + 1;
    clrpth = 0;
    objdet = millis();
    }
    else if(irRval > 200) {
    BrowUP();
    PLval = 650;
    PRval = 620;
    x = 5;
    cntr = cntr + 1;
    clrpth = 0;
    objdet = millis();
    }
    else {
    x = 1;
    PLval = 850;
    PRval = 620;
    counter = counter + 1;
    clrpth = (millis() - objdet);
    if(add == true) {
    pwm = pwm + 50;
    }
    else if(add == false) {
    pwm = pwm - 50;
    }
    if(pwm < 400) {
    pwm = 400;
    add = true;
    }
    if(pwm > 950) {
    pwm = 950;
    add = false;
    }
    digitalWrite(PingServoPin, HIGH);
    delayMicroseconds(pwm * 2);
    digitalWrite(PingServoPin, LOW);
    delay(20);
    readPing();
    if(ultrasoundValue < 200) { // this value is the closeness of PING will get.
    cntr = cntr + 1;
    switch(pwm) {
    case 400:
    x = 7;
    PLval = 650;
    PRval = 650;
    Go();
    break;
    case 500:
    x = 10;
    PLval = 650;
    PRval = 650;
    Go();
    break;
    case 600:
    x = 14;
    PLval = 850;
    PRval = 850;
    Go();
    break;
    case 700:
    x = 10;
    PLval = 850;
    PRval = 850;
    Go();
    break;
    case 950:
    x = 7;
    PLval = 850;
    PRval = 850;
    Go();
    break;
    }
    }
    }
    if(cntr > 25 && clrpth < 2000) {
    clrpth = 0;
    cntr = 0;
    Scan();
    }
    }
    void Go() {
    for(i = 0; i < x; i++) {
    digitalWrite(LeftPin, HIGH);
    delayMicroseconds(PLval * 2);
    digitalWrite(LeftPin, LOW);
    digitalWrite(RightPin, HIGH);
    delayMicroseconds(PRval * 2);
    digitalWrite(RightPin, LOW);
    delay(20);
    }
    }
    void readPing() { // Get Distance from Ultrasonic Ranger
    timecount = 0;
    val = 0;
    pinMode(ultraSoundSignal, OUTPUT); // Switch signalpin to output
    digitalWrite(ultraSoundSignal, LOW); // Send low pulse
    delayMicroseconds(2); // Wait for 2 microseconds
    digitalWrite(ultraSoundSignal, HIGH); // Send high pulse
    delayMicroseconds(5); // Wait for 5 microseconds
    digitalWrite(ultraSoundSignal, LOW); // Holdoff
    pinMode(ultraSoundSignal, INPUT); // Switch signalpin to input
    val = digitalRead(ultraSoundSignal); // Append signal value to val
    while(val == LOW) { // Loop until pin reads a high value
    val = digitalRead(ultraSoundSignal);
    }

    while(val == HIGH) { // Loop until pin reads a high value
    val = digitalRead(ultraSoundSignal);
    timecount = timecount +1; // Count echo pulse time
    }
    ultrasoundValue = timecount; // Append echo pulse time to ultrasoundValue

    // Lite up LED if any value is passed by the echo pulse
    if(timecount > 0){
    digitalWrite(ledPin, HIGH);
    }
    }
    void Scan() { // Scan for the Clearest Path
    oldDistance = 10;
    task = 0;
    for(i = 1; i < 5; i++) {
    switch(i) {
    case 1:
    //Serial.println("Pos. 1");
    pwm = 1125; /// incr. by 100 from 1085
    break;
    case 2:
    //Serial.println("Pos. 2");
    pwm = 850; //// increased by 100 from 850
    break;
    case 3:
    //Serial.println("Pos. 3");
    pwm = 400;
    break;
    case 4:
    //Serial.println("Pos. 4");
    pwm = 235;
    break;
    }
    for(pulseCount = 0; pulseCount < 20; pulseCount++) { // Adjust Pan Servo and Read USR
    digitalWrite(PingServoPin, HIGH);
    delayMicroseconds(pwm * 2);
    digitalWrite(PingServoPin, LOW);
    readPing();
    delay(20);
    }
    distance = ((float)ultrasoundValue * CmConstant); // Calculate Distance in Cm
    if(distance > oldDistance) { // If the Newest distance is longer, replace previous reading with it
    oldDistance = distance;
    task = i; // Set task equal to Pan Servo Position
    }
    }
    distance = 50; // Prevents Scan from Looping
    switch(task) { // Determine which task should be carried out
    case 0: // Center was clearest
    x = 28;
    PLval = (850);
    PRval = (850);
    Go();
    break;
    case 1: // 90 degrees Left was Clearest
    x = 14;
    PLval = (650);
    PRval = (650);
    Go();
    break;
    case 2: // 45 degrees left
    x = 7;
    PLval = (650);
    PRval = (650);
    Go();
    break;
    case 3: // 45 degrees right
    x = 7;
    PLval = (850);
    PRval = (850);
    Go();
    break;
    case 4: // 90 degrees right
    x = 14;
    PLval = (850);
    PRval = (850);
    Go();
    break;
    }
    }

    void BrowUP()
    {
    myservo.attach(11);
    pos = 0;
    myservo.write(pos);
    delay(500);
    BrowDOWN();
    delay(50);
    myservo.detach();
    return;
    }
    void BrowDOWN()
    {
    myservo.attach(11);
    pos = 40;
    myservo.write(pos);
    delay(50);
    myservo.detach();
    return;
    }

    // End Robot Code

    Thanks for your help.
  • MovieMakerMovieMaker Posts: 502
    edited 2009-08-16 17:46
    Sorry, I gave you the wrong version:

    #include <MegaServo.h>
    MegaServo myservo;
    // Begin Robot Code
    //int micVal;
    //int cdsVal;
    int irLval; // Left IR
    int irCval; // Center IR
    int irRval; // Right IR
    int i; // Generic Counter
    int x; // Generic Counter
    int PLval; // Pulse Width for Left Servo
    int PRval; // Pulse Width for Right Servo
    int cntr; // Generic Counter Used for Determining amt. of Object Detections
    int counter; // Generic Counter
    int clrpth; // amt. of Milliseconds Of Unobstructed Path
    int objdet; // Time an Object was Detected
    int task; // Routine to Follow for Clearest Path
    int pwm; // Pulse Width for Pan Servo
    boolean add; // Whether to Increment or Decrement PW Value for Pan Servo
    int distance; // Distance to Object Detected via Ultrasonic Ranger
    int oldDistance; // Previous Distance Value Read from Ultrasonic Ranger

    float scale = 1.9866666666666666666666666666667; // *Not Currently Used*

    int LeftPin = 6; // Left Servo
    int RightPin = 9; // Right Servo
    int PingServoPin = 5; // Pan Servo
    int irLPin = 0; // Analog 0; Left IR
    int irCPin = 1; // Analog 1; Center IR
    int irRPin = 2; // Analog 2; Right IR
    int ultraSoundSignal = 7; // Ultrasound signal pin
    int val = 0; // Used for Ultrasonic Ranger
    int ultrasoundValue = 0; // Raw Distance Val
    int oldUltrasoundValue; // *Not used*
    int pulseCount; // Generic Counter
    int timecount = 0; // Echo counter
    int ledPin = 13; // LED connected to digital pin 13
    int pos = 0;
    int SPKR = 4;

    #define BAUD 9600
    #define CmConstant 1/29.034

    void setup() {
    myservo.attach(11);
    pos = 40;
    myservo.write(pos);
    delay(150);
    myservo.detach();
    Serial.begin(9600);
    pinMode(SPKR, OUTPUT);
    pinMode(ledPin, OUTPUT);
    pinMode(LeftPin, OUTPUT);
    pinMode(RightPin, OUTPUT);
    pinMode(PingServoPin, OUTPUT);
    pinMode(irLPin, INPUT);
    pinMode(irCPin, INPUT);
    pinMode(irRPin, INPUT);
    // Beep!
    {
    for (int i = 0; i<500; i++) { // generate a 1KHz tone for 1/2 second
    digitalWrite(SPKR, HIGH);
    delayMicroseconds(400);
    digitalWrite(SPKR, LOW);
    delayMicroseconds(400);
    }
    for(i = 0; i < 20; i++) {
    digitalWrite(PingServoPin, HIGH);
    delayMicroseconds(655 * 2);
    digitalWrite(PingServoPin, LOW);
    delay(20);
    }
    ultrasoundValue = 600;
    i = 0;
    }
    }
    void loop()
    {
    Look();
    Go();
    }
    void Look() {
    irLval = analogRead(irLPin);
    irCval = analogRead(irCPin);
    irRval = analogRead(irRPin);
    if(irLval > 200) {
    BrowUP();
    PLval = 850;
    PRval = 820;
    x = 5;
    cntr = cntr + 1;
    clrpth = 0;
    objdet = millis();
    }
    else if(irCval > 200) {
    BrowUP();
    PLval = 850;
    PRval = 820;
    x = 10;
    cntr = cntr + 1;
    clrpth = 0;
    objdet = millis();
    }
    else if(irRval > 200) {
    BrowUP();
    PLval = 650;
    PRval = 620;
    x = 5;
    cntr = cntr + 1;
    clrpth = 0;
    objdet = millis();
    }
    else {
    x = 1;
    PLval = 850;
    PRval = 620;
    counter = counter + 1;
    clrpth = (millis() - objdet);
    if(add == true) {
    pwm = pwm + 50;
    }
    else if(add == false) {
    pwm = pwm - 50;
    }
    if(pwm < 400) {
    pwm = 400;
    add = true;
    }
    if(pwm > 950) {
    pwm = 950;
    add = false;
    }
    digitalWrite(PingServoPin, HIGH);
    delayMicroseconds(pwm * 2);
    digitalWrite(PingServoPin, LOW);
    delay(20);
    readPing();
    if(ultrasoundValue < 150) { // this value is the closeness of PING will get.
    cntr = cntr + 1;
    switch(pwm) {
    case 400:
    x = 7;
    PLval = 650;
    PRval = 650;
    Go();
    break;
    case 500:
    x = 10;
    PLval = 650;
    PRval = 650;
    Go();
    break;
    case 600:
    x = 14;
    PLval = 850;
    PRval = 850;
    Go();
    break;
    case 700:
    x = 10;
    PLval = 850;
    PRval = 850;
    Go();
    break;
    case 950:
    x = 7;
    PLval = 850;
    PRval = 850;
    Go();
    break;
    }
    }
    }
    if(cntr > 25 && clrpth < 2000) {
    clrpth = 0;
    cntr = 0;
    Scan();
    }
    }
    void Go() {
    for(i = 0; i < x; i++) {
    digitalWrite(LeftPin, HIGH);
    delayMicroseconds(PLval * 2);
    digitalWrite(LeftPin, LOW);
    digitalWrite(RightPin, HIGH);
    delayMicroseconds(PRval * 2);
    digitalWrite(RightPin, LOW);
    delay(20);
    }
    }
    void readPing() { // Get Distance from Ultrasonic Ranger
    timecount = 0;
    val = 0;
    pinMode(ultraSoundSignal, OUTPUT); // Switch signalpin to output
    digitalWrite(ultraSoundSignal, LOW); // Send low pulse
    delayMicroseconds(2); // Wait for 2 microseconds
    digitalWrite(ultraSoundSignal, HIGH); // Send high pulse
    delayMicroseconds(5); // Wait for 5 microseconds
    digitalWrite(ultraSoundSignal, LOW); // Holdoff
    pinMode(ultraSoundSignal, INPUT); // Switch signalpin to input
    val = digitalRead(ultraSoundSignal); // Append signal value to val
    while(val == LOW) { // Loop until pin reads a high value
    val = digitalRead(ultraSoundSignal);
    }
    while(val == HIGH) { // Loop until pin reads a high value
    val = digitalRead(ultraSoundSignal);
    timecount = timecount +1; // Count echo pulse time
    }
    ultrasoundValue = timecount; // Append echo pulse time to ultrasoundValue
    // Lite up LED if any value is passed by the echo pulse
    if(timecount > 0){
    digitalWrite(ledPin, HIGH);
    }
    }
    void Scan() { // Scan for the Clearest Path
    oldDistance = 30;
    task = 0;
    for(i = 1; i < 5; i++) {
    switch(i) {
    case 1:
    //Serial.println("Pos. 1");
    pwm = 1125; /// incr. by 100 from 1085
    break;
    case 2:
    //Serial.println("Pos. 2");
    pwm = 850; //// increased by 100 from 850
    break;
    case 3:
    //Serial.println("Pos. 3");
    pwm = 400;
    break;
    case 4:
    //Serial.println("Pos. 4");
    pwm = 235;
    break;
    }
    for(pulseCount = 0; pulseCount < 20; pulseCount++) { // Adjust Pan Servo and Read USR
    digitalWrite(PingServoPin, HIGH);
    delayMicroseconds(pwm * 2);
    digitalWrite(PingServoPin, LOW);
    readPing();
    delay(20);
    }
    distance = ((float)ultrasoundValue * CmConstant); // Calculate Distance in Cm
    if(distance > oldDistance) { // If the Newest distance is longer, replace previous reading with it
    oldDistance = distance;
    task = i; // Set task equal to Pan Servo Position
    }
    }
    distance = 50; // Prevents Scan from Looping
    switch(task) { // Determine which task should be carried out
    case 0: // Center was clearest
    x = 28;
    PLval = (850);
    PRval = (850);
    Go();
    break;
    case 1: // 90 degrees Left was Clearest
    x = 14;
    PLval = (650);
    PRval = (650);
    Go();
    break;
    case 2: // 45 degrees left
    x = 7;
    PLval = (650);
    PRval = (650);
    Go();
    break;
    case 3: // 45 degrees right
    x = 7;
    PLval = (850);
    PRval = (850);
    Go();
    break;
    case 4: // 90 degrees right
    x = 14;
    PLval = (850);
    PRval = (850);
    Go();
    break;
    }
    }

    void BrowUP()
    {
    myservo.attach(11);
    pos = 0;
    myservo.write(pos);
    delay(500);
    BrowDOWN();
    return;
    }
    void BrowDOWN()
    {
    myservo.attach(11);
    pos = 40;
    myservo.write(pos);
    delay(120);
    myservo.detach();
    return;
    }

    // End Robot Code
  • SRLMSRLM Posts: 5,045
    edited 2009-08-16 19:53
    Try commenting out the three lines where you call "BrowUP". From the function, it appears that brow up takes about 3/4 of a second, while the rest of the code takes maybe 1/4 (in cases where there is a clear spot forward). Add them together, and you get a dramatic slow down.

    I've never programmed a uC in C, but I do alot of C++ at school so some of the general algorithms are understandable.

    Some tips for better C*:
    1. Never use a global variable. It completely destroys the benefits of scope.
    2. Use lots of functions. Most functions should take parameters and return a value (dependent on the function purpose)
    3. Don't repeat yourself. For example, instead of controlling servos all throughout your code, use a single function, possibly with a header like "bool servo(int pin, int position)".
    4. Avoid the use of 'magic numbers'. Use constants instead.
    5. Encapsulate things that are likely to change in functions. For example, you may change the way you get distance readings. If it's in it's own function, you need to look in only one place.
    6. Use lots of comments. At a minimum, comment every functions parameters and return value.

    Anyway, HTH.

    *These are how many people like to write C (and other HLL), and it's how I like to do it. Some people will probably just say of these rules "That's dumb" or "That's conformist c**p". They probably work harder than they have to by being stubborn.
  • MovieMakerMovieMaker Posts: 502
    edited 2009-08-16 20:22
    Thanks for the comment.
Sign In or Register to comment.