Java Performans etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
Java Performans etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

4 Ana Java Performans Anti Patterni, Spring Boot / Java örnekleri ile

Ana Performans Karşı-Örüntüleri. Bir performans problemi araştırırken, kusurunuzun hangi karşı-örüntüye en çok benzediğini kendinize sorun.



Gereksiz Başlatma: Daha büyük bir süreci başlatırken, sistem, zaten işlenmiş olan küçük bir sonucu tekrar işler. Birikmiş etkiler, ekstra CPU/RAM tüketimi ve/veya yavaşlamayı gerektirir; bunların hepsi önlenebilir. Küçük sonucu önbelleklemek ana panzehirdir.


Strateji/Algoritma Verimsizliği: Yanlış yapılandırılmış veya zayıf seçilmiş bir algoritma veya kodlama stratejisi performans sorunlarına neden olur. Bir strateji, bir kod tabanında kullanılan bir tekniktir ve bir algoritma, tek bir bileşeni uygulamak için kullanılan bir plandır.


Aşırı İşleme: Sistem gereksiz işler yapıyor. Bu işleri kaldırmak ölçülebilir performans faydası sağlar. Fazla veri almak ve çoğunun atılması, yanlış kaynak-yoğun kullanım durumunun yük testine dahil edilmesi gibi örnekler verilebilir.


Büyük İşleme Zorluğu: Büyük miktarda veriyi işlemeye ve fethetmeye çalışma. Böyle bir ihtiyacı olan çok az uygulama vardır, ancak mevcuttur. 4 milyar satır veriyi sorgulama, yavaş bir ağ üzerinden sürekli olarak 10MB veri transferi yapma vb.


Maalesef, bu ana karşı-örüntüler arasında örtüşme vardır, burada bir performans kusuru iki veya daha fazla farklı ana karşı-örüntüye uyabilir. 


"Gereksiz Başlatma" (Unnecessary Initialization) adı verilen bir yazılım anti-patronu detaylı olarak inceleniyor. Bu, genellikle kodun başlangıç aşamasında ortaya çıkan, CPU ve I/O yoğunluğu yüksek, verimsiz bir durumdur. Aynı işlemin gereksiz yere tekrar tekrar yapılması, ekstra yük oluşturur.

Bu anti-patronun tipik örnekleri şunlar olabilir:

XML şema dosyalarının (.xsd ve .xslt) her işlemde tekrar okunup ayrıştırılması, oysa bu tür dosyaların içeriği nadiren değişir.
Yetkilendirme, ürün, organizasyonel veri gibi sabit uygulama düzeyindeki verilerin sürekli olarak yeniden yüklenmesi.
Ağ bağlantılarının (TCP soketi gibi) veya veritabanı bağlantılarının her istekte yeniden oluşturulması.
Bu tür durumlar, performans problemlerine yol açabilir. Bunun yerine, veriler önbelleğe alınabilir veya yeniden kullanılabilir hale getirilebilir, böylece diskten veya ağ üzerinden gereksiz istekler en aza indirilir. Bu, uygulamanın genel performansını artıracaktır. İlgili kod örnekleri, yazarın GitHub reposunda bulunabilir.

Bu anti-patron, sıklıkla küçük I/O işlemlerinin yinelenmesi veya yanlış bir programlama dilinin kullanılmasıyla tanınabilir. "Gereksiz I/O işlemlerinden kaçınmak" klişe bir tavsiye olabilir, ancak bu durum, performans sorunlarının yaygın bir kaynağıdır. Bu nedenle, diske veya ağa yapılan gereksiz isteklerin en aza indirilmesine dikkat etmek önemlidir.

Aşağıda, "Gereksiz Başlatma" (Unnecessary Initialization) anti-paternini örneklemek için yaygın bir Java kod parçacı ve daha sonra bunu düzeltmek için nasıl optimize edilebileceği açıklanmaktadır.

Örnek: Gereksiz Başlatma
Bu örnekte, her seferinde aynı XSD dosyasını ayrıştırmak için XML Schema Factory'nin yeniden oluşturulduğu bir durumu ele alalım:

java
Copy code
public class UnnecessaryInitialization {
    public boolean validateXML(String xmlContent, String xsdPath) throws SAXException, IOException {
        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Schema schema = factory.newSchema(new File(xsdPath));
        Validator validator = schema.newValidator();
        validator.validate(new StreamSource(new StringReader(xmlContent)));
        return true; // Geçerli ise
    }
}
Bu kod, her çağrıldığında XSD dosyasını yeniden okur ve ayrıştırır, bu da gereksiz I/O maliyetine neden olur.

Doğru Yöntem: Önbelleğe Alma
Bu kodu optimize etmek için, Schema nesnesini önbelleğe alabiliriz. Schema nesnesi değişmediğinde yeniden oluşturulmasına gerek yoktur.

java
Copy code
public class OptimizedInitialization {
    private static Schema schema;

