set
06
Escalabilidade segundo a wikipedia, é uma característica desejavel em todo sistema que indica sua habilidade de manipular uma porção crescente de trabalho de forma uniforme. Ou seja, se uma determinada aplicação foi projetada para realizar apenas 100 processos e derrepente há a necessidade de ampliação do processamento para 100.000, se esta aplicação for escalável, certamente não haverá problemas para a parte lógica do sistema (software). Escalabilidade é um termo muito amplo e engloba não somente o software, mas o nosso foco nesse post será apenas a parte lógica.Quando desenvolvemos uma aplicação sem o conhecimento da linguagem e metodologia utilizada ou sem um conhecimento básico de sistemas operacionais, carga de memória, algorítmos ou o que o processador irá fazer com um determinado trecho do seu código, podem surgir aplicativos que não são escaláveis e quando a demanda aumentar, você terá que refatorar seu código e possivelmente reescrever boa parte de seu aplicativo.
Para exemplificar, imagine que você necessite desenvolver uma solução que abra um arquivo no formato TXT de 60.000 linhas, procure por linhas que contenham a string "192.168.1.20" e escreva estas linhas em um novo arquivo:
public class AplicativoTXT {
public static void main(String[] args) {
File log = new File("access.log");
File nov = new File("access.log.bkp");
if (log.exists()) {
try {
String conteudo = "";
FileReader reader = new FileReader(log.getPath());
BufferedReader leitor = new BufferedReader(reader);
String linha;
int contador = 1;
while ((linha = leitor.readLine()) != null) {
if (linha.contains("192.168.1.20")){
conteudo += linha;
}
contador++;
}
BufferedWriter wr=new BufferedWriter(new FileWriter(nov));
writer.wr(conteudo);
wr.close();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}
}
Ok, este código cumpre com sua função de varrer um aquivo txt, encontrar linhas que contenha uma determinada string, separá-las em uma string denominada "conteudo" e então, através de um BufferedWriter, salvar o conteúdo no arquivo.
Agora entra a parte do conhecimento técnico da linguagem e de algorítimos de computação: Ao executar este código com um arquivo TXT com 60.000 linhas, ele com certeza levará mais de 15 minutos de execução se ele não apresentar uma StackOverflowError na tela por causa do consumo excessivo de memória e simplesmente não concluir a execução do código. Um desenvolvedor inexperiente ou que nunca passou pela necessidade de escalabilidade de seu aplicativo, certamente não notará a deficiência que esse código pode trazer.
Em java, a classe String é imutável, ou seja, ao concatenar um objeto do tipo String, é alocado na memória mais uma nova intância de String, e a variável deixa de apontar para o valor antigo e aponta para o novo valor, mantendo o valor antigo alocado na memória. O Garbage collector recolhe o lixo, mas não é garantido quando, isso pode saturar a memória, pois a cada loop, o tamanho necessário a ser alocado, aumenta, trazendo também lentidão ao processamento com essa brincadeira de alocar espaços na memória.
Para resolver este problema, criaram as classes StringBuilder e StringBuffer. Basicamente elas são Strings mutáveis. Ao invés de substituir ou concatenar o valor da variável, com o StringBuilder, simplesmente é chamado o métido .append(String) para concatenar um valor a variável. Foi colocado no projeto destas classes, métodos responsáveis pela alteração e modificação do conteúdo interno, sem que necessariamente um novo objeto seja criado. O algorítimo criado para esta realização foi desenvolvido para ser extremamente rápido, segundo diz o livro Effective Java, cerca de 9 vezes mais rápido para um bloco de 800 caracteres.
O código com a utilização do StringBuilder ficaria da seguinte maneira:
public class AplicativoTXT {
public static void main(String[] args) {
File log = new File("access.log");
File nov = new File("access_filtrado.log");
if (log.exists()) {
try {
StringBuilder conteudo = new StringBuilder();
FileReader reader = new FileReader(log.getPath());
BufferedReader leitor = new BufferedReader(reader);
String linha;
int contador = 1;
while ((linha = leitor.readLine()) != null) {
if (linha.contains("192.168.1.20")){
conteudo.append(linha);
conteudo.append("\n");
}
contador++;
}
BufferedWriter wr=new BufferedWriter(new FileWriter(nov));
writer.wr(conteudo.toString());
wr.close();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}
}