The biggest world global eCommerce - AliExpress has its own messaging and its source code looks interesting especially with claims "Throughout the period, 99.996% of the delay fell within 10ms, very few due to GC caused by the pause in 50ms or less, for the read and write ratio is almost balanced distributed message engine, the results are all exciting." which are about Java software.
With first look following can be spotted: heavy usage of java.util.concurrent, volatile keyword, ByteBuffers and very limited usage of synchronized blocks. File storage uses plain RandomAccessFile with OS-mapped ByteBuffers where everything read and written is with computed offsets. Flushing data to disk is performed in file groups which is very wise due to mechanical sympathy with underlying disks (think about hardware I/O queues and servicing according to given offsets). Memory storage uses direct ByteBuffers not affected by GC and also locked into physical memory with POSIX mlock call. Very smart! I was exploiting the last feature while writing near RealTime software for T-Mobile emergency number. It really helps to achieve low latency without outliers.
Pokazywanie postów oznaczonych etykietą real-time. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą real-time. Pokaż wszystkie posty
piątek, kwietnia 21, 2017
wtorek, stycznia 27, 2015
JMS datastore replication: performance with enterprise server
source: sync-msgs.db 5GB, GFS2
target: EXT4
serial: WALL TIME: 121sec 133msec
sendfile: WALL TIME: 113sec 264msec
default: WALL TIME: 64sec 7msec
mmap: WALL TIME: 142sec 57msec
aio: WALL TIME: 8sec 791msec
piątek, listopada 23, 2012
czwartek, marca 31, 2011
Prevent JVM from swapping
import com.sun.jna.Native;
public final class LIBC {public static final int MCL_CURRENT = 1;
public static final int MCL_FUTURE = 2;
static {
Native.register("c");
}
public static native int mlockall(int flags);
public static native int munlockall();
private LIBC() {}
}LIBC.mlockall(LIBC.MCL_CURRENT | LIBC.MCL_FUTURE);
On Solaris box you can do: -XX:+UseISM
poniedziałek, lipca 05, 2010
sobota, lipca 03, 2010
SLA Real-Time (Linux x86)
Napiszmy sobie prosty i szybki serwerowy kod Javy, który powinien wyrabiać się po stronie klienta w milisekundach (w idealnych warunkach czas działania zależy od czasu stosu TCP/IP) - serwer WWW zwracający aktualną datę.Do tego mały zły programik w C zużywający sporo cykli procesora tudzież alokujący sporo pamięci (system operacyjny przez niego będzie używał swapa)
Mamy zasymulowany obciążony serwer aplikacyjny. Programy napisane w Javie i C działają na kontach różnych użytkowników.
Na wykresie widzimy system ze zwykłą Javą 6.0 od Sun-a. Konfiguracja out-of-box. Na osi pionowej czas odpowiedzi serwera JEE w milisekundach.
Spójrzmy jeszcze na JRockit-a RT 4.0 (RT oznacza deterministyczny garbage collector). Prawie idealnie. Gdyby poprzez bibliotekę w C i JNI zawołać mlockall, mielibyśmy wyniki spełniające SLA RT.
piątek, września 11, 2009
Prstat
27109 adinstan 469M 323M cpu1 30 0 209:37:17 35% bwengine/64Proces skacze po procesorach. Można go dowiązać narzędziami psrset+pbind, co powinno zmniejszyć opóźnienia (ważna rzecz dla np. aplikacji RT).
27109 adinstan 469M 323M cpu17 20 0 209:37:45 35% bwengine/64
27109 adinstan 469M 323M cpu16 20 0 209:38:14 35% bwengine/64
27109 adinstan 469M 323M cpu17 20 0 209:38:56 35% bwengine/64
27109 adinstan 469M 323M cpu18 20 0 209:39:10 35% bwengine/64
27109 adinstan 469M 323M cpu0 10 0 209:39:24 35% bwengine/64
27109 adinstan 469M 323M cpu2 10 0 209:39:38 35% bwengine/64
27109 adinstan 469M 323M cpu19 10 0 209:40:07 35% bwengine/64
sobota, marca 28, 2009
StringMaker
public class StringMaker {
private ArrayList<string> strings = new ArrayList<string>();
public StringMaker append(Object p) {
strings.add(String.valueOf(p));
return this;
}
public String toString() {
int cnt=0, p=0, l=0;
for (String s : strings) {
cnt +=s.length();
}
char[] value = new char[cnt];
for (String s : strings) {
l = s.length();
s.getChars(0, l, value, p);
p+=l;
}
return new String(value);
}
}
public class Test1 {
private final static String S = "private ArrayList<String> strings = new ArrayList<String>()";
public long[] test1() {
Random r = new Random(System.currentTimeMillis());
StringMaker sm = new StringMaker();
long t1 = System.currentTimeMillis();
for (int i=0; i < 100000; i++) {
sm.append(S.substring(r.nextInt(40)));
}
String result = sm.toString();
long t2 = System.currentTimeMillis();
return new long[] { t2-t1, result.length() };
}
// test2 - to samo na StringBufferze
// test3 - to samo na StringBuilderze
// test4 - to samo na StringBufferze(4000000)
}
BEA JRockit(R) (build R27.6.0-50_o-100423-1.6.0_05-20080626-2104-linux-ia32, compiled mode):
n=100 test1: 50ms, 3950201 chars
n=100 test2: 77ms, 3949690 chars
n=100 test3: 77ms, 3950259 chars
n=100 test4: 41ms, 3950640 chars
Java HotSpot(TM) Client VM (build 11.0-b16, mixed mode, sharing):
n=100 test1: 92ms, 3951062 chars
n=100 test2: 118ms, 3949873 chars
n=100 test3: 118ms, 3950118 chars
n=100 test4: 36ms, 3950035 chars
IBM J9 VM (build 2.4, J2RE 1.6.0 IBM J9 2.4 Linux x86-32 jvmxi3260-20090215_29883 (JIT enabled, AOT enabled):
n=100 test1: 64ms, 3949910 chars
n=100 test2: 70ms, 3950291 chars
n=100 test3: 70ms, 3950410 chars
n=100 test4: 31ms, 3949690 chars
niedziela, lipca 13, 2008
Poprawki dla 2.6.25.10-rt7
Siadłem nad tym kernelem i doprowadziłem go do stanu używalności na moim laptopie:libata: fix locking for kmap_atomic
pm_qos_params: change spinlock to rwlock
no i oczywiście żeby się kompilowało w kernel/sched.c trzeba dodać:
static inline u64 global_rt_runtime()Tak przy okazji - mocny motyw:
{
if (sysctl_sched_rt_period < 0)
return RUNTIME_INF;
return (u64)sysctl_sched_rt_runtime * NSEC_PER_USEC;
}
niedziela, stycznia 20, 2008
glibc_malloc vs alloca => 166197 / 1536 = ~100
localhost systest_modules # ./malloc
Ustawianie maski procesorow na 1
-- SYSTEM INFO -------------------
localhost: Linux 2.6.24-rc7 #6 SMP PREEMPT Mon Jan 14 16:50:37 CET 2008
Ustawianie priorytetu dla SCHED_OTHER na 0 (zwykly proces) dla 29488
*** TIMED: Instrukcja: 'tab[++i] = malloc_sbrk(100);'
*** TIMED: 0sec 9357nsec +- 1nsec
Addr: 804c000
*** TIMED: Instrukcja: 'tab[++i] = malloc_mmap(100);'
*** TIMED: 0sec 8449nsec +- 1nsec
Addr: b7f0e000
*** TIMED: Instrukcja: 'tab[++i] = malloc_stos(100);'
*** TIMED: 0sec 1536nsec +- 1nsec
Addr: bf806550
*** TIMED: Instrukcja: 'tab[++i] = malloc_libc(100);'
*** TIMED: 0sec 166197nsec +- 1nsec
Addr: 804c070
Ustawianie priorytetu dla SHED_FIFO na 99 (zakres 1-99) dla 29488
*** TIMED: Instrukcja: 'tab[++i] = malloc_sbrk(100);'
*** TIMED: 0sec 5446nsec +- 1nsec
Addr: 806d000
*** TIMED: Instrukcja: 'tab[++i] = malloc_mmap(100);'
*** TIMED: 0sec 6495nsec +- 1nsec
Addr: b7f0d000
*** TIMED: Instrukcja: 'tab[++i] = malloc_stos(100);'
*** TIMED: 0sec 1396nsec +- 1nsec
Addr: bf806550
*** TIMED: Instrukcja: 'tab[++i] = malloc_libc(100);'
*** TIMED: 0sec 1816nsec +- 1nsec
Addr: 804c070
A kod wyglądał tak:
#include "framework.h"
#include
inline void* malloc_sbrk(int size) {
/* Poszerzenie przestrzeni adresowej programu */
void *addr = sbrk(size);
if (addr == (void*)-1)
addr = NULL;
return addr;
}
inline void* malloc_mmap(int size) {
/* Alokacja pamieci za pomoca mmap */
void *addr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
if (addr == (void*)-1)
addr = NULL;
return addr;
}
inline void* malloc_stos(int size) {
/* Alokacja pamieci na stosie */
return alloca(size);
}
inline void* malloc_libc(int size) {
return malloc(size);
}
void test_malloc(int rt) {
int i = 0;
void* tab[10];
RT_ON(rt);
#define CHECK_OK() do { \
printf("Addr: %x\n\n",(unsigned int)tab[i]); \
if (tab[i] == NULL) SHOW_ERR(); \
} while(0);
TIMED(
tab[++i] = malloc_sbrk(100);
);
CHECK_OK();
TIMED(
tab[++i] = malloc_mmap(100);
);
CHECK_OK();
TIMED(
tab[++i] = malloc_stos(100);
);
CHECK_OK();
TIMED(
tab[++i] = malloc_libc(100);
);
CHECK_OK();
free(tab[i]);
}
int main(int argc, char **argv) {
one_cpu();
uname_info();
test_malloc(0);
test_malloc(1);
return 0;
}
sobota, stycznia 19, 2008
Systest 20080119
Poprawiłem wreszcie systest, żeby dawał sensowne rezultaty na systemach z więcej niż jednym procesorem. Jest to zestaw programów wykorzystujących API POSIX 1.b mierzący np. czas przełączania sie dwóch procesówużywających tego samego semafora.
Z tej samej beczki: Intel wypuścił narzędzie do badania opóźnień w systemie - http://www.latencytop.org. Nazwa nawiązuje do powertopa mierzącego przez jak długi czas procesor znajduje się w danym stanie snu (C1, C2, C3...) i co go budzi. U mnie procesor przeważnie jest budzony przez ndiswrappera. LatencyTOP wymaga linuksa 2.6.24-rc7 (na razie są patche tylko na to jądro).
Z podobnej beczki: Jak ktoś ogląda commity od 2.6.24 rc, to widać, że ludzie używają inftrastruktury RT, którą do jądra wrzucił Ingo Molnar, a pozwala ona odnaleźć błędy, które siedziały w kernelu latami. Tak więc przy okazji robienia jądra realtime zyskują wszyscy.
sobota, grudnia 01, 2007
Dorwałem ostatnio JamaicaVM od firmy Aicas - JVM czasu rzeczywistego. Ma to jedną dużą binarkę z wszystkimi systemowymi rzeczami wkompilowanymi statycznie, binarka jest stripped także w nm nie można nic zobaczyc. Linia polecen Jamajki jest niekompatybilna ze zwykłą Javą - nie można odpalić Eclipse'a (jakich przerzutek używa Eclipse można zobabaczyć w eclipse.ini). Co ciekawe Jamaica potrafi kod Javy skompilować do statycznej binarki. Fajne. Można tego używać pod Eclipsem - producent dostarcza stosowny plugin pozwalający w IDE wybrać JRE (Jak powszechnie wiadomo Eclipse nie potrzebuje JDK i javac, bo ma własny kompilator ECJ).
A poza tym to trochę się boję Pawlaka jako ministra od gospodarki...
A poza tym to trochę się boję Pawlaka jako ministra od gospodarki...
Subskrybuj:
Posty (Atom)