    static {
        try {
            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
            schema = factory.newSchema(new File("path/to/your.xsd")); // Yol sabitse
        } catch (SAXException e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    public boolean validateXML(String xmlContent) throws SAXException, IOException {
        Validator validator = schema.newValidator();
        validator.validate(new StreamSource(new StringReader(xmlContent)));
        return true; // Geçerli ise
    }
}
Bu durumda, Schema nesnesi yalnızca sınıf ilk yüklendiğinde oluşturulur. Bu, XML şemasının değişmediği varsayılarak, bu kodun daha etkili çalışmasına yardımcı olur.

Önbelleğe alma, ayrıştırma gibi pahalı işlemlerin gereksiz yinelenmesini önlemek için kullanılabilir. Bu örnek, gereksiz I/O maliyetini azaltmaya yardımcı olur ve kodun daha hızlı çalışmasını sağlar.


"Strateji/Algoritma Verimsizliği"(Strategy/Algorithm Inefficiency:) olarak adlandırılan ikinci ana anti-patron ele alınmaktadır. Bu anti-patron, iyi performans göstermeyen bir algoritma veya strateji seçimiyle ilgilidir. Ayrıca, yanlış algoritma yapılandırması veya parametreleme ile doğru algoritmanın seçilmesi de dahildir.
Bu durum, algoritmaların karmaşıklığının "Büyük O" notasyonu ile karşılaştırılmasından çok, daha basit ve yaygın işlerle ilgilidir. Çünkü çoğu şirket yazılımı, algoritma karmaşıklığından çok verinin bir noktadan diğerine taşınmasıyla ilgilenir.
Bu anti-patron, sadece algoritmalarla değil, aynı zamanda veri erişim stratejileri gibi stratejilerle de ilgilidir. Algoritmanın uygulanması genellikle tek bir yerde olurken, bir strateji, kodun sistemin dört bir yanına yayılması nedeniyle daha zor ayarlanabilir veya değiştirilebilir olabilir.
Erken geliştirme aşamasında performans testleri kullanmak, değiştirmesi maliyetli olan düşük performanslı bir kod stratejisine yatırım yapmaktan kaçınmaya yardımcı olabilir. Örneğin, 25'ten fazla veritabanı veya diğer arka uç isteği gerçekleştirmenin iyi performans gösterip göstermeyeceğini erken aşamada keşfedebilirsiniz.

Bu ana anti-patern, uygun olmayan bir algoritma veya strateji seçimi ile ilgilidir. Örnek olarak, veritabanına çok sayıda ayrı sorgu göndermek yerine, aynı verileri bir kezde almak için optimize edilmiş bir sorgu kullanma durumunu ele alalım.

Yanlış Strateji: Veritabanına Aşırı Sorgulama
Bu kod parçacığı, veritabanından belirli bir koşula uyan her ürünün ayrı ayrı alındığı bir durumu göstermektedir. Bu, veritabanına gereksiz yere çok sayıda sorgu gönderilmesine neden olabilir.

java
Copy code
public class InefficientStrategy {
    public List<Product> getProducts(Connection connection, List<Integer> productIds) throws SQLException {
        List<Product> products = new ArrayList<>();
        for (int productId : productIds) {
            PreparedStatement statement = connection.prepareStatement("SELECT * FROM products WHERE id = ?");
            statement.setInt(1, productId);
            ResultSet rs = statement.executeQuery();
            while (rs.next()) {
                products.add(new Product(rs.getInt("id"), rs.getString("name"), rs.getDouble("price")));
            }
        }
        return products;
    }
}
Doğru Strateji: Tek Sorguda Toplu Alma
Bunu düzeltmek için, aynı verileri tek bir sorguyla alabilecek bir SQL sorgusu kullanabiliriz. Bu, veritabanına yapılan I/O çağrılarını azaltır ve genel performansı artırır.

java
Copy code
public class EfficientStrategy {
    public List<Product> getProducts(Connection connection, List<Integer> productIds) throws SQLException {
        List<Product> products = new ArrayList<>();
        String joinedIds = productIds.stream().map(String::valueOf).collect(Collectors.joining(", "));
        String query = "SELECT * FROM products WHERE id IN (" + joinedIds + ")";
        Statement statement = connection.createStatement();
        ResultSet rs = statement.executeQuery(query);
        while (rs.next()) {
            products.add(new Product(rs.getInt("id"), rs.getString("name"), rs.getDouble("price")));
        }
        return products;
    }
}
Bu kod, bir kezde birden fazla ürün almak için SQL IN anahtar sözcüğünü kullanır, böylece tüm ürünler tek bir sorguyla alınabilir. Bu, I/O maliyetini önemli ölçüde azaltır ve uygulamanın performansını artırır.

Bu stratejinin doğru veya yanlış olduğunu belirtmek önemlidir. Yukarıdaki iki yaklaşımın hangisinin uygun olduğu, spesifik kullanım durumuna ve gereksinimlere bağlıdır. Ancak, genellikle, veritabanına yapılan gereksiz yere aşırı sorguları azaltmak, performansı önemli ölçüde artırabilir.



 "Aşırı İşleme"(Overprocessing) olarak adlandırılan üçüncü ana anti-patron tanıtılmaktadır. Bu anti-patron, yalnızca marjinal olarak geçerli olan kaynak yoğun kullanım senaryolarına yönelik yanlış girişimlerle ilgilidir.

Bir örnek, bir kullanıcının tek bir ekran dolusu veya web sayfası bilgisiyle yararlanabileceğinden daha fazla verinin işlenmesidir. 100 ms içinde yüklenmesi beklenen tek bir HTML tablosunda 50 sayfa veri beklemek gerçekçi değildir. Ancak, “sonraki sayfa” düğmesiyle 3 sayfa veri oldukça iyi performans gösterebilir.

Bu anti-patronun değerlendirilmesi bazı teknik uzmanlık gerektirse de, daha çok iş uzmanlığına dayalıdır. Hangi iş süreçlerinin üretimde kullanılacağını ve bunların kabaca yüzdeliklerini bilmek yararlı olacaktır.

Aşırı İşleme anti-patronuna sıkça neden olan bir durum, test veritabanlarının, üretimde hiçbir zaman bu kadar büyük veya karmaşık olmayan bazı "süper müşteriler" içermesidir.

Bu senaryonun bir yolu, yük testinizde yanlışlıkla yer alsa bile, kullanıcıların nadiren geçtiği belirli bir kod bölümü üzerinde çok zaman harcamanızdır. Bu zaman kaybıdır.

Başka bir örnek, işlenmesi ekstra zaman alan yanlışlıkla aşırı boyutlandırılmış bir RDBMS sonuç kümesidir. Bunun nedeni, bir SELECT ifadesinde yanlış yerleştirilmiş bir genel arama karakteri veya veritabanındaki beklenmeyen ve geçersiz veri olabilir.

Performans ayarının, kodu daha hızlı hale getirmek kadar akıllıca hangi iş süreçlerini yük testi yapacağınıza dair kararlar almakla da ilgili olduğunu unutmamak önemlidir. Bunun, performans endişelerini karşılamak için web sayfası boyutlarını küçük tutmak gibi performans ve kullanıcı arayüzü tasarımı arasındaki dengelemelerle de ilgili olduğu anlamına gelir.

Bu, sisteminizin kaputunun altına bakarken, büyük bir sonuç kümesinden şüpheli performans gördüğünüzde, düşünmenizi yeniden yönlendirmeniz ve daha soyut şeyleri, performans/kullanılabilirlik değiş tokuşları gibi düşünmeniz gerektiği anlamına gelir. Bu insan bağlam değişimi kolay değildir, ancak düşünün: Bazı ayarlama zorlukları, yük testinde baştan yer almaması gereken gerçeküstü kullanım durumları nedeniyle tamamen önlenebilir.


Bu anti-patern, gereksiz veri işleme ya da kullanıcı için çok fazla veri sunma gibi durumları ele alır. Aşağıda, bu tür bir durumda yanlış yapılan bir şeyi ve nasıl düzeltileceğini gösteren Java kod örnekleri verilmiştir.

Yanlış Strateji: Fazla Veri Yüklemek
Bu kod parçacığı, bir web sayfasında gösterilmek üzere tüm müşteri verilerini yüklemektedir. Bu, kullanıcının bir seferde kullanamayacağı çok fazla veri olabilir, böylece zaman ve kaynak israfına yol açar.

java
Copy code
public class OverprocessingExample {
    public List<Customer> getAllCustomers(Connection connection) throws SQLException {
        List<Customer> customers = new ArrayList<>();
        Statement statement = connection.createStatement();
        ResultSet rs = statement.executeQuery("SELECT * FROM customers");
        while (rs.next()) {
            customers.add(new Customer(rs.getInt("id"), rs.getString("name"), rs.getString("email")));
        }
        return customers;
    }
}
Doğru Strateji: Sayfalama Kullanarak Veriyi Parçalara Bölmek
Bu durumu düzeltmek için, sayfalama kullanarak yalnızca kullanıcının şu anda ihtiyaç duyduğu verileri yükleyebiliriz. Bu, gereksiz yere büyük miktarda veri işlemesini önler.

java
Copy code
public class EfficientProcessingExample {
    public List<Customer> getCustomersWithPagination(Connection connection, int page, int pageSize) throws SQLException {
        List<Customer> customers = new ArrayList<>();
        String query = "SELECT * FROM customers LIMIT ? OFFSET ?";
        PreparedStatement statement = connection.prepareStatement(query);
        statement.setInt(1, pageSize);
        statement.setInt(2, (page - 1) * pageSize);
        ResultSet rs = statement.executeQuery();
        while (rs.next()) {
            customers.add(new Customer(rs.getInt("id"), rs.getString("name"), rs.getString("email")));
        }
        return customers;
    }
}
Bu kod, veritabanından yalnızca belirli bir sayfa boyutuna uygun müşterileri alır, böylece kullanıcı için gerçekten gerekli olan verileri işler. "Önceki" ve "Sonraki" düğmeleri kullanarak kullanıcının diğer verilere erişmesine olanak tanır.

Bu örnek, performansı artırmak ve işlem yükünü azaltmak için veri yüklemesinin nasıl optimize edilebileceğini göstermektedir. İlgili kullanım durumuna bağlı olarak, bu gibi stratejilerle, uygulamanın gereksiz işlemler yapmasını önleyebilir ve kullanıcı deneyimini iyileştirebilirsiniz.


Ana Anti-Patron #4, “Büyük İşleme Sorunu(Large Processing Challenge)nu tanımlar. Bu anti-patron, birkaç milyar satır veri üzerinde arama gibi büyük performans sorunlarına, I/O ve diğer donanım kısıtlamalarına işaret eder. Şirket yazılımı geliştirmede bu tür büyük, zorlu sorunlar nadiren ortaya çıkar. Ancak böyle bir sorunla karşılaştığınızda, ekstra tasarım ve test özeni, saygı ve tedirginlikle yaklaşmanızı öneririm. Geri kalan her şeyi optimize etmek neredeyse önemsizdir.
“Büyük İşleme Sorunu”, dört Ana Anti-Patron'un sonuncusudur. Birinci en çok karşılaşılan iken dördüncü en az karşılaşılandır. Bu büyük sorunlarla düzenli olarak karşılaşıyorsanız, bu durumda bir istisna olarak kabul edebilirsiniz. Ancak, çoğumuz şirket web uygulamaları yazarken, bu tür korku uyandıran büyük işleme sorunları çok azdır.
Büyük sorunlara örnekler şunlar olabilir:
200 milyon kayıtlı bir tabloda sadece birkaç kayıt üzerinde arama yapmak.
Özellikle uzun mesafelerde, yavaş bir ağ üzerinden tekrar tekrar çok miktarda veri (örneğin bir megabayttan fazla) aktarmak.
Çoklu iş parçacığı performansının doğru bir şekilde elde edilmesi zor olsa da, bir başkasının zaten performansı doğru bir şekilde elde ettiği birçok kullanıma hazır API ve çözüm bulunmaktadır.
Bu büyük sorunlara hazırlanmak çok çalışma gerektirdiğinden, hazırlıkların tasarım belgesi oluşturulduğunda başlaması gerektiği gibi görünmektedir. Eğer büyük bir işleme sorunundan gerçekten korkuyorsanız, projenin erken aşamasında bunun uygulanabilirliğini test etmek için zaman ayırın; belki donanım uzmanları burada katkı sağlayabilir.
Büyük işleme sorunları, performans sorunlarını vurgulayan bir performans radarında ortaya çıkar. Büyük işleme sorunlarını ele almanın zor işi nedeniyle, geliştirme ekipleri ekstra çalışmayı öngörmeli ve performans ayarlama çabasının önceliğini artırmalıdır. Ancak, daha küçük performans sorunları performans radarında ortaya çıktığında, büyük performans sorunlarını ayarlama gibi diğer önceliklerin önüne geçerler. Tasarım, geliştirme, QA vb. diğer geliştirme yaşam döngüsü parçalarından da zaman çalarlar.
Küçük performans sorunlarını ayarlamak, temelde bir rahatsızlıktır; tecrübeme göre, küçük performans sorunlarındaki yavaşlamalar, tüm performans kusurlarının beklenmedik büyük bir bölümünü oluşturur.
Özellikle, işleme meydan okumanın büyüklüğü küçük ve kullanılan API kamuya açık olduğunda, başkaları zaten sorunları belgelemiş ve makul çözüm yolları bulmuş olabilir.
Bu anti-patron, ekiplerin bu tür sorunlara nasıl yaklaşması gerektiğine dair somut öneriler ve ipuçları sağlar, böylece daha etkili ve verimli olabilirler.

Bu anti-patern, genellikle geniş bir ölçekte, çok büyük veri setleri üzerinde işlem yapmanın zorluklarını tanımlar. Aşağıda böyle bir durumda yanlış olan bir şeyi ve nasıl düzeltileceğini gösteren Java kod örnekleri verilmiştir.

Yanlış Yaklaşım: Büyük Bir Veri Seti Üzerinde Basit Bir Arama
Bu kod parçacığı, 200 milyon kayıttan oluşan bir tabloda belirli bir kaydı aramaktadır. Bu, büyük bir işlem zorluğunu temsil eder ve ölçeklendirmek zor olabilir.

java
Copy code
public class LargeProcessingChallenge {
    public Customer findCustomerById(Connection connection, int id) throws SQLException {
        Statement statement = connection.createStatement();
        ResultSet rs = statement.executeQuery("SELECT * FROM customers WHERE id=" + id);
        if (rs.next()) {
            return new Customer(rs.getInt("id"), rs.getString("name"), rs.getString("email"));
        }
        return null;
    }
}
Doğru Yaklaşım: Veri Yapılarını ve Algoritmaları Optimize Etme
Büyük veri setlerinde işlem yaparken, özel indeksler, önbellekleme veya daha verimli algoritmalar gibi veri yapılarını ve teknikleri kullanmak önemlidir. Aşağıdaki örnek, veritabanındaki bir indeksi kullanarak arama işlemini optimize etmektedir.

java
Copy code
public class OptimizedLargeProcessingChallenge {
    public Customer findCustomerById(Connection connection, int id) throws SQLException {
        // Bu sorgu, "id" alanı üzerinde bir indeks olduğunu varsayarak optimize edilmiştir.
        PreparedStatement statement = connection.prepareStatement("SELECT * FROM customers WHERE id = ?");
        statement.setInt(1, id);
        ResultSet rs = statement.executeQuery();
        if (rs.next()) {
            return new Customer(rs.getInt("id"), rs.getString("name"), rs.getString("email"));
        }
        return null;
    }
}
Bu örnek, büyük veri setleri üzerinde işlem yapmanın zorluklarını ve bunları aşmak için bazı stratejileri göstermektedir. Ancak, büyük işlem zorluklarını ele almanın doğru yolu genellikle özel ve karmaşıktır, bu nedenle belirli bir duruma uygun en iyi çözümü bulmak için dikkatli analiz ve planlama gerekebilir. Daha özel ve etkili çözümler, paralel işlem, veri parçalama, önbellekleme gibi teknikler ve uygun donanım veya bulut kaynakları kullanmayı içerebilir.

Spring Boot / Java örnekleri

Anti-Pattern #1: Gereksiz Başlatma
Bu anti-pattern, gereksiz veya aşırı nesne başlatma işlemleri nedeniyle kaynakların verimsiz bir şekilde kullanılmasına neden olur.

Yanlış Yaklaşım
Aşağıdaki örnek, her istekte yeni bir servis nesnesi oluşturduğundan, gereksiz başlatma işlemlerinin bir örneğini göstermektedir.

java
Copy code
@RestController
public class UserController {

    @GetMapping("/user/{id}")
    public User getUser(@PathVariable Long id) {
        // Her istekte yeni bir servis nesnesi oluşturuluyor
        UserService userService = new UserService();
        return userService.findUserById(id);
    }
}
Bu yaklaşım, özellikle yüksek yük altında, bellek kullanımının ve GC basıncının artmasına neden olabilir.

Doğru Yaklaşım
Gereksiz başlatma sorununu çözmek için Spring'in Dependency Injection (DI) özelliğinden yararlanabiliriz. Aşağıdaki örnek, UserService'i bir bean olarak enjekte ederek bu sorunu nasıl düzelteceğimizi göstermektedir.

java
Copy code
@RestController
public class OptimizedUserController {

    @Autowired
    private UserService userService; // UserService Spring bean olarak enjekte ediliyor

    @GetMapping("/user/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findUserById(id); // Aynı servis nesnesi yeniden kullanılıyor
    }
}
Bu düzeltilmiş sürüm, aynı UserService nesnesini yeniden kullanır, böylece gereksiz başlatma işlemlerini önler ve uygulamanın performansını artırır.



Elbette! Şimdi ikinci anti-pattern olan "Strateji/Algoritma Verimsizliği" üzerine odaklanacağım.

Anti-Pattern #2: Strateji/Algoritma Verimsizliği
Bu anti-pattern, verimsiz bir algoritma veya stratejinin seçilmesi durumunda ortaya çıkar. Uygulamanın performansını düşürebilir veya ölçeklenebilirliği zorlaştırabilir.

Yanlış Yaklaşım
Aşağıdaki örnek, her istekte tüm kullanıcıları veritabanından getirip, ardından belirli bir kullanıcıyı bulan verimsiz bir kod örneğini göstermektedir.

java
Copy code
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public User findUserById(Long id) {
        List<User> allUsers = userRepository.findAll(); // Tüm kullanıcıları getir
        return allUsers.stream()
                .filter(user -> user.getId().equals(id))
                .findFirst()
                .orElse(null); // Ardından belirli bir kullanıcıyı filtrele
    }
}
Bu yaklaşım, büyük bir kullanıcı tablosu olduğunda performans problemlerine neden olabilir.

Doğru Yaklaşım
Doğru bir strateji kullanarak, yalnızca gerekli olan kullanıcıyı doğrudan veritabanından getirebiliriz. Bu, performansı artıracak ve ölçeklenebilirliği kolaylaştıracaktır.

java
Copy code
@Service
public class OptimizedUserService {

