Czy .NET Core jest szybszy od Javy?

0

Tyle się mówi o tym, jaka to JVM jest szybka, a w tym benchmarku nie wypada lepiej od .NET Core'a pod względem szybkości.
https://benchmarksgame-team.pages.debian.net/benchmarksgame/faster/csharp.html

Jak to w końcu jest?

0

ZTCP to jeszcze niedawno .NET Core był trochę wolniejszy w tych benchmarkach. Jak widać poprawili w .NETu szybkość działania na tablicach. Daleko jednak tym benchmarkom do typowego biznesowego OOPa, a siłą JVMa są takie mechanizmy jak dewirtualizacja metod czy escape analysis. Ponadto w kodzie C# można uświadczyć takie kwiatki jak:

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    static unsafe byte GetByte(double* pCrb, double Ciby)
unsafe public static class NBody_StructPtr2 {
    struct NBody { public double x, y, z, vx, vy, vz, mass; }

    public static void Main(string[] args) {
        unchecked {   

// There doesn't seem to be a difference between 
// using stackalloc or fixed pointer.  
// stackalloc uses fewer lines though. 

            NBody* ptrSun = stackalloc NBody[5];   
            NBody* ptrEnd = ptrSun+4;              

Musieli narobić trochę dziadostwa by o odrobinę prześcignąć Javę. Nie martwcie się jednak, kolejna rundka już wkrótce :) Pojedyncze wyniki Javowego JITa nowej generacji są tutaj: http://www.graalvm.org/docs/examples/java-performance-examples/ W sumie mógłby ktoś odpalić te benchmarks game na GraalVMie. Sprawa by się rozjaśniła. Na chwilę obecną jednak fakty są takie, że .NET Core jest odrobinę szybszy od Javy w operacjach na tablicach w Benchmarks Game.

Do zastosowań webowych znacznie lepszym benchmarkiem jest TechEmpower Web Framework Benchmarks Round #15. Programy to dalej mini popierdółki, ale przynajmniej to aplikacje webowe, a nie operacje na tablicach. Z drugiej strony w tych benchmarkach TechEmpower dużą rolę odgrywają frameworki webowe oprócz samej VMki (co jest w sumie na plus, bo każdy normalny człowiek korzysta z jakiegoś frameworku czy biblioteki do stawiania aplikacji webowej, a nie pisze do socketów bezpośrednio).

0

Wibowit, wnoszę po tonie Twego postu, nie lubisz .NET?

Zechciałbyś rozwinąć, dlaczego?

(Pytam, bo niniejszym dłubię coś w .NET core, to i ciekaw jestem opinii, jeśli ktoś uważa tę platformę za zło?)

5

Po prostu Wibowit nie ogarnia wskaźników, więc gwiazdki w kodzie na zasadzie dziecinnych skojarzeń nazywa "kwiatkami". Podobnie | to dla niego "rurka pionowa", a & to "jakiś pojebany zawijas".

A co do tematu - wszystkie sztuczne benchmarki są niewiele warte, bo w prawdziwych projektach całą potencjalną wydajność platformy można zjechać skopaną architekturą. (I tak się zazwyczaj dzieje.)

1
Mały Programista napisał(a):

Wibowit, wnoszę po tonie Twego postu, nie lubisz .NET?

Zechciałbyś rozwinąć, dlaczego?

(Pytam, bo niniejszym dłubię coś w .NET core, to i ciekaw jestem opinii, jeśli ktoś uważa tę platformę za zło?)

W zasadzie to mi zwisa i powiewa co się dzieje w .NETu tak samo jak niespecjalnie interesuje mnie Node.js czy Google Go. Nie widzę wspaniałości w tych rozwiązaniach. Sam programuję w Scali i uważam, że to znacznie lepszy język niż C#, JS, Go itp itd Mam prawo do swojej opinii tak samo jak C#-owcy twierdzący, że C# jest optymalny, a bajery ze Scali tylko przeszkadzają, bądź JS-owcy czy Pythonowcy lubiący brak statycznego typowania. Jako, że standardowym backendem dla Scali jest platforma Java to jestem na bieżąco z Javą.

somekind napisał(a):

Po prostu Wibowit nie ogarnia wskaźników, więc gwiazdki w kodzie na zasadzie dziecinnych skojarzeń nazywa "kwiatkami". Podobnie | to dla niego "rurka pionowa", a & to "jakiś pojebany zawijas".

Niestety Onet skasował moją stronę o asemblerze (asembler.republika.pl), którą stworzyłem chyba jeszcze w gimnazjum, ale za to zapraszam na mojego GitHuba: https://github.com/tarsa Są algorytmy w C, C++ i Ruście :] Wskaźników jest tam sporo, pojebanych zawijasów też.

Nie sądzę, by chwalenie się wydajnością kodu oznaczonego jako unsafe było sensowne. Nie po to wybiera się platformę programistyczną dającą szereg gwarancji dotyczących bezpieczeństwa kodu, by je ominąć dla kilku procent wydajności. W Javce też jest klasa sun.misc.Unsafe i można z jej pomocą robić wysokowydajne grożne potworki, ale ta klasa jest na wylocie i ma być zastąpiona przez bezpieczne alternatywy, które nie łamią standardowych gwarancji.

1

Użyteczność języka, czy jego opłacalność dawno już się nie mierzy prędkością danego języka.
Mówimy o różnicy kilku procent, a w przypadku często stosowanego dziś modelu aplikacji webowych znacznie dłuższe jest oczekiwania na bazę czy transfer pomiędzy serwerem i klientem.

1
Wibowit napisał(a):

Niestety Onet skasował moją stronę o asemblerze (asembler.republika.pl), którą stworzyłem chyba jeszcze w gimnazjum

No cóż, nie pierwszy to raz, gdy niemieckie media niszczą polską myśl techniczną. Masz piosenkę na pocieszenie.

Nie sądzę, by chwalenie się wydajnością kodu oznaczonego jako unsafe było sensowne. Nie po to wybiera się platformę programistyczną dającą szereg gwarancji dotyczących bezpieczeństwa kodu, by je ominąć dla kilku procent wydajności.

Nikt nie wyłącza przecież GC dla kodu biznesowego z setkami alokowanych obiektów, tylko dla małych fragmentów kodu realizujących operacje na blokach pamięci. C# od początku był przemyślany do takiego działania, stąd słowa kluczowego unsafe, stackallock i fixed.

0
somekind napisał(a):

Nikt nie wyłącza przecież GC dla kodu biznesowego z setkami alokowanych obiektów, tylko dla małych fragmentów kodu realizujących operacje na blokach pamięci. C# od początku był przemyślany do takiego działania, stąd słowa kluczowego unsafe, stackallock i fixed.

W kodzie C# dla nbody na benchmarksgame wszystko jest alokowane na stosie i wszystkie metody operują na wskaźnikach zamiast referencji: https://benchmarksgame-team.pages.debian.net/benchmarksgame/program/nbody-csharpcore-7.html Nawet pętle wyglądają jakby były żywcem wyjęte z C - jest ręczne przesuwanie wskaźników.

0

No i ile tam jest obiektów?

0

A co to ma za znaczenie? Jakby zamiast 5 było 55555 to co wtedy? Autorzy tego koszmarka w C# sami napisali:

// There doesn't seem to be a difference between
// using stackalloc or fixed pointer.
// stackalloc uses fewer lines though.

Zamieniasz stackalloc na fixed pointer i możesz mieć 5555555 obiektów.

Błędogenność nie zależy liniowo od wielkości zaalokowanej pamięci. To nie jest tak, że jak zaalokujesz 5x więcej obiektów to będzie 5x większa szansa na pojawienie się błędu.

0

Ja was obu pogodzę:

nbody:
Java - 22.17
C# .NET Core - 21.39
C++ g++ - 8.24

0
Wibowit napisał(a):

A co to ma za znaczenie?

GC ma zastosowanie w złożonych aplikacjach, nie w zabawkach typu mikrobenchmarki. GC stosuje się po to, aby zdjąć z programisty ciężar ręcznego odśmiecania i uniknąć problemów z wyciekaniem pamięci poprzez gubienie referencji. W przypadku programiku takiego jak ten - krótko żyjącego, w którym nie ma żadnych referencji i wszystko jest statyczne, GC niczego nie daje, więc pozbycie się go nie jest problemem.

0

W zasadzie to w microbenchmarkach nieważny jest nie tylko GC, ale także JIT, OOP, jakiekolwiek gwarancje bezpieczeństwa, zarządzanie zasobami, asynchroniczne konstrukcje, itp itd Można to wszystko wyłączyć i testować scenariusze totalnie oderwane od typowych zastosowań dla Javy i C# (czyli aplikacji webowych). To trochę jakby testować Ferrari przed zakupem na polu buraków zamiast na niemieckiej autostradzie.

0
Wibowit napisał(a):

To trochę jakby testować Ferrari przed zakupem na polu buraków zamiast na niemieckiej autostradzie.

Raczej jakby testować Jeepa / Hummera na niemieckiej autostradzie. Wlecze się, ciągle sobie jednak przypominasz, że przecież ten samochód ma masę zalet, tylko na innym, nomen-omen, polu.

0

Z ciekawości chciałem odpalić ten nbody benchmark u siebie. Wyniki mam takie: dla Javy czas to ok 5.3s, a dla C to ok 3.5s. Różnica znacznie mniejsza niż na samej stronie benchmarksgame.

Jak odpailć wersję C#? Zainstalowałem .NET Core na Ubuntu 16.04, ale nie wiem jak skompilować program z linii komend i go odpalić w taki sam sposób jak odpalają go na benchmarksgame (czyli np z System.GC.Server = true itd). Jest coś takiego:

notes, command-line, and program output
NOTES:
64-bit Ubuntu quad core
sdk/2.1.300
.NETCore.App 2.1.0
"System.GC.Server": true


Wed, 06 Jun 2018 03:33:16 GMT

MAKE:
cp nbody.csharpcore-7.csharpcore Program.cs
cp Include/csharpcore/tmp.csproj .
cp Include/csharpcore/runtimeconfig.template.json .
mkdir obj
cp Include/csharpcore/tmp.csproj.nuget.g.props ./obj
cp Include/csharpcore/tmp.csproj.nuget.g.targets ./obj
/usr/bin/dotnet build -c Release
Microsoft (R) Build Engine version 15.7.179.6572 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restoring packages for /home/dunham/benchmarksgame_quadcore/nbody/tmp/tmp.csproj...
  Generating MSBuild file /home/dunham/benchmarksgame_quadcore/nbody/tmp/obj/tmp.csproj.nuget.g.props.
  Restore completed in 270.62 ms for /home/dunham/benchmarksgame_quadcore/nbody/tmp/tmp.csproj.
  tmp -> /home/dunham/benchmarksgame_quadcore/nbody/tmp/bin/Release/netcoreapp2.1/tmp.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:02.35

2.98s to complete and log all make actions

COMMAND LINE:
/usr/bin/dotnet ./bin/Release/netcoreapp2.1/tmp.dll 50000000

PROGRAM OUTPUT:
-0.169075164
-0.169059907

Skąd się biorą te wszystkie kopiowane pliki?

0

dotnet build -c Release buduje projekt w konfiguracji Release. Potem uruchamiasz przez dotnet Aplikacja.dll.

0

dotnet new console -o App1 wygeneruje ci nową aplikację w katalogu App1. Podmień zawartość pliku Program.cs na swoją. W pliku .csproj dodaj w jakiejś sekcji <PropertyGroup>

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

A potem już dotnet build -c Release. I wynik masz w katalogu bin/Release/netcoreapp2.0 (czy tam 2.1, w zależności jaką masz wersję).

0

Nie przejmowałbym się benchmarkami bo z benchmarków wynika tylko kto napisał szybszą appkę pod danego benchmarka. Język jest prawie zawsze bez znaczenia - używaj tego co Ci pomoże skończyć szybciej projekt, a perf ulepszysz jak będzie Ci to potrzebne (jak zrobisz drugiego facebooka to będzie Cie stać na przepisanie kodu z dowolnego języka na dowolny jeśli będzie taka potrzeba).

1

.NET Core poradził sobie całkiem dobrze na tej wersji z unsafe/ unchecked. Dorzuciłem dla porównania program o nazwie "n-body C# .NET Core #3". Wyniki dla nbody przy nieobciążonym kompie (Ubuntu 16.04, Core i5-4670 @ 3.8 GHz), parametry kompilacji takie jak podane przy kodzie każdej wersji:

platforma | wersja programu | czas

  • | - | -
    .NET Core 2.1.300 | bez unsafe/ unchecked (n-body C# .NET Core #3) | 5.5s
    Java 8u171 | (n-body Java #4) | 5.2s
    .NET Core 2.1.300 | z unsafe/ unchecked (n-body C# .NET Core #7) | 4.7s
    GCC 5.4.0 | z ręcznymi optymalizacjami SIMD (n-body C gcc #4) | 3.5s

Trzeba wziąć pod uwagę, że wersja w C używa wprost XMM intrinsics, a jedna z wersji w C# używa gołych (czyli chyba niezarządzanych/ niesprawdzanych/ etc?) wskaźników. Java w wersji 11 będzie mieć EpsilonGC (czyli brak GC) i wtedy narzut GC na benchmark powinien być w dużej mierze wyeliminowany (jak nie zapomnę to się pobawię benchmarks game pod oficjalną Javą 11). Wersję C# odpalałem z włączoną opcją <ServerGarbageCollection>true</ServerGarbageCollection> ale nie miała ona widocznego wpływu na wydajność w tym benchmarku.

2

A tak na poważnie - co za różnica, czy szybszy jest .NET, Java, PHP czy C, skoro i tak to wszystko będzie przykryte frontendem w Angularze, który będzie się ładował 30 sekund?

1 użytkowników online, w tym zalogowanych: 0, gości: 1