0

Comment puis-je optimiser ce code? J'ai fait IPFilter et j'ai besoin de l'optimiser.Optimisation du code Java

package com.ipfilter; 

import java.util.HashMap; 
import java.util.Map; 

/** 
*  IPFilter 
* 
*  Loads given IP addresses to memory, so you can easily check if ip addres has been blocked 
*/ 

public class IPFilter { 
     private Map<Integer, IPFilter> filter = new HashMap<Integer, IPFilter>(); 

     /** 
     * Convert String ip address to Integer array and then calls add ip method 
     * @param ip 
     * @return 
     */ 
     public void addIP(String ip) 
     { 
       int[] numbers = convert(ip); 
       addIP(numbers, 0); 
     } 

     /** 
     * Convert String ip address to Integer array 
     * @param ip 
     * @return 
     */ 
     private int[] convert(String ip) { 
       String[] strings = ip.split("\\."); 
       int[] numbers = new int[strings.length]; 
       for(int i = 0; i < strings.length; i++) 
       { 
         numbers[i] = Integer.parseInt(strings[i]); 
       } 
       return numbers; 
     } 

     /** 
     * Add ip address to memory 
     * @param ip 
     * @param level 
     */ 
     private void addIP(int[] ip, int level) { 
       if(level < ip.length) 
       { 
         if (filter.containsKey(ip[level])) { 
           filter.get(ip[level]).addIP(ip, level + 1); 
         } else { 
           filter.put(ip[level], new IPFilter()); 
           filter.get(ip[level]).addIP(ip, level + 1); 
         } 
       } 
     } 

     /** 
     * Checks if ip address is in filter 
     * @param ip 
     * @return 
     */ 
     public boolean isBlocked(String ip) 
     { 
       return isBlocked(filter, convert(ip), 0); 
     } 

     /** 
     * Check if ip address is blocked 
     * @param list 
     * @param ip 
     * @param level 
     * @return 
     */ 
     private boolean isBlocked(Map<Integer, IPFilter> list, int[] ip, int level) 
     { 
       if(list.containsKey(ip[level])) 
       { 
         if(level < ip.length - 1) 
         { 
           return isBlocked(list.get(ip[level]).getList(), ip, level + 1); 
         } 
         else 
         { 
           return true; 
         } 
       } 
       else 
       { 
         return false; 
       } 
     }  

     /** 
     * Getter for list 
     * @return 
     */ 
     protected Map<Integer, IPFilter> getList() { 
       return filter; 
     } 
} 
+0

Que voulez-vous dire par « l'optimisation »? Avez-vous besoin de le faire fonctionner plus vite? Avez-vous besoin de le faire utiliser moins de mémoire? Ou voulez-vous simplement rendre le code plus court ou plus élégant? – Jesper

Répondre

9

Faites le profil de certains cas d'utilisation typiques et utilisez ces données pour déterminer les goulots d'étranglement des performances. ALORS, optimisez ce code. Sans vraiment savoir où se situe le problème de performance, vous pouvez passer beaucoup de temps et d'efforts à économiser des microsecondes.

2

Je ne sais pas exactement ce que vous essayez d'optimiser. Cependant, vous avez un couple de containsKey suivi de get. Une optimisation possible consiste à utiliser get et à comparer à null. Par exemple, au lieu de:

if (filter.containsKey(ip[level])) { 
     filter.get(ip[level]) 
} 

Effectuez les opérations suivantes:

IPFilter value = filter.get(ip[level]); 
if (value != null) { 
     value.addIp(...); 
} 

Mais je pense que le meilleur conseil que je peux vous donner est: utiliser un profileur. Si vous utilisez Eclipse, vérifiez TPTP.

2

Pas pour rien, mais une adresse IP est un entier de 4 octets comme il est généralement mis en œuvre. Pourquoi ne pas encoder à cela, et juste laisser:

int ipSrc = convertIpToInt(String ip); 
if (ipSrc == ipDest) { 
    /// 
} 

être votre comparaison.

Et pour IPv6, vous pouvez utiliser un long.

Ensuite, ce que je ferais probablement est d'utiliser java.net.Inet4Address et de les stocker dans un ensemble.

Puisque vous utilisez déjà une carte, pourquoi ne pas essayer une approche simpliste? Une implémentation intelligente à mi-chemin de Inet4Address.equals() ferait une comparaison d'entier, et non une comparaison de chaîne.

Bien sûr, cette méthode se décompose si vous voulez faire wildcarding ...: -/

+0

Je ne pense pas que cela tombe en panne pour les caractères génériques - au moins begin_with et ends_with peuvent être manipulés avec des opérations de masquage de bits dans le calcul hashCode. Utiliser un entier et/ou long serait beaucoup plus rapide que l'algorithme original. –