Artigos com o marcador C++

Configurando ambiente de desenvolvimento C++ no Windows com Eclipse e MinGW

O Eclipse é uma das melhores IDEs de desenvolvimento Java no mercado. O que pouca gente sabe, é que ela também pode ser usada para desenvolvimento de aplicações utilizando o C++. Nesse pequeno tutorial, mostrarei como instalar o compilador C++ para Windows (MinGW) e utilizar o Eclipse para trabalhar com esse compilador.

O compilador MinGW (Minimalist GNU for Windows) é uma versão portada para Microsoft Windows do conjunto de ferramentas GNU. Este software inclui um conjunto de arquivos cabeçalho para a API do Windows que permite aos desenvolvedores usar o GCC para criar programas nativos em Windows sem precisar contar com uma emulação em tempo real de um sistema Unix-like.

Ambiente usado nesse tutorial:

  • Windows XP SP2
  • Eclipse 3.4 – Ganymede C++

O primeiro passo é baixar o Eclipse para C++. Para isso, vá ao site oficial do Eclipse (http://www.eclipse.org), clique em “Download Eclipse” e baixe a última versão do “Eclipse IDE for C/C++ Developers“. O Eclipse vem em uma pacote ZIP (quando Windows) com aproximadamento 68MB. Feito o download do Eclipse, descompacte o arquivo ZIP. Agora vamos ao próximo passo.

Nesse segundo passo, vamos baixar o MinGW, que é o compilador que utilizaremos. Acessem o site do MinGW (http://www.mingw.org), vá em “Downloads” e baixe a última versão do “Automated MinGW Installer“. Enquanto esse artigo esta sendo escrito, a última versão é a MinGW 5.1.4 de 26/04/2008. O arquivo é pequeno porque toda a instalação será feita online. Ele baixará todos os arquivos necessários na hora da instalação.

Existe alguns detalhes para se instalar o MinGW. Duplo clique no instalador e vamos começar a instalação. Você deverá estar conectado a Internet para instalar o MinGW com sucesso. Na primeira tela, clique em “Next“. Na segunda, marque a opção “Download and install“, igual na figura abaixo.

mingw1

Depois clique em “I Agree” para aceitar a licensa GPL e na tela de escolha de pacote (Choose Package), marque a opção “Current“, para instalar a versão estável atual do MinGW.

  • Previous: Versão estável anterior;
  • Current: Versão atual estável;
  • Candidate: Versão futura porém instável;

mingw2

Na escolha de componentes (Choose Components), você deverá obrigatoriamente marcar as opções:

  • MinGW base tools;
  • g++ compiler

As outras opções (g77 compiler, Ada compiler…) são opcionais. Elas não são necessárias para o que pretendemos fazer com esse tutotial. Instale se você quiser.

mingw3

Clique em “Next” e escolha o diretório de instalação. O diretório padrão e recomendado é o “C:\MinGW“. Avance mais uma vez e o instalador irá começar a fazer o download dos componentes e a instalação dos mesmos.

mingw4

Após terminar, finalize o instalador e abra o Eclipse (que você descompactou no primeiro passo). Para rodar o Eclipse você irá precisar da JRE instalada. Caso você não tenha a JRE, basta fazer o download aqui: http://java.sun.com/javase/downloads/index.jsp. Selecione a opção: “Java SE Runtime Environment (JRE)“.

Com o Eclipse aberto, teremos a seguinte tela:

eclipse1

Até aí tudo certo? Agora vamos criar o nosso projetinho C++ de exemplo para ver se está tudo OK e se a compilação está funcionando. Para criar o projeto faça: “File > New > C++ Project“. Digite um nome para seu projeto e escolha a opção “Hello World C++ Project“. Verifique se o MinGW aparece no Toolchains. Abaixo segue uma figura para você ter uma referência:

eclipse2

Agora clique em “Finish” e vamos testar. O projeto será criado e você pode fechar essa tela de “Welcome” que aparece quando se inicia o Eclipse. Repare que o projeto criado está no lado esquerdo do Eclipse. Essa janela onde fica os projetos é chamada de “Project Explorer“. Expanda seu projeto, vá na pasta src e duplo clique no arquivo “Teste.cpp“. Você terá um código igual ao abaixo:

//============================================================================
// Name        : Teste.cpp
// Author      : 
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================
 
#include <iostream>
using namespace std;
 
int main() {
	cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
	return 0;
}

Abaixo segue uma screenshot do Eclipse para você ter uma referência de como estarão as coisas nesse momento.

eclipse3

Agora vamos rodar o projeto. Para compilar e rodar esse projeto, clique no “Play” na barra de ferramentas lá em cima no Eclipse. Se tudo der certo, no console dele irá aparecer “!!!Hello World!!!“. Se aparecer, quer dizer que deu tudo certo e seu Eclipse está prontinho para ser usado como uma IDE de desenvovlimento C++.

eclipse4

Existem muitos livros e muitos tutoriais na Internet sobre C++. De uma pesquisada no Google sobre o assunto e você verá quanta informação você achará. Até a próxima e bons estudos.

Fontes:
Explicação sobre o MinGW: http://pt.wikipedia.org/wiki/MinGW

  • Share/Bookmark

Comparação de desempenho entre linguagens de programação

No dia 08/07/2008 o blog var/log/mind publicou uma comparação de desempenho entre algumas linguagens de programação. As linguagens testadas pelo blog foram C++, JAVA, Ruby, JRuby, Python, Jython, Groovy e PHP. Esse tema gerou até um bafafá na blogosfera nacional e internacional.

A tipo de benchmark feito pelo é blog foi bem simples e baseado em um pedaço de lógica onde é medido o tempo de cada iteração num total de 100000 iterações.

O mais espantoso foi que JAVA obteve um desempenho melhor do que C++. Esse resultado me deixou com uma pulga atrás da orelha porque sempre acreditei (mas nunca havia testado) de que C++ por ser somente compilado seria bem mais rápido do que JAVA que é compilado e interpretado pela JVM.

Então resolvi fazer o mesmo teste que o blog var/log/mind fez. Utilizei os mesmos códigos disponibilizados por ele e rodei eles em minha máquina. Somente não testei Python, Jython e o Groovy.

Ambiente de Testes

Meu ambiente de testes difere do ambiente de testes do var/log/mind (veja a tabela mais abaixo), assim como versões de compiladores e interpretadores. Abaixo segue o meu ambiente de testes e mais um pouco abaixo as versões dos compiladores e interpretadores usados no teste.

Meu ambiente:

  • Processador: AMD 4200+ X2 64 Bits
  • Memória: 3GB RAM
  • SO: Windows XP SP2 Professional

As diferenças entre o ambiente de teste original do var/log/mind e o meu ambiente de teste:

MeuPost.com var/log/mind
Processador AMD 4200+ X2 64 Bits Intel® Core™ Duo CPU T2600 @ 2.16GHz
Memória 3GB RAM 2GB
SO: Windows XP SP2 Professional Ubuntu Gutsy Gibbon 7.10

Compiladores e Interpretadores usados:

  • C++: MinGW32 GCC: 3.4.2
  • JAVA 1.6
  • Ruby 1.8.6-26
  • JRuby 1.1
  • PHP 5.2.3

Teste:

Para realizar o teste rodei 5 vezes o código de cada linguagem diferente e anotei todos os resultados em nanossegundos. Depois tirei a média dos resultados.

Resultados

Seguinte a tendência dos resultados, em meu ambiente JAVA também foi superior ao C++. Os resultados também mostraram que o Python está mais maduro que Ruby embora nas últimas versões do Ruby (1.9) o desempenho tenha melhorado muito.

Outro fato interessante é que o JRuby está também mais rápido que Ruby. Já o PHP mostra a força de sua maturidade e popularidade ganhando tanto do Ruby como do JRuby, isso em meu ambiente, porque no var/log/mind tanto o Ruby como o JRuby ganharam do PHP.

Acredito que esse desempenho superior do Ruby no var/log/mind está diretamente associado ao sistema operacional. O Ruby está rodando muito mais rápido em ambientes Linux do que em Windows.

Abaixo segue a tabela de resultados:

Iteração 1 Iteração 2 Iteração 3 Iteração 4 Iteração 5 Média Total
C++ 12000 12000 12000 12000 12000 12000 60000
Java 1509 1369 1384 1376 1385 1404,6 7023
Ruby 491990 493750 494690 493280 494840 444232 2468550
Jruby 244040 246360 243830 243450 246750 244886 1224430
PHP 125200 125030 124880 124890 124900 124980 624900
1 segundo = 1000000 microssegundo = 1000000000 nanossegundo

Para facilitar a visualização dos resultados, abaixo segue um gráfico com o resultado do teste:

Desempenho das Linguagens de Programação

Códigos

Abaixo segue os códigos utilizados nos testes. São os mesmos do var/log/mind com uma única diferença no código C++. Como o var/log/mind usou o Linux, ele usou a função gettimeofday(), em Windows essa função não existe, então eu como não sou um programador C++, achei essa função no Blog OpenAsthra e coloquei no código.

Todos os outros códigos são exatamente iguais.

C++

#include &lt;time.h&gt;
#include &lt;windows.h&gt;
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;sys/time.h&gt;
 
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
#else
  #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
#endif
 
struct timezone 
{
  int  tz_minuteswest; /* minutes W of Greenwich */
  int  tz_dsttime;     /* type of dst correction */
};
 
int gettimeofday(struct timeval *tv, struct timezone *tz)
{
  FILETIME ft;
  unsigned __int64 tmpres = 0;
  static int tzflag = 0;
 
  if (NULL != tv)
  {
    GetSystemTimeAsFileTime(&amp;ft);
 
    tmpres |= ft.dwHighDateTime;
    tmpres &lt;&lt;= 32;
    tmpres |= ft.dwLowDateTime;
 
    tmpres /= 10;  /*convert into microseconds*/
    /*converting file time to unix epoch*/
    tmpres -= DELTA_EPOCH_IN_MICROSECS; 
    tv-&gt;tv_sec = (long)(tmpres / 1000000UL);
    tv-&gt;tv_usec = (long)(tmpres % 1000000UL);
  }
 
  if (NULL != tz)
  {
    if (!tzflag)
    {
      _tzset();
      tzflag++;
    }
    tz-&gt;tz_minuteswest = _timezone / 60;
    tz-&gt;tz_dsttime = _daylight;
  }
 
  return 0;
}
 
#define TEST
#ifdef TEST
#endif
 
class Person
{
 
    public:
 
        Person(int count) : _next(NULL), _prev(NULL) { _count = count; }
        int shout(int shout, int nth)
        {
            if (shout &lt; nth) return (shout + 1);
            _prev-&gt;_next = _next;
 
            _next-&gt;_prev = _prev;
            return 1;
        }
        int count() { return _count; }
        Person* next() { return _next; }
        void next(Person* person) { this-&gt;_next = person ; }
        Person* prev() { return _prev; }
        void prev(Person* person) { this-&gt;_prev = person; }
    private:
        int _count;
        Person* _next;
        Person* _prev;
};
 
class Chain
{
    public:
        Chain(int size) : _first(NULL)
        {
            Person* current = NULL;
            Person* last = NULL;
            for(int i = 0 ; i &lt; size ; i++)
            {
                current = new Person(i);
                if (_first == NULL) _first = current;
                if (last != NULL)
                {
                    last-&gt;next(current);
                    current-&gt;prev(last);
                }
                last = current;
            }
            _first-&gt;prev(last);
            last-&gt;next(_first);
        }
        Person* kill(int nth)
        {
            Person* current = _first;
            int shout = 1;
            while(current-&gt;next() != current)
            {
                Person* tmp = current;
                shout = current-&gt;shout(shout,nth);
                current = current-&gt;next();
                if (shout == 1)
                {
                    delete tmp;
                }
            }
            _first = current;
            return current;
        }
        Person* first() { return _first; }
    private:
        Person* _first;
};
 
int main(int argc, char** argv)
{
    int ITER = 100000;
    Chain* chain;
    struct timeval start, end;
    gettimeofday(&amp;start,NULL);
    for(int i = 0 ; i &lt; ITER ; i++)
    {
        chain = new Chain(40);
        chain-&gt;kill(3);
        delete chain;
    }
    gettimeofday(&amp;end,NULL);
    fprintf(stdout,"Time per iteration = %d microsecondsnr", (((end.tv_sec - start.tv_sec) * 1000000) + (end.tv_usec - start.tv_usec)) / ITER);
    //fprintf(stdout,"Last man standing is %dnr", (chain-&gt;first()-&gt;count() + 1));
    return 0;
}
 
}

JAVA:

package com.dnene.josephus;
 
public class Chain {
 
	private Person first = null;
 
	public Chain(int size) {
		Person last = null;
		Person current = null;
 
		for (int i = 0; i &lt; size; i++) {
			current = new Person(i);
 
			if (first == null)
				first = current;
 
			if (last != null) {
				last.setNext(current);
				current.setPrev(last);
			}
 
			last = current;
		}
 
		first.setPrev(last);
		last.setNext(first);
	}
 
	public Person kill(int nth) {
		Person current = first;
		int shout = 1;
 
		while (current.getNext() != current) {
			shout = current.shout(shout, nth);
			current = current.getNext();
		}
 
		first = current;
 
		return current;
	}
 
	public Person getFirst() {
		return first;
	}
 
	public static void main(String[] args) {
 
		int ITER = 100000;
		long start = System.nanoTime();
 
		for (int i = 0; i &lt; ITER; i++) {
			Chain chain = new Chain(40);
			chain.kill(3);
		}
 
		long end = System.nanoTime();
 
		System.out.println("Time per iteration = " + ((end - start) / (ITER))
				+ " nanoseconds.");
	}
}
 
package com.dnene.josephus;
 
public class Person {
 
	int count;
	private Person prev = null;
	private Person next = null;
 
	public Person(int count) {
		this.count = count;
	}
 
	public int shout(int shout, int deadif) {
		if (shout &lt; deadif)
			return (shout + 1);
 
		this.getPrev().setNext(this.getNext());
		this.getNext().setPrev(this.getPrev());
 
		return 1;
	}
 
	public int getCount() {
		return this.count;
	}
 
	public Person getPrev() {
		return prev;
	}
 
	public void setPrev(Person prev) {
		this.prev = prev;
	}
 
	public Person getNext() {
		return next;
	}
 
	public void setNext(Person next) {
		this.next = next;
	}
}

Ruby / JRuby

class Person
    attr_reader :count, :prev, :next
    attr_writer :count, :prev, :next
 
    def initialize(count)
        #puts 'Initializing person : ' + count.to_s()
        @count = count
        @prev = nil
        @next = nil
    end
 
    def shout(shout, deadif)
        if shout &lt; deadif
            return shout + 1
        end
        @prev.next = @next
        @next.prev = @prev
        return 1
    end
end      
 
class Chain
    attr_reader :first
    attr_writer :first
 
    def initialize(size)
        @first = nil
        last = nil
        for i in (1..size)
            current = Person.new(i)
            if @first == nil
                @first = current
            end
            if last != nil
                last.next = current
                current.prev = last
            end
            last = current
        end
        @first.prev = last
        last.next = @first
    end
 
    def kill(nth)
        current = @first
        shout = 1
        while current.next != current
            shout = current.shout(shout,nth)
            current = current.next
        end
        @first = current
        return current
    end
end
 
ITER=100000
start = Time.now
ITER.times { |i|
chain = Chain.new(40)
chain.kill(3)
}
ends = Time.now
puts 'Time per iteration = ' + ((ends - start) * 1000000 / ITER).to_s() + " microseconds"

PHP

&lt;?php
class Person
{   
    function __construct($c)
    {   
        $this-&gt;count = $c;
    }       
 
    function getPrev()
    {       
        return $this-&gt;prev; 
    }           
 
    function setPrev($pr)
    {   
        $this-&gt;prev = $pr;
    }   
 
    function getNext()
    {
        return $this-&gt;next;
    }
 
    function setNext($nxt)
    {
        $this-&gt;next = $nxt;
    }
 
    function shout($shout, $nth)
    {
        if ($shout &lt; $nth)
        {
            return $shout + 1;
        }
        $this-&gt;getPrev()-&gt;setNext($this-&gt;getNext());
        $this-&gt;getNext()-&gt;setPrev($this-&gt;getPrev());
        return 1;
    }
}
 
class Chain
{
    var $first;
 
    function __construct($size)
    {
        for($i = 0; $i &lt; $size ; $i++)
        {
            $current = new Person($i);
            if ($this-&gt;first == null) $this-&gt;first = $current;
            if ($last != null)
            {
                $last-&gt;setNext($current);
                $current-&gt;setPrev($last);
            }
            $last = $current;
        }
        $this-&gt;first-&gt;setPrev($last);
        $last-&gt;setNext($this-&gt;first);
    }
 
    function kill($nth)
    {
        $current = $this-&gt;first;
        $shout = 1;
        while($current-&gt;getNext() !== $current)
        {
            $shout =  $current-&gt;shout($shout,$nth);
            $current = $current-&gt;getNext();
        }
        $this-&gt;first = $current;
    }
}
 
$start = microtime(true);
$ITER = 100000;
for($i = 0 ; $i &lt; $ITER ; $i++)
{
    $chain = new Chain(40);
    $chain-&gt;kill(3);
}
$end = microtime(true);
printf("Time per iteration = %3.2f microsecondsnr",(($end -  $start) * 100000 / $ITER));
?&gt;

É isso pessoal.

Esse tema de desempenho sempre gera polêmica pois sempre há brechas e margens para discussão. Então, quem quiser debater sobre o assunto.

Até a próxima.

  • Share/Bookmark