    @Autowired
    private UserRepository userRepository;

    public User findUserById(Long id) {
        return userRepository.findById(id) // Yalnızca belirli bir kullanıcıyı getir
                .orElse(null);
    }
}
Bu durumda, veritabanı sorgusu yalnızca gerekli olan kullanıcıyı getirir, böylece gereksiz veritabanı erişimi ve veri işleme maliyeti önlenir.

Bu ikinci anti-pattern için açıklamalarım bu kadar. Devam etmek isterseniz, lütfen bana bildirin!

Tabii ki! Şimdi üçüncü anti-pattern olan "Overprocessing" üzerine odaklanalım.

Anti-Pattern #3: Overprocessing
Overprocessing, gereğinden fazla işlem yapmak anlamına gelir. İster kullanıcı arayüzü, isterse veritabanı sorguları olsun, gereksiz işlemler sistemin performansını düşürebilir.

Yanlış Yaklaşım
Aşağıdaki örnek, her kullanıcı için detaylı profil bilgilerini de içerecek şekilde tüm kullanıcıları getirmeyi deneyen bir hizmeti gösterir. Bu, gereğinden fazla veri yüklemek anlamına gelebilir, özellikle de kullanıcının yalnızca birkaç kullanıcıyı görmek istediği bir durumda.

java
Copy code
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public List<UserDetailedInfo> getAllUsersWithDetails() {
        List<User> users = userRepository.findAll();
        return users.stream()
                .map(user -> fetchDetailedInfo(user))
                .collect(Collectors.toList());
    }

    private UserDetailedInfo fetchDetailedInfo(User user) {
        // Kullanıcı için ayrıntılı bilgi getir (Örnek: profili, arkadaş listesi vs.)
        // Bu işlem, çok fazla veri getirmek ve işlemek anlamına gelebilir.
    }
}
Doğru Yaklaşım
Bu durumda, kullanıcının gerçekten neye ihtiyacı olduğunu belirlemek önemlidir. Eğer detaylara gerek yoksa, yalnızca gerekli bilgileri getirerek bu anti-pattern'ı düzeltebiliriz.

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    
    @Query("SELECT new com.example.UserBasicInfo(u.name, u.email) FROM User u")
    List<UserBasicInfo> findAllBasicInfo();
}

@Service
public class OptimizedUserService {

    @Autowired
    private UserRepository userRepository;

    public List<UserBasicInfo> getAllUsers() {
        // Yalnızca kullanıcının temel bilgilerini veritabanından çeker
        return userRepository.findAllBasicInfo();
    }
}
Bu durumda, gereksiz ayrıntıları getirmek yerine, yalnızca kullanıcıların temel bilgilerini getiriyoruz. Bu, veritabanı sorgularını, ağ trafiğini ve istemci tarafı işlemesini önemli ölçüde azaltabilir.

Bu, Overprocessing anti-pattern'ı için uygun bir çözüm olabilir. Devam etmek isterseniz, lütfen bana bildirin!

Elbette, son anti-pattern olan "Large Processing Challenge" üzerinde konuşalım.

Anti-Pattern #4: Large Processing Challenge
Bu anti-pattern, I/O veya diğer donanım kısıtlamalarının neden olduğu büyük performans zorluklarıyla ilgilidir. Bu gibi durumlar oldukça nadirdir ancak karşılaşıldığında ekstra dikkat gerektirir.

Yanlış Yaklaşım
Bu örnek, bir tabloda birkaç milyar satıra sahip olabilecek büyük bir veritabanı sorgusu oluşturur. Bu, performansı ciddi şekilde etkileyebilir.

java
Copy code
@Service
public class ProductSearchService {

    @Autowired
    private ProductRepository productRepository;

    public List<Product> searchProducts(String keyword) {
        // Bu sorgu, milyarlarca kayıt içeren bir tabloyu tarayabilir.
        return productRepository.findProductsByKeyword(keyword);
    }
}
Doğru Yaklaşım
Bu tür büyük işlem zorlukları, özel bir dikkat ve optimizasyon gerektirir. İlk adım, gerekli olmayan verilerin işlenmesini önlemektir. İkinci adım, uygun indeksleme, önbellekleme ve veritabanı optimizasyonlarını kullanmaktır.

java
Copy code
@Service
public class OptimizedProductSearchService {

    @Autowired
    private ProductRepository productRepository;

    public Page<Product> searchProducts(String keyword, Pageable pageable) {
        // Sonuçları sayfalamak, verilerin yalnızca bir kısmını yüklememize izin verir.
        return productRepository.findProductsByKeyword(keyword, pageable);
    }
}
Bu durumda, yalnızca gerekli olan sonuçları yüklemek için sayfalama kullanıyoruz. Ayrıca, uygun veritabanı indeksleri kullanmak ve sorgunun etkin bir şekilde çalıştığından emin olmak için ekstra çalışma yapabilirsiniz.

Bu yaklaşım, "Large Processing Challenge" anti-pattern'ını çözmek için uygun bir yoldur. Sorgunun yalnızca gerçekten ihtiyaç duyulan kısmını işlemek, sistem kaynaklarını önemli ölçüde azaltabilir.

Java performansı Wikipedia Çevirisi

Java performansı

Yazılım geliştirmede , Java programlama dili, tarihsel olarak, C ve C++ gibi en hızlı 3. nesil yazılı dillerden daha yavaş kabul edildi . [1] Ana sebep, Java programlarının derlendikten sonra C ve C++ programlarında olduğu gibi yerel kod olarak doğrudan bilgisayarın işlemcisi yerine bir Java sanal makinesinde (JVM) çalıştığı farklı bir dil tasarımıdır. Java 1990'ların sonlarında ve 2000'lerin başlarında hızla popüler hale geldikten sonra birçok iş yazılımı Java ile yazıldığı için performans bir endişe konusuydu.

