Melhorando o uso do STL Vector

Eu uso bastante o STL (Standard Template Library) do C++. Ele está disponível em diversas plataformas, é rápido e é (relativamente) fácil de aprender. As vezes, seus desenvolvedores tomam atitudes conservadoras: só recentemente o STL incluiu uma estrutura de dados de tabela hash padrão ( com C++11). No entanto, usar STL é muito mais seguro do que lidar diretamente com ponteiros.

Eu uso o template em quase todo o meu software C++. Essencialmente, você pode usá-lo sempre que precisar de uma matriz dinâmica. Neste post escrevo sobre o uso de vectors STL, porém, você deve saber usá-los corretamente, se você precisa de velocidade!

Ao usar um vector em código de alto desempenho, é preciso estar ciente de vários fatores importantes. Por exemplo, a capacidade (uso de memória) de um vector nunca vai diminuir, mesmo se você chamar o método “clear”, a menos que você use o método de “swap”. Na minha opinião, o que torna difícil para liberar memória foi uma decisão infeliz de projeto. Outro problema com o template é que sempre que você copiar um “vector”, você copia todos os dados que ele contém. Mais uma vez, a fim de evitar esse problema, você deve usar o método “swap”.

Mas um problema complicado com vectors STL é que existem muitas maneiras de construí-los. Suponha que eu queira criar uma matriz em C++ que contém os números de 0 a N em ordem crescente. Então eu quero calcular a soma destes valores. Ouvi dizer que os matemáticos possuem com uma fórmula para este problema :), mas o microprocessador Intel não sabe disso.

A abordagem convencional usada pela maioria dos programadores é de alocar memória usando o comando new do C++:


int * bigarray = new int[N];
for(unsigned int k = 0; k<N; ++k)
bigarray[k] = k;
int sum = total(bigarray,N);
delete [] bigarray;
return sum;

Ou, você pode fazer o mesmo usando STL:


vector bigarray(N);
for(unsigned int k = 0; k<N; ++k)
bigarray[k] = k;
int sum = total(bigarray,N);
return sum;

É mais cômodo usar a última abordagem, porque você não precisa se lembrar de liberar a memória alocada. Há um preço a pagar no entanto, porque quando você constrói o vector desta forma, a memória é inicializada com zero.

Você pode fazer isso usando STL puro, com o método push_back:


vector bigarray;
for(unsigned int k = 0; k<N; ++k)
bigarray.push_back(k);
int sum = total(bigarray,N);
return sum;

We can improve the push_back method by using the fact that we know ahead of time how big the array will be. Thus, we can reserve the memory before the push_backs.
Podemos melhorar o método push_back, usando o fato de que sabemos de antemão o quão grande a matriz será. Assim, podemos reservar a memória antes de chamar os push_backs.


vector bigarray;
bigarray.reserve(N);
for(unsigned int k = 0; k<N; ++k)
bigarray.push_back(k);
int sum = total(bigarray,N);
return sum;
It is likely to be slightly faster.

Então, qual é o resultado disto? No meu desktop Intel Core i7, recebo os seguintes números de ciclos de CPU por inteiro processados​​:

método usado  ciclos por inteiro processado
C++ new 8.5
STL vector 8.9
push_back 20.6
reserve + push_back 12.6

Como de costume, meu código esta gratuitamente disponível neste link

Note que você pode enganar e obter a mesma velocidade que um C + + novo, construindo o vetor vazio, reservando a memória (reserva) e nunca redimensionamento o tamanho da matriz. Isto está fora das especificações padrão e pode ser perigoso, mas poupa-lhe até a metade de um ciclo de CPU por inteiro.

Concluindo, usar vectors STL pode ser muito rápido mas se você usá-los para armazenar inteiro, o uso do método push_back pode ser reltivamente caro.

Artigo original: http://lemire.me/blog/archives/2012/06/20/do-not-waste-time-with-stl-vectors/

Reading and Saving an Array of Structures with Objective-C

Hi,

Today I’m reading a good book called Pragmatic Programmer, and in this book there are some challenges. One is about how to save a simple “data base” record using binary data in you preferred programming language, so I decided do this using Objective>-C. The challenge is very simple, it involves to write a name and a phone number of your contacts.

For me to acomplish this task,  I need to create a structure comprised of two fields (name and phone). See code bellow:

typedef struct
{
  char name[255];
  char phone[11];
} User;

Now, you must create a vector of User and populate it.

User users[2] = {
  {"Sergio Vieira>\0", "(00)123456\0"},
  {"Alexandra Vieira\0", "(01)987654\0"}
};

After that, you must to create a  NSData object which is typically used for data storage.

NSData *data = [NSData dataWithBytes:&users length:sizeof(users)];

The method dataWithBytes:lenght creates and returns a data object containing a given number of bytes copied from a given buffer (Reference).

To write the contact list I decided to use a NSUserDefaults class which provide us a interface to easily save data in the system.

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

[userDefaults setObject:data forKey:@"users"];
[userDefaults synchronize];

The methods setObject:forKey: sets the value of the specified default key in the standard application domain (Reference)

With this, all data is saved. To read the sctructure you must to load NSData using NSUserDefaults.

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSData *data = [userDefaults objectForKey:@"users"];
User records[2];

[data getBytes:&records length:sizeof(records)];

and now you can show all stored values.

for (NSUInteger i = 0; i < 2; i++)
{
  printf("Name:%s Phone:%s\n", records[i].name, records[i].phone);
}

That’s all. 🙂

Compiling LDasm in Ubuntu 12.04 amd64

Hi Folks,
In this post, I’ll show you how to compile and install the LDasm 0.04.53 on ubuntu 12.04 amd64. Firstly, you will need to download a compressed ldasm file in this link http://freecode.com/projects/ldasm.

Before you compile, you’ll need change some code in ptrace/ptrace.c .

  1. Change linux/user.h to sys/user.h
  2. Change typedef enum { FALSE = 0,TRUE } Bool; to typedef enum { False = 0,True } Bool;
  3. Change all instances of _cooked_size to size
  4. Change all instances of eip to rip

In ptrace/Makefile

Change COPTS to COPTS   = -W -Wall -g
Change LIBS to LIBS    = -lbfd -liberty

and finally, type

$ make

$ sudo make install

😀

Aprendendo Objective-C – Parte 5

Projetando uma Interface de Classe

A sintaxe do Objective-C para criar uma classe é muito simples. Ela geralmente vem em duas partes.
A interface de classe geralmente vem armazenada no arquivo ClassName.h, e nela podem ser definidas variáveis de instância e métodos públicos.A implementação da classe fica no arquivo ClassName.m onde ficam o código destes métodos. Lá também podem existir métodos privados que não podem ser acessados pelos clientes da classe.Abaixo vemos como uma interface se parece. A classe é chamada Photo, portanto o nome do arquivo deve ser Photo.h:
#import <Cocoa/Cocoa.h> 

@interface Photo : NSObject { 
NSString* caption; 
NSString* photographer; 
} 
@end
Primeiro, importamos a biblioteca Cocoa.h, para podermos acessar todas as classe básicas para o aplicativo Cocoa. A diretiva #import automaticamente impede que a bliblioteca seja incluída várias vezes.

A palavra reservada @interface indica o início da delcaração da classe Photo. O dois pontos especifica a superclasse, neste caso NSObject.

Entre as chaves, existem duas variáveis de instância: caption e photographer. Ambos do tipo NSString, mas elas podem ser qualquer tipo de objeto, incluindo id.

Finalmente, o símbolo @end finaliza a declaração da classe.

Adicionar Métodos

Vamos adicionar alguns getters para as variáveis de instância.
#import <Cocoa/Cocoa.h> 
@interface Photo : NSObject { 
  NSString* caption; 
  NSString* photographer; 
} 
  - caption; 
  - photographer;
@end

Lembre-se, os métodos do Objective-C tipicamente dispensão o prefixo “get”. Um traço simples antes do nome do método significa que ele é um método de instância. Já um + antes do nome do método significa que ele é um método de classe.