1990'ların sonlarından bu yana, Java programlarının yürütme hızı, tam zamanında derleme (JIT) (1997'de Java 1.1 için ), [2] [3] [4] daha iyi kodu destekleyen dil özelliklerinin eklenmesiyle önemli ölçüde arttı. JVM'deki analiz ve optimizasyonlar ( 2000'de HotSpot'un Sun'ın JVM'si için varsayılan hale gelmesi gibi). ARM'den Jazelle tarafından sunulanlar gibi Java bayt kodunun donanım yürütmesinin de önemli performans iyileştirmeleri sağladığı araştırıldı.

Java bytecode derlenmiş bir Java programının performansı , kendisine verilen görevlerin ana bilgisayar Java sanal makinesi ( JVM) tarafından ne kadar iyi yönetildiğine ve JVM'nin bunu yaparken bilgisayar donanımı ve işletim sisteminin (OS) özelliklerini ne kadar iyi kullandığına bağlıdır. Bu nedenle, herhangi bir Java performans testi veya karşılaştırması her zaman kullanılan JVM'nin sürümünü, satıcısını, işletim sistemini ve donanım mimarisini rapor etmelidir. Benzer bir şekilde, yerel olarak derlenen eşdeğer programın performansı, oluşturulan makine kodunun kalitesine bağlı olacaktır, bu nedenle test veya karşılaştırma, kullanılan derleyicinin adını, sürümünü ve satıcısını ve etkinleştirilmiş derleyici optimizasyonunu da rapor etmelidir .direktifler.

Sanal makine optimizasyon yöntemleri değiştir ]

Birçok optimizasyon, zaman içinde JVM'nin performansını iyileştirmiştir. Bununla birlikte, Java genellikle bunları başarıyla uygulayan ilk sanal makine olmasına rağmen , genellikle diğer benzer platformlarda da kullanılmıştır.

Tam zamanında derleme değiştir ]

İlk JVM'ler her zaman Java bayt kodlarını yorumladı Bunun, ortalama uygulamalarda Java'ya karşı C için 10 ile 20 arasında büyük bir performans cezası vardı. [5] Bununla mücadele etmek için Java 1.1'e bir tam zamanında (JIT) derleyici eklendi. Yüksek derleme maliyeti nedeniyle, Java 1.2'de HotSpot adı verilen ek bir sistem tanıtıldı ve Java 1.3'te varsayılan yapıldı. Java sanal makinesi , bu çerçeveyi kullanarak, sık sık veya tekrar tekrar yürütülen etkin noktalar için program performansını sürekli olarak analiz eder . Bunlar daha sonra optimizasyon için hedeflenir ve performans açısından daha az kritik kod için minimum ek yük ile yüksek performanslı yürütmeye yol açar .[6] [7] Bazı kıyaslamalar bu sayede 10 kat hız artışı gösteriyor. [8] Bununla birlikte, zaman kısıtlamaları nedeniyle, derleyici programı tam olarak optimize edemez ve bu nedenle ortaya çıkan program, yerel kod alternatiflerinden daha yavaştır. [9] [10]

Uyarlanabilir optimizasyon değiştir ]

Uyarlamalı optimizasyon, bilgisayar biliminde geçerli yürütme profiline dayalı olarak bir programın parçalarının dinamik olarak yeniden derlenmesini gerçekleştiren bir yöntemdir. Basit bir uygulamayla, uyarlanabilir bir optimize edici, tam zamanında derleme ve yönergeleri yorumlama arasında basitçe bir değiş tokuş yapabilir. Başka bir düzeyde, uyarlanabilir iyileştirme, uzaktaki dalları optimize etmek ve satır içi genişletmeyi kullanmak için yerel veri koşullarından yararlanabilir.

HotSpot gibi bir Java sanal makinesi, önceden JITed olan kodun optimizasyonunu da kaldırabilir. Bu, agresif (ve potansiyel olarak güvenli olmayan) optimizasyonların gerçekleştirilmesine izin verirken, daha sonra kodun optimizasyonunu kaldırabilir ve güvenli bir yola geri dönebilir. [11] [12]

Çöp toplama değiştir ]

1.0 ve 1.1 Java sanal makineleri (JVM'ler) , bir çöp toplama işleminden sonra yığını parçalayabilen bir işaretleme toplayıcı kullandı. Java 1.2'den başlayarak JVM'ler, çok daha iyi bir birleştirme davranışına sahip olan bir nesil toplayıcıya dönüştü. [13] Modern JVM'ler, çöp toplama performansını daha da iyileştiren çeşitli yöntemler kullanır [14]

Diğer optimizasyon yöntemleri değiştir ]

Sıkıştırılmış Hatalar değiştir ]

Sıkıştırılmış Hatalar, Java 5.0+ sürümünün 32 bit referanslarla 32 GB'a kadar yığını adreslemesine izin verir. Java, bireysel baytlara erişimi desteklemez, yalnızca varsayılan olarak 8 baytlık hizalanmış nesnelere erişimi destekler. Bu nedenle bir heap referansının en düşük 3 biti her zaman 0 olacaktır. 32 bit referansların çözünürlüğü 8 byte bloklara düşürülerek adreslenebilir alan 32 GB'a çıkarılabilir. Java, C++ gibi bazı dillerden çok daha fazla referans kullandığından, bu, 64 bitlik referanslar kullanmaya kıyasla bellek kullanımını önemli ölçüde azaltır. Java 8, 32 bit referanslarla 64 GB'a kadar desteklemek için 16 bayt hizalama gibi daha büyük hizalamaları destekler. alıntı gerekli ]

Bölünmüş bayt kodu doğrulaması değiştir ]

Sun JVM, bir sınıfı yürütmeden önce Java bayt kodlarını doğrular (bkz . bayt kodu doğrulayıcı ). Bu doğrulama tembel bir şekilde gerçekleştirilir: sınıfların bayt kodları, programın başında değil, yalnızca belirli sınıf yüklendiğinde ve kullanıma hazır olduğunda yüklenir ve doğrulanır. Bununla birlikte, Java sınıf kitaplıkları da normal Java sınıfları olduğundan, kullanıldıklarında ayrıca yüklenmeleri gerekir; bu, örneğin bir Java programının başlangıç ​​süresinin genellikle ++ programlarından daha uzun olduğu anlamına gelir.

İlk olarak Java Platformu Micro Edition'da (J2ME) tanıtılan bölünmüş zamanlı doğrulama adlı bir yöntem , JVM'de Java sürüm 6'dan beri kullanılmaktadır . Java bayt kodunun doğrulanmasını iki aşamaya ayırır : [15]

  • Tasarım zamanı – bir sınıfı kaynaktan bayt koduna derlerken
  • Çalışma zamanı – bir sınıf yüklenirken.

Uygulamada bu yöntem, Java derleyicisinin sahip olduğu sınıf akışı bilgisini yakalayarak ve derlenmiş yöntem bayt kodlarını sınıf akış bilgisinin bir özetiyle açıklayarak çalışır. Bu, çalışma zamanı doğrulamasını önemli ölçüde daha az karmaşık hale getirmez , ancak bazı kısayollara izin verir. alıntı gerekli ]

Kaçış analizi ve kilit kabalaştırma değiştir ]

Java, çoklu iş parçacığını dil düzeyinde yönetebilir . Çoklu iş parçacığı, programların aynı anda birden çok işlemi gerçekleştirmesine izin vererek, birden çok işlemci veya çekirdeğe sahip bilgisayar sistemlerinde çalışan programların performansını artırır Ayrıca, çok iş parçacıklı bir uygulama, uzun süren görevleri yerine getirirken bile girdiye yanıt verebilir.

Bununla birlikte, çoklu iş parçacığı kullanan programların, iş parçacıklarından biri tarafından kullanıldığında paylaşılan yöntemlere veya bloklara erişimi kilitlemek için iş parçacıkları arasında paylaşılan nesnelere daha fazla dikkat etmesi gerekir. Bir bloğu veya bir nesneyi kilitlemek, söz konusu işletim sistemi düzeyindeki işlemin temelindeki doğası gereği zaman alan bir işlemdir (bkz. eşzamanlılık denetimi ve kilit ayrıntı düzeyi ).

Java kitaplığı birden fazla iş parçacığı tarafından hangi yöntemlerin kullanılacağını bilmediğinden, standart kitaplık çok iş parçacıklı bir ortamda gerektiğinde blokları her zaman kilitler.

Java 6'dan önce, bir nesnenin aynı anda iki farklı iş parçacığı tarafından değiştirilme riski olmasa bile, sanal makine program tarafından istendiğinde nesneleri ve blokları her zaman kilitledi . Örneğin, bu durumda, diğer iş parçacıkları tarafından değiştirilmeyeceğinden ( senkronize edildiğinden) emin olmak için her bir eklemeVector işleminden önce bir yerel kilitlendi , ancak yöntem için kesinlikle yerel olduğu için buna gerek yok: Vector

public String getNames () { final Vector < String > v = new Vector <> (); V. _ ekle ( "Ben" ); V. _ ekle ( "Siz" ); V. _ ekle ( "O" ); dönüş _ _ toString (); }   
          
     
     
     
      

Java 6'dan başlayarak, kod blokları ve nesneler yalnızca ihtiyaç duyulduğunda kilitlenir, [16] bu nedenle yukarıdaki durumda, sanal makine Vector nesnesini hiç kilitlemez.

6u23 sürümünden bu yana Java, kaçış analizi için destek içerir. [17]

Tahsis iyileştirmelerini kaydedin değiştir ]

Java 6'dan önce istemci sanal makinesinde kayıtların tahsisi çok ilkeldi ( bloklar arasında yaşamıyorlardı ), bu, x86'larda olduğu gibi daha az işlemci kaydı bulunan CPU tasarımlarında bir sorundu Bir işlem için başka kayıt yoksa, derleyicinin kayıttan belleğe (veya bellekten kayda) kopyalaması gerekir, bu da zaman alır (kayıtlara erişim önemli ölçüde daha hızlıdır). Ancak, sunucu sanal makinesi bir renkli grafik ayırıcı kullandı ve bu sorunu yaşamadı.

Kayıt tahsisinin optimizasyonu Sun'ın JDK 6'sında tanıtıldı; [18] daha sonra aynı kayıtları bloklar arasında kullanmak (uygulanabilir olduğunda) mümkün oldu ve bu da belleğe erişimi azalttı. Bu, bazı kıyaslamalarda yaklaşık %60'lık bir rapor edilen performans artışına yol açtı. [19]

Sınıf verisi paylaşımı _

Sınıf verisi paylaşımı (Sun tarafından CDS olarak adlandırılır), Java uygulamalarının başlatma süresini azaltan ve ayrıca bellek ayak izini azaltan bir mekanizmadır JRE kurulduğunda , yükleyici, sistem JAR dosyasından (rt.jar adı verilen tüm Java sınıf kitaplığını tutan JAR dosyası) bir sınıf kümesini özel bir dahili temsile yükler ve bu temsili bir dosyaya döker. "paylaşılan arşiv". Sonraki JVM çağrıları sırasında, bu paylaşılan arşiv , bu sınıfları yükleme maliyetinden tasarruf etmek ve JVM'nin bu sınıflar için meta verilerinin çoğunun birden çok JVM işlemi arasında paylaşılmasına izin vermek için bellek eşlenir . [20]

Başlatma süresindeki ilgili gelişme, küçük programlar için daha belirgindir. [21]

Performans iyileştirmelerinin geçmişi değiştir ]

Burada listelenen geliştirmelerin dışında, Java'nın her sürümü, JVM ve Java uygulama programlama arayüzünde (API) birçok performans iyileştirmesi getirmiştir.

JDK 1.1.6: İlk tam zamanında derleme ( Symantec'in JIT derleyicisi) [2] [22]

J2SE 1.2: Nesil toplayıcı kullanımı .

J2SE 1.3: HotSpot tarafından tam zamanında derleme .

J2SE 1.4: Sun'ın 1.3 ve 1.4 sürümleri arasındaki performans iyileştirmelerine genel bakış için buraya bakın.

Java SE 5.0: Sınıf verisi paylaşımı [23]

Java SE 6:

Diğer iyileştirmeler:

  • Java OpenGL Java 2D ardışık düzen hız geliştirmeleri [24]
  • Java 2D performansı da Java 6'da önemli ölçüde iyileştirildi [25]

Ayrıca bkz. 'Java 5 ve Java 6 arasındaki performans iyileştirmelerine ilişkin Sun'a genel bakış'. [26]

Java SE 6 Güncelleme 10 düzenle ]

Java 7 değiştir ]

Java 7 için birkaç performans iyileştirmesi yayınlandı: Java 6 veya Java 7 güncellemesi için gelecekteki performans iyileştirmeleri planlanıyor: [31]

  • Şu anda Da Vinci Machine (Multi Language Virtual Machine) üzerinde yapılan prototipleme çalışmasının ardından, dinamik programlama dilleri için JVM desteği sağlamak , [32]
  • Çok çekirdekli işlemcilerde paralel hesaplamayı yöneterek mevcut eşzamanlılık kitaplığını geliştirin [33] [34]
  • JVM'nin, katmanlı derleme adı verilen bir yöntemle aynı oturumda hem istemci hem de sunucu JIT derleyicilerini kullanmasına izin verin: [35]
    • İstemci başlangıçta kullanılacaktır (çünkü başlangıçta ve küçük uygulamalar için iyidir) ,
    • Sunucu , uygulamanın uzun süreli çalışması için kullanılacaktır (çünkü bunun için istemci derleyicisinden daha iyi performans gösterir).
  • Zaman içinde tutarlı duraklamalar sağlamak için mevcut eşzamanlı düşük duraklamalı çöp toplayıcıyı (aynı zamanda eşzamanlı işaret tarama (CMS) toplayıcı olarak da adlandırılır) Önce Çöp (G1) adlı yeni bir toplayıcı ile değiştirin. [36] [37]

Diğer dillerle karşılaştırma değiştir ]

Bir Java programının performansı ile C++ gibi başka bir dilde yazılmış eşdeğer bir programın performansını nesnel olarak karşılaştırmak, aynı görevleri tamamlayan programları karşılaştıran dikkatli ve dikkatli bir şekilde oluşturulmuş bir kıyaslama gerektirir. Java'nın bayt kodu derleyicisinin hedef platformu , Java platformudur ve bayt kodu, JVM tarafından ya yorumlanır ya da makine koduna derlenir. Diğer derleyiciler neredeyse her zaman belirli bir donanım ve yazılım platformunu hedefleyerek yürütme sırasında neredeyse hiç değişmeden kalacak makine kodu üretir kaynak belirtilmeli ] . Bu iki farklı yaklaşımdan çok farklı ve karşılaştırması zor senaryolar ortaya çıkıyor: statik ve dinamik derlemelerve yeniden derlemeler , çalışma zamanı ortamı ve diğerleri hakkında kesin bilgilerin kullanılabilirliği.

Java genellikle çalışma zamanında Java sanal makinesi tarafından tam zamanında derlenir , ancak C++ gibi önceden de derlenebilir . Tam zamanında derlendiğinde, The Computer Language Benchmarks Game'in mikro ölçütleri , performansı hakkında aşağıdakileri gösterir: [38]

  • C veya C++ gibi derlenmiş dillerden daha yavaş [39]
  • C# gibi diğer tam zamanında derlenen dillere benzer [40]
  • Perl , Ruby , PHP ve Python gibi etkili yerel kod derleyicisi ( JIT veya AOT ) olmayan dillerden çok daha hızlı . [41]

Program hızı _

Kıyaslamalar genellikle sayısal olarak yoğun küçük programların performansını ölçer. Bazı nadir gerçek programlarda Java, C'den daha iyi performans gösterir. Bir örnek, Jake2'nin karşılaştırmalı testidir (orijinal GPL C kodunu çevirerek Java'da yazılmış bir Quake II klonu ). Java 5.0 sürümü, bazı donanım yapılandırmalarında C muadilinden daha iyi performans gösterir. [42] Verilerin nasıl ölçüldüğü belirtilmemekle birlikte (örneğin, 1997'de derlenen orijinal Quake II yürütülebilir dosyası kullanıldıysa, bu, mevcut C derleyicileri Quake için daha iyi optimizasyonlar elde edebileceğinden kötü olarak kabul edilebilir), aynı şeyin nasıl olduğunu not eder. Java kaynak kodu, yalnızca VM'yi güncelleyerek büyük bir hız artışı sağlayabilir; bu, %100 statik bir yaklaşımla elde edilmesi imkansız bir şeydir.

Diğer programlar için, C++ muadili, Java eşdeğerinden önemli ölçüde daha hızlı çalışabilir ve genellikle çalışır. Google tarafından 2011'de gerçekleştirilen bir kıyaslama, C++ ve Java arasında 10 kat olduğunu gösterdi. [43] Diğer uçta, 2012'de bir 3B modelleme algoritmasıyla gerçekleştirilen akademik bir kıyaslama, Java 6 JVM'nin Windows altında C++'dan 1,09 ila 1,91 kat daha yavaş olduğunu gösterdi. [44]

Java ve benzeri dillerde mümkün olan bazı optimizasyonlar, C++'da bazı durumlarda mümkün olmayabilir: [45]

  • C tarzı işaretçi kullanımı, işaretçileri destekleyen dillerde iyileştirmeyi engelleyebilir,
  • Kaçış analizi yöntemlerinin kullanımı , örneğin C++' ta sınırlıdır , çünkü bir C++ derleyicisi, işaretçiler nedeniyle belirli bir kod bloğunda bir nesnenin değiştirilip değiştirilmeyeceğini her zaman bilemez [not 1]
  • Java, türetilmiş örnek yöntemlerine, C++'nın ekstra sanal tablo araması sayesinde C++'nın türetilmiş sanal yöntemlere erişebileceğinden daha hızlı erişebilir. Bununla birlikte, C++'daki sanal olmayan yöntemler v-table performans darboğazlarından muzdarip değildir ve bu nedenle Java'ya benzer bir performans sergiler.

JVM ayrıca işlemciye özel optimizasyonlar veya satır içi genişletme gerçekleştirebilir Ayrıca, zaten derlenmiş veya satır içine alınmış kodun optimizasyonunu kaldırma yeteneği, bazen harici kitaplık işlevleri söz konusu olduğunda, statik olarak yazılan diller tarafından gerçekleştirilenlerden daha agresif optimizasyonlar gerçekleştirmesine izin verir. [46] [47]

Java ve C++ arasındaki mikro kıyaslama sonuçları büyük ölçüde hangi işlemlerin karşılaştırıldığına bağlıdır. Örneğin, Java 5.0 ile karşılaştırırken:


notlar
  1. ^ Bu nitelikteki içerik , Java'nın gizlemek ve kapsüllemek için tasarlandığı türden düşük düzeyli kodlama karmaşıklığından tam olarak yararlanan özel ayırıcılar gibi gelişmiş yöntemler kullanılarak kaynak kod düzeyinde C++ programlarında hafifletilebilirancak, program birincil geliştirme aşamasındayken benimsenmezse (veya en azından beklenmezse) bu yaklaşım nadiren pratiktir.

Çok çekirdekli performans _