Por padrão, o compilador assume que o retorno do método é um objeto id, e que todos os valores de entrada são do tipo id. O Código acima é tecnicamente correto, mas não é comum. Vamos adicionar os tipos específicos para os valores de retorno.

#import <Cocoa/Cocoa.h> 

@interface Photo : NSObject { 
  NSString* caption; 
  NSString* photographer; 
} 
  - (NSString*) caption;
   - (NSString*) photographer;
@end
Vamos adicionar os “setters“:
#import <Cocoa/Cocoa.h> 

@interface Photo : NSObject { 
  NSString* caption; 
  NSString* photographer; 
} 
  - (NSString*) caption; 
  - (NSString*) photographer; 
  - (void) setCaption: (NSString*)input; 
  - (void) setPhotographer: (NSString*)input; 
@end
Setters” não precisam de um valor de retorno, portanto vamos especificá-los como sendo do tipo void.

Aprendendo Objective-C – Parte 4

Gerenciamento Básico de Memória

Se você está escrevendo uma aplicação para o Mac OS X, você tem a opção de tivar o garbage collection. Em geral, isto significa que você não tem que se preocupar com o gerenciamento de memória a não ser que você precise de algo mais complexo.
Entretanto, você pode nem sempre está trabalhando em um ambiente que suporta o garbage collection. Neste caso, você precisa saber alguns conceitos básicos.
Se você criar um objeto utilizando o alloc, você precisa liberar (release) o objeto depois. Você não deve explicitamente liberar um objeto autorelease pois sua aplicação irá apresentar um mal funcionamento.
Veja estes dois exemplos:
// string1 will be released automatically 
NSString* string1 = [NSString string]; 
// must release this when done 
NSString* string2 = [[NSString alloc] init]; 
[string2 release];
Neste tutorial, você pode assumir que um objeto automático irá ser desalocado da memória quando a função atual terminar.
Existem mais coisas para aprender sobre gerenciamento de memória, mas isto irá fazer mais sentido depois que aprendermos mais alguns conceitos da linguagem.

Aprendendo Objective-C – Parte 3

Criando Objetos

Existem duas formas principais de criar um objeto. A primeira você já nos posts anteriores.

NSString* myString = [NSString string];
Esta é a forma mais conveniente de fazer isto. Neste caso, você está criando um objeto autorelease, no qual veremos mais detalhes depois. Em muito casos, ao meu ver, você deve criar um objeto de forma manual.
NSString* myString = [[NSString alloc] init];
Esta é uma chamada aninhada de método. A primeira é o método alloc chamado através de NSString. Esta é uma chamada relativamente de baixo nível na qual reserva um espaço de memória e instancia um objeto.
A segunda é uma chamada ao método init do novo objeto. A implementação de init geralmente realiza um ajuste básico no objeto, como criar as variáveis de instância. Os detalhes disto não precisam ser conhecidos por você como cliente da classe.
Em alguns casos, você pode usar uma versão diferente de init, no qual toma um valor de entrada:
NSNumber* value = [[NSNumber alloc] initWithFloat:1.0];

Sincronizando Legenda e Fala

Olá a todos,

Tenho trabalhado em um projeto para Iphone, e neste projeto vou precisar sincronizar um texto com uma narração. Tive a ideia de criar um aplicativo em java que me ajudasse durante esse processo. Passei esse fim de semana programa tal aplicativo e daí surgiu o Clacket. Seu funcionamento é bastante simples. Você basicamente digita uma frase e especifica quanto tempo ela permanece visível. Quando tiver feito todos os ajuster de tempo e tiver clicado em iniciar, as frases aparecerão ao mesmo tempo que o aplicativo grava o que for dito no microfone, desta forma a aplicação vai sincronizar automaticamente o texto a fala. Este é um projeto opensource e ele está hospedado no github. Caso queira acompanhar seu desenvolvimento, aqui está o link https://github.com/sergiosvieira/Clacket

Valeu…