Java uygulamalarının çok çekirdekli sistemlerde ölçeklenebilirliği ve performansı, nesne ayırma oranıyla sınırlıdır. Bu etki bazen "tahsis duvarı" olarak adlandırılır. [54] Bununla birlikte, pratikte, modern çöp toplayıcı algoritmaları, çöp toplamayı gerçekleştirmek için birden fazla çekirdek kullanır ve bu da bu sorunu bir dereceye kadar hafifletir. Bazı çöp toplayıcıların saniyede bir gigabaytın üzerinde tahsis oranlarını sürdürdükleri bildirilmektedir [55] ve birkaç yüz CPU çekirdeğine ve birkaç yüz GB büyüklüğündeki yığınlara ölçeklendirmede sorun yaşamayan Java tabanlı sistemler mevcuttur. [56]

Java'daki otomatik bellek yönetimi, bir tür çöp toplama olmadan uygulanması son derece zor veya bazen imkansız olan kilitsiz ve değişmez veri yapılarının verimli kullanımına izin verir. alıntı gerekli ] Java, java.util.concurrent paketindeki standart kitaplığında bu tür bir dizi üst düzey yapı sunarken, geçmişte C veya C++ gibi yüksek performanslı sistemler için kullanılan birçok dilde hala bunlardan yoksundur. alıntı gerekli ]

Başlatma zamanı düzenle ]

Java başlatma süresi genellikle C , C++ , Perl veya Python dahil olmak üzere birçok dilden çok daha yavaştır çünkü birçok sınıfın (ve her şeyden önce Class library platformundaki sınıfların ) kullanılmadan önce yüklenmesi gerekir.

Benzer popüler çalışma zamanlarıyla karşılaştırıldığında, bir Windows makinesinde çalışan küçük programlar için başlatma süresi Mono'nunkine benzer ve .NET'inkinden biraz daha yavaş görünmektedir [57]

Görünüşe göre başlatma süresinin çoğu, JVM başlatma veya sınıf yükleme yerine giriş-çıkış (IO) bağlı işlemlerden kaynaklanıyor ( tek başına rt.jar sınıfı veri dosyası 40 MB'dir ve JVM bu büyük dosyada çok fazla veri aramalıdır) . [27] Bazı testler, yeni bölünmüş bayt kodu doğrulama yönteminin sınıf yüklemeyi kabaca %40 oranında iyileştirmesine rağmen , büyük programlar için yalnızca yaklaşık %5'lik bir başlangıç ​​iyileştirmesi gerçekleştirdiğini gösterdi. [58]

Küçük bir gelişme olsa da, basit bir işlem gerçekleştiren ve sonra çıkan küçük programlarda daha belirgindir çünkü Java platformu veri yüklemesi, gerçek programın çalışmasının yükünün birçok katını temsil edebilir.

Java SE 6 Güncelleme 10'dan itibaren Sun JRE, verileri disk yerine disk önbelleğinden almak için OS başlangıcında sınıf verilerini önceden yükleyen bir Hızlı Başlatıcı ile birlikte gelir .

Excelsior JET, soruna diğer taraftan yaklaşır. Startup Optimizer, uygulama başlangıcında diskten okunması gereken veri miktarını azaltır ve okumaları daha sıralı hale getirir.

Kasım 2004'te, "JVM başlatma yüküne maruz kalmadan Java programlarını komut satırından çalıştırmak için bir istemci, protokol ve sunucu" olan Nailgun halka açıldı. [59], JVM başlatma ek yükü olmadan bir veya daha fazla Java uygulamasını çalıştırmak için komut dosyaları için bir JVM'yi arka plan programı olarak kullanma seçeneğini ilk kez sunuyor . Nailgun arka plan programı güvensizdir: "tüm programlar sunucuyla aynı izinlerle çalıştırılır". Çok kullanıcılı güvenliğin gerekli olduğu durumlarda , özel önlemler alınmadan Nailgun uygun değildir. Uygulama başına JVM başlatmanın kaynak kullanımına hakim olduğu betikler, bir ila iki büyüklük sırası çalışma zamanı performans iyileştirmelerine bakın. [60]

Bellek kullanımı _

Java bellek kullanımı, C++'ın bellek kullanımından çok daha yüksektir, çünkü:

  • Java'da her nesne için 8 bayt ve her dizi [61] için 12 bayt ek yük vardır . Bir nesnenin boyutu 8 baytın katı değilse, 8'in bir sonraki katına yuvarlanır. Bu, bir bayt alanı tutan bir nesnenin 16 bayt kapladığı ve 4 baytlık bir referansa ihtiyaç duyduğu anlamına gelir. C++ ayrıca, sınıfın doğrudan veya dolaylı olarak sanal işlevler bildirdiği her nesne için bir işaretçi (genellikle 4 veya 8 bayt) tahsis eder . [62]
  • Adres aritmetiği eksikliği, dar aralıklı yapılar ve XOR bağlantılı listeler gibi bellek açısından verimli kaplar oluşturmayı şu anda imkansız hale getiriyor ( OpenJDK Valhalla projesi, işaretçi aritmetiğini tanıtmayı amaçlamasa da bu sorunları azaltmayı hedefliyor; bu, bir çöp toplama ortamı).
  • malloc ve new'in aksine, yığın boyutu arttıkça çöp toplamanın ortalama ek yükü asimptotik olarak sıfıra (daha doğrusu bir CPU döngüsü) yaklaşır. [63]
  • Java Sınıf Kitaplığının bazı bölümleri, programın yürütülmesinden önce yüklenmelidir (en azından bir program içinde kullanılan sınıflar). [64] Bu, küçük uygulamalar için önemli bir bellek ek yüküne yol açar. alıntı gerekli ]
  • Hem Java ikili hem de yerel yeniden derlemeler tipik olarak bellekte olacaktır.
  • Sanal makine önemli miktarda bellek kullanır.
  • Java'da, ayrılmış B ve C örneklerine yapılan referanslar kullanılarak bir bileşik nesne (B ve C örneklerini kullanan A sınıfı) oluşturulur. C++'da, B ve C örneği kullanıldığında bu tür başvuruların bellek ve performans maliyetinden kaçınılabilir. /veya C, A içinde bulunur.

Çoğu durumda bir C++ uygulaması, Java'nın sanal makinesinin büyük yükü, sınıf yüklemesi ve otomatik bellek yeniden boyutlandırması nedeniyle eşdeğer bir Java uygulamasından daha az bellek tüketir. Diller ve çalışma zamanı ortamları arasında seçim yapmak için belleğin kritik bir faktör olduğu programlar için bir maliyet/fayda analizi gereklidir.

Trigonometrik fonksiyonlar değiştir ]

Trigonometrik fonksiyonların performansı, C'ye kıyasla kötüdür, çünkü Java, temeldeki donanım uygulamasına karşılık gelmeyebilecek, matematiksel işlemlerin sonuçları için katı spesifikasyonlara sahiptir. [65] x87 kayan nokta alt kümesinde , Java 1.4'ten beri yazılımda sin ve cos için argüman azaltma yapıyor, [66] aralığın dışındaki değerler için büyük bir performans isabetine neden oluyor. [67] [ açıklama gerekli ]

Java Yerli Arayüzü değiştir ]

Java Yerel Arabirimi , JVM'de çalışan kod ile yerel kod arasındaki sınırı aşmayı maliyetli hale getiren yüksek bir ek yüke neden olur. [68] [69] [70] Java Yerel Erişimi (JNA), JNI veya yerel kod olmadan, yalnızca Java kodu aracılığıyla Java programlarının yerel paylaşılan kitaplıklara ( Windows'ta dinamik bağlantı kitaplığı (DLL'ler)) kolay erişimini sağlar. Bu işlevsellik, Windows'un Platform/Invoke ve Python'un ctipleri ile karşılaştırılabilir. Erişim, kod oluşturma olmadan çalışma zamanında dinamiktir. Ancak bir maliyeti vardır ve JNA genellikle JNI'den daha yavaştır. [71]

Kullanıcı arayüzü _

Swing , parçacıkların işlenmesini saf Java 2D API'sine devrettiği için, yerel parçacık araç setlerinden daha yavaş olarak algılanmıştır Bununla birlikte, Swing'in performansını , işlemeyi işletim sisteminin yerel GUI kitaplıklarına devreden Standard Widget Toolkit ile karşılaştıran kıyaslamalar, net bir kazanan göstermez ve sonuçlar büyük ölçüde bağlama ve ortamlara bağlıdır. [72] Ek olarak, Swing'in yerini alması amaçlanan daha yeni JavaFX çerçevesi, Swing'in doğasında olan birçok sorunu giderir.

Yüksek performanslı bilgi işlem için kullanın değiştir ]

Bazı insanlar , yüksek performanslı bilgi işlem (HPC) için Java performansının, yoğun bilgi işlem kıyaslamalarında Fortran'a benzer olduğuna , ancak JVM'lerin bir ızgara bilgi işlem ağında yoğun iletişim gerçekleştirmek için hala ölçeklenebilirlik sorunları olduğuna inanıyor . [73]

Bununla birlikte, Java ile yazılmış yüksek performanslı bilgi işlem uygulamaları, kıyaslama yarışmalarını kazanmıştır. 2008, [74] ve 2009, [75] [76] 'da bir Apache Hadoop (Java ile yazılmış açık kaynaklı, yüksek performanslı bir bilgi işlem projesi) tabanlı bir küme, bir terabayt ve petabayt tamsayıları en hızlı şekilde sıralayabildi. Bununla birlikte, rakip sistemlerin donanım kurulumu sabitlenmedi. [77] [78]

Programlama yarışmalarında değiştir ]

Java'daki programlar, diğer derlenmiş dillerdeki programlardan daha yavaş başlar. [79] [80] Bu nedenle, bazı çevrimiçi hakem sistemleri, özellikle Çin üniversiteleri tarafından barındırılanlar, Java kullanan yarışmacılara adil olmak için [81] [82] [83] [84] [85] Java programları için daha uzun süre sınırları kullanır.

Ayrıca bkz _

alıntılar _

  1. "Java ve C++ kıyaslamaları" .
  2. ^Şuraya atla:b "Symantec'in Tam Zamanında Java Derleyicisi Sun JDK 1.1'e Entegre Edilecek".
  3. "Kısa Bilgi: Apple, Symantec'in tam zamanında derleyicisini lisanslar" . cnet.com. 12 Mayıs 1998 Erişim tarihi : 15 Kasım 2015 .
  4. "Java, yeni Symantec tam zamanında derleyici ile dört kat daha hızlı" .
  5. "Java/.NET Çalışma Zamanlarının Performans Karşılaştırması (Ekim 2004)" .
  6. ^ Kawaguchi, Kohsuke (30 Mart 2008). "Java'dan montaj koduna derinlemesine dalış" . 2 Nisan 2008 tarihinde kaynağından arşivlendi Erişim tarihi : 2 Nisan 2008 .
  7. "Tam Zamanında Java Derleyicisinde Hızlı, Etkili Kod Oluşturma" (PDF) . Intel Corporation Erişim tarihi : 22 Haziran 2007 .
  8. ^ Bu makale , yorumlanmış mod ile Hotspot arasındaki performans kazancının 10 kattan fazla olduğunu göstermektedir.
  9. ^ C, C# ve Java'da sayısal performans
  10. ^ Algoritmik Performans Karşılaştırması Arasında C, C++, Java ve C# Programlama Dilleri 31 Mart 2010'da Wayback Machine'de Arşivlendi
  11. "Java HotSpot Sanal Makinesi, v1.4.1" . Güneş Mikrosistemleri Erişim tarihi : 20 Nisan 2008 .
  12. ^ Nutter, Charles (28 Ocak 2008). "Lang.NET 2008: 1. Gün Düşünceleri" Erişim tarihi : 18 Ocak 2011 . Performans kaygılarıyla uğraşırken deoptimizasyon çok heyecan vericidir, çünkü bu çok daha agresif optimizasyonlar yapabileceğiniz anlamına gelir... daha sonra denenmiş ve gerçek bir güvenli yola geri dönebileceğinizi bilerek
  13. ^ IBM DeveloperWorks Kitaplığı
  14. ^ Örneğin, duraklamaların süresi artık daha az fark edilir. ÖrneğinJava ile yazılmış bu Quake II klonuna bakın: Jake2 .
  15. "Yeni Java SE 6 Özelliği: Doğrulayıcıyı Denetleme Türü" . Java.net Erişim tarihi : 18 Ocak 2011 .kalıcı ölü bağlantı ]
  16. ^ Brian Goetz (18 Ekim 2005). "Java teorisi ve pratiği: Mustang'de senkronizasyon optimizasyonları" . IBM Erişim tarihi : 26 Ocak 2013 .
  17. "Java HotSpot Sanal Makine Performans Geliştirmeleri" . Oracle Şirketi Erişim tarihi : 14 Ocak 2014 . Kaçış analizi, Java Hotspot Sunucu Derleyicisinin yeni bir nesnenin kullanım kapsamını analiz edebildiği ve onu Java öbeğinde tahsis edip etmeyeceğine karar verebildiği bir tekniktir. Kaçış analizi, Java SE 6u23 ve sonrasında varsayılan olarak desteklenir ve etkinleştirilir.
  18. ^ Hata raporu: yeni kayıt ayırıcı, Mustang (JDK 6) b59'da düzeltildi
  19. ^ Mustang'in HotSpot İstemcisi %58 daha hızlı! 5 Mart 2012'de Wayback Machine'de Osvaldo Pinali Doederlein'ın java.net'teki Blogunda arşivlendi
  20. ^ Java.sun.com'da Sınıf Veri Paylaşımı
  21. ^ artima geliştiricisinde Java Buzz Forumunda JDK 1.5.0'da Sınıf Veri Paylaşımı
  22. ^ Mckay, Niali. "Java, yeni Symantec tam zamanında derleyici ile dört kat daha hızlı hale geliyor" .
  23. ^ Sun'ın 1.4 ve 5.0 sürümleri arasındaki performans iyileştirmelerine genel bakışı.
  24. ^ STR-Crazier: Performance Enhancements in Mustang 5 Ocak 2007'de Wayback Machine'de Chris Campbell'ın java.net'teki Blogunda arşivlendi
  25. ^ JFreeChart uygulaması için Java 5.0'dan 6'ya yaklaşık %60'lık bir performans artışını gösteren bir kıyaslama için buraya bakın
  26. ^ http://java.sun.com adresinde Java SE 6 Performans Teknik Raporu
  27. ^Şuraya atla:b Haase, Chet (Mayıs 2007). "Tüketici JRE: Daha Yalın, Daha Ortalama Java Teknolojisi"Güneş MikrosistemleriErişim tarihi : 27 Temmuz 2007İşletim sistemi düzeyinde, tüm bu megabaytların diskten okunması gerekir ki bu çok yavaş bir işlemdir. Aslında, katil olan diskin aranma zamanıdır; büyük dosyaları sırayla okumak nispeten hızlıdır, ancak aslında ihtiyacımız olan bitleri aramak değildir. Bu nedenle, herhangi bir uygulama için bu büyük dosyalardaki verilerin yalnızca küçük bir kısmına ihtiyacımız olsa da, dosyaların her yerinde aramamız, bol miktarda disk etkinliği olduğu anlamına gelir.
  28. ^ Haase, Chet (Mayıs 2007). "Tüketici JRE: Daha Yalın, Daha Ortalama Java Teknolojisi" . Güneş Mikrosistemleri Erişim tarihi : 27 Temmuz 2007 .
  29. ^ Haase, Chet (Mayıs 2007). "Tüketici JRE: Daha Yalın, Daha Ortalama Java Teknolojisi" . Güneş Mikrosistemleri Erişim tarihi : 27 Temmuz 2007 .
  30. ^ Campbell, Chris (7 Nisan 2007). "Gölgelendiriciler Üzerinden Daha Hızlı Java 2D" . 5 Haziran 2011 tarihinde kaynağından arşivlendi Erişim tarihi : 18 Ocak 2011 .
  31. ^ Haase, Chet (Mayıs 2007). "Tüketici JRE: Daha Yalın, Daha Ortalama Java Teknolojisi" . Güneş Mikrosistemleri Erişim tarihi : 27 Temmuz 2007 .
  32. "JSR 292: Java Platformunda Dinamik Olarak Yazılan Dilleri Destekleme" . jcp.org Erişim tarihi : 28 Mayıs 2008 .
  33. ^ Goetz, Brian (4 Mart 2008). "Java teorisi ve pratiği: İçine bir çatal saplayın, Bölüm 2" . IBM _ Erişim tarihi : 9 Mart 2008 .
  34. ^ Lorimer, RJ (21 Mart 2008). "Java 7'de Fork/Join ile Paralellik" . infoq.com Erişim tarihi : 28 Mayıs 2008 .
  35. "Java HotSpot Sanal Makinesinde Yeni Derleyici Optimizasyonları" (PDF) . Güneş Mikrosistemleri. Mayıs 2006 Erişim tarihi : 30 Mayıs 2008 .
  36. ^ Humble, Charles (13 Mayıs 2008). "JavaOne: Önce Çöp" . infoq.com Erişim tarihi : 7 Eylül 2008 .
  37. ^ Korkak, Danny (12 Kasım 2008). "Java VM: JDK 7 için yeni bir Çöp Toplayıcı deneniyor" . 8 Aralık 2011 tarihinde kaynağından arşivlendi Erişim tarihi : 15 Kasım 2008 .
  38. "Bilgisayar Dili Karşılaştırma Oyunu" . benchmarksgame.alioth.debian.org. 25 Ocak 2015 tarihinde kaynağından arşivlendi Erişim tarihi : 2 Haziran 2011 .
  39. "Bilgisayar Dili Karşılaştırma Oyunu" . benchmarksgame.alioth.debian.org. 13 Ocak 2015 tarihinde kaynağından arşivlendi Erişim tarihi : 2 Haziran 2011 .
  40. "Bilgisayar Dili Karşılaştırma Oyunu" . benchmarksgame.alioth.debian.org. 10 Ocak 2015 tarihinde kaynağından arşivlendi Erişim tarihi : 2 Haziran 2011 .
  41. "Bilgisayar Dili Karşılaştırma Oyunu" . benchmarksgame.alioth.debian.org. 2 Ocak 2015 tarihinde kaynağından arşivlendi Erişim tarihi : 2 Haziran 2011 .
  42. ^ : 260/250 kare/sn ile 245 kare/sn ( karşılaştırmaya bakın )
  43. ^ Hunt, Robert. "C++/Java/Go/Scala'da Döngü Tanıma" (PDF) . Scala Günleri 2011 . Stanford, Kaliforniya Erişim tarihi : 23 Mart 2014 .
  44. ^ L.Gherardi; D. Brugali; D.Comotti (2012). "Bir Java ve C++ performans değerlendirmesi: bir 3B modelleme kıyaslaması" (PDF) . Bergamo Üniversitesi Erişim tarihi : 23 Mart 2014 . Uzun süre çalışan uygulamalar için en iyi şekilde ayarlanmış olan Sunucu derleyicisini kullanmak, bunun yerine Java'nın 1,09 ila 1,91 kat daha yavaş olduğunu göstermiştir(...) Sonuç olarak, sunucu derleyici ile elde edilen sonuçlar ve bu önemli özellikler, Java'nın şunları yapabileceğini göstermektedir: C++ için geçerli bir alternatif olarak kabul edilebilir 
  45. ^ Lewis, JP; Neumann, Ulrich. "C++'a karşı Java performansı" . Bilgisayar Grafikleri ve Sürükleyici Teknoloji Laboratuvarı, Güney Kaliforniya Üniversitesi.
  46. "Java HotSpot Performans Motoru: Yöntem Satır İçi Örneği" . Oracle Şirketi Erişim tarihi : 11 Haziran 2011 .
  47. ^ Nutter, Charles (3 Mayıs 2008). "JVM'nin Gücü" Erişim tarihi : 11 Haziran 2011 .B geldiğinde A'nın yöntemini zaten satır içine aldıysanız ne olur? Burada yine JVM parlıyor. JVM, temelde dinamik bir dil çalışma zamanı olduğu için, tam olarak bu tür olayların gerçekleşmesini izleyerek her zaman tetikte kalır. Ve işte gerçekten harika olan kısım: durumlar değiştiğinde, JVM'nin optimizasyonu kaldırılabilir. Bu çok önemli bir detay. Diğer birçok çalışma zamanı, optimizasyonlarını yalnızca bir kez yapabilir. C derleyicileri, derleme sırasında hepsini önceden yapmalıdır. Bazıları, uygulamanızın profilini çıkarmanıza ve bunu sonraki yapılara beslemenize izin verir, ancak bir kez bir kod parçası yayınladıktan sonra, esasen hiç olmadığı kadar optimize edilir. CLR gibi diğer VM benzeri sistemlerin bir JIT aşaması vardır, ancak bu, yürütmenin erken aşamalarında gerçekleşir (belki sistem çalışmaya başlamadan önce) ve bir daha asla olmaz.
  48. "Microbenchmarking C++, C# ve Java: 32-bit tamsayı aritmetiği" . Dobb'un Günlüğü . 1 Temmuz 2005 Erişim tarihi : 18 Ocak 2011 .
  49. "Microbenchmarking C++, C# ve Java: 64-bit double aritmetik" . Dobb'un Günlüğü . 1 Temmuz 2005 Erişim tarihi : 18 Ocak 2011 .
  50. "Microbenchmarking C++, C# ve Java: Dosya G/Ç" . Dobb'un Günlüğü . 1 Temmuz 2005 Erişim tarihi : 18 Ocak 2011 .
  51. "Microbenchmarking C++, C# ve Java: İstisna" . Dobb'un Günlüğü . 1 Temmuz 2005 Erişim tarihi : 18 Ocak 2011 .
  52. "Microbenchmarking C++, C# ve Java: Array" . Dobb'un Günlüğü . 1 Temmuz 2005 Erişim tarihi : 18 Ocak 2011 .
  53. "Microbenchmarking C++, C# ve Java: Trigonometric functions" . Dobb'un Günlüğü . 1 Temmuz 2005 Erişim tarihi : 18 Ocak 2011 .
  54. ^ Yi Zhao, Jin Shi, Kai Zheng, Haichuan Wang, Haibo Lin ve Ling Shao, Tahsis duvarı: ortaya çıkan çok çekirdekli platformlarda Java uygulamalarının sınırlayıcı bir faktörü , Nesne yönelimli programlama sistemleri dilleri ve uygulamaları üzerine 24. ACM SIGPLAN konferansının Bildirileri , 2009.
  55. ^ C4: Sürekli Eşzamanlı Kompakt Toplayıcı
  56. ^ Azul, Java'yı 768 çekirdekli makineyle zorbalık ediyor
  57. ".Net, Mono, Java, C++ ve ilgili kullanıcı arayüzleri için başlatma ve sistem performansını kıyaslama" . 2 Eylül 2010.
  58. "Yeni doğrulayıcı ne kadar hızlı?" 7 Şubat 2006. 16 Mayıs 2006 tarihinde kaynağından arşivlendi Erişim tarihi : 9 Mayıs 2007 .
  59. ^ Çivi tabancası
  60. ^ Nailgun Arka Plan sayfası , 33 katlık " en iyi durum senaryosu " hızlanma gösterir ( "Merhaba, Dünya!" yazılı programlar , yani kısa süreli programlar için).
  61. "Java nesnelerinin bellek kullanımı nasıl hesaplanır" .
  62. "InformIT: C++ Başvuru Kılavuzu > Nesne Modeli" . 21 Şubat 2008 tarihinde kaynağından arşivlendi Erişim tarihi : 22 Haziran 2009 .
  63. ^ https://www.youtube.com/watch?v=M91w0SBZ-wc  : Java Çöp Koleksiyonunu Anlamak - JavaOne'da Gil Tene tarafından yapılan bir konuşma
  64. ".: ToMMTi-Systems :: Kulissen modern 3D Donanımından Hinter" .
  65. "Matematik (Java Platformu SE 6)" . Güneş Mikrosistemleri Erişim tarihi : 8 Haziran 2008 .
  66. ^ Gosling, James (27 Temmuz 2005). "Transandantal Meditasyon" . 12 Ağustos 2011 tarihinde kaynağından arşivlendi Erişim tarihi : 8 Haziran 2008 .
  67. ^ Cowell-Shah, Christopher W. (8 Ocak 2004). "Dokuz Dil Performans Özeti: Matematik ve Dosya G/Ç Karşılaştırması" . 11 Ekim 2018 tarihinde kaynağından arşivlendi Erişim tarihi : 8 Haziran 2008 .
  68. ^ Wilson, Steve; Jeff Kesselman (2001). "JavaTM Platform Performansı: Yerel Kodu Kullanma" . Güneş Mikrosistemleri Erişim tarihi : 15 Şubat 2008 .
  69. ^ Kurzyniec, Dawid; Vaidy Sunderam. "Java ve Yerel Kodlar Arasında Verimli İşbirliği - JNI Performans Kıyaslaması" (PDF) . 14 Şubat 2005 tarihinde kaynağından (PDF) arşivlendi Erişim tarihi : 15 Şubat 2008 .
  70. ^ Bloch 2018 , s. 285, Bölüm §11 Madde 66: Yerel yöntemleri akıllıca kullanın.
  71. "JNA performansı, özel JNI ile karşılaştırıldığında nasıldır?" Güneş Mikrosistemleri Erişim tarihi : 26 Aralık 2009 .kalıcı ölü bağlantı ]
  72. ^ Igor, Križnar (10 Mayıs 2005). "SWT ve Swing Performans Karşılaştırması" (PDF) . cosylab.com. 4 Temmuz 2008 tarihinde kaynağından (PDF) arşivlendi Erişim tarihi : 24 Mayıs 2008 . SWT'nin Swing'den daha iyi performans göstereceği veya tam tersi olduğu durumlarda pratik bir kural vermek zordur. Bazı ortamlarda (örn. Windows), SWT kazanır. Diğerlerinde (Linux, Windows barındıran VMware ), Swing ve yeniden çizim optimizasyonu, SWT'den önemli ölçüde daha iyi performans gösterir. Performanstaki farklılıklar önemlidir: her iki yönde de 2 ve daha fazla faktör yaygındır 
  73. ^ Brian Amedro; Vladimir Bodnartçuk; Denis Caromel; Christian Delbe; Kumaş Huet; Guillermo L. Taboada (Ağustos 2008). "HPC için Java'nın Mevcut Durumu" . INRIA Erişim tarihi : 9 Eylül 2008 . İlk önce çeşitli JVM'ler için temel aritmetik işlemler(...) için genel olarak iyi performansı gösteren bazı mikro kıyaslamalar gerçekleştiriyoruz. Bu uygulamayı bir Fortran/MPI uygulamasıyla karşılaştırdığımızda, yoğun hesaplama ölçütlerinde benzer performansa sahip olduklarını, ancak yoğun iletişim gerçekleştirirken hala ölçeklenebilirlik sorunları yaşadıklarını gösteriyoruz.
  74. ^ Owen O'Malley - Yahoo! Izgara Hesaplama Ekibi (Temmuz 2008). "Apache Hadoop Terabyte Sıralama Testini Kazandı" . 15 Ekim 2009 tarihinde kaynağından arşivlendi Erişim tarihi : 21 Aralık 2008 . Bu, bir Java veya açık kaynak programının kazandığı ilk sefer.
  75. "Hadoop, Bir Petabaytı 16,25 Saatte ve Bir Terabaytı 62 Saniyede Ayırır" . CNET.com . 11 Mayıs 2009. 16 Mayıs 2009 tarihinde kaynağından arşivlendi Erişim tarihi : 8 Eylül 2010 . Donanım ve işletim sistemi ayrıntıları:(...)Sun Java JDK (1.6.0_05-b13 ve 1.6.0_13-b03) (32 ve 64 bit)
  76. "Hadoop, veri sıralama dünya rekorlarını kırdı" . CNET.com . 15 Mayıs 2009 Erişim tarihi : 8 Eylül 2010 .
  77. ^ Chris Nyberg; Mehul Şah. "Kıyaslama Ana Sayfasını Sırala" Erişim tarihi : 30 Kasım 2010 .
  78. ^ Czajkowski, Grzegorz (21 Kasım 2008). "1PB'yi MapReduce ile Sıralama" Erişim tarihi : 1 Aralık 2010 .
  79. "TCO10" . 18 Ekim 2010 tarihinde kaynağından arşivlendi Erişim tarihi : 21 Haziran 2010 .
  80. "Timus Çevrimiçi Hakem @ Java çözümleri nasıl yazılır" .
  81. "SSS" .
  82. "SSS | TJU ACM-ICPC Çevrimiçi Hakem" . 29 Haziran 2010 tarihinde kaynağından arşivlendi Erişim tarihi : 25 Mayıs 2010 .
  83. "SSS | CodeChef" .
  84. "Xidian Üniv. Çevrimiçi Hakem Ana Sayfası" . 19 Şubat 2012 tarihinde kaynağından arşivlendi Erişim tarihi : 13 Kasım 2011 .
  85. "SSS" .

Referanslar düzenle ]

  • Bloch, Yeşu (2018). "Etkili Java: Programlama Dili Kılavuzu" (üçüncü baskı). Addison-Wesley. ISBN 978-0134685991.

Dış bağlantılar değiştir ]

Rastgele İçerik

DonanımHaber

© tüm hakları saklıdır
made with by templateszoo