1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-05-01 01:03:09 +00:00
Commit graph

1609 commits

Author SHA1 Message Date
Niklas Fiekas
ee7a68ea5f Fix last search info carried over to mate position
When starting search in a mate or stalemate position, Stockfish does not
even care to reinitialize and start worker threads. However after search
all threads are checked for the best move.

This can lead to bestmove and info beeing carried over from the last
search.

Example session:

    setoption name threads value 7
    go movetime 4000
    position startpos moves f2f3 e7e5 g2g4 d8h4
    go movetime 4000

Actual output is like (almost always):

    [...]
    bestmove e2e4
    info depth 0 score mate 0
    info depth 20 seldepth 29 multipv 1 score cp 28 [...] pv e2e4
    bestmove e2e4

Expected output / output after fix:

    [...]
    bestmove e2e4 ponder e7e6
    info depth 0 score mate 0
    bestmove (none)

Resolves #623
2016-04-16 10:22:36 +01:00
Marco Costalba
647402ff79 Assorted cleanup of latest commits
No functional change.

Resolves #601
2016-03-14 20:42:44 -07:00
Stefan Geschwentner
a273b6ef8c Add followup moves history for move ordering
STC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 7955 W: 1538 L: 1378 D: 5039

LTC:
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 5323 W: 778 L: 642 D: 3903

Bench: 8261839

Resolves #599
2016-03-10 14:26:06 -08:00
ElbertoOne
c13052f344 Clean up depth reduction calculation
Might also be a slight speed up

No functional change

Resolves #593
2016-02-28 13:40:47 +00:00
VoyagerOne
45a309d92e Simplify Reduction Formula
Formula now only contains one coefficient. Making it much easier to tune.

STC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 187443 W: 34858 L: 35028 D: 117557

LTC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 88329 W: 11982 L: 11953 D: 64394

Bench: 7521394

Resolves #591
2016-02-28 13:31:25 +00:00
VoyagerOne
744ed85a4d Fix futility pruning bug
PredictedDepth can be negative, causing the futility_margin to be negative.
It will be very difficult to tweak moveCount pruning and reduction formula, as they are tuned to prevent this behavior.

No functional change

Resolves #587
2016-02-14 19:48:46 +00:00
Marco Costalba
4f6aa15228 Document HalfDensityMap
No functional change.

Resolves #584
2016-02-07 20:54:25 +00:00
Leonid Pechenik
aedebe35cf Time management simplification
10+0.1:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 41963 W: 7967 L: 7883 D: 26113

60+0.6:
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 132314 W: 17939 L: 17969 D: 96406

Resolves #580
2016-01-29 00:47:07 +00:00
Guenther Demetz
9a10313a9d rotating symmetric patterns with increasing skipsize
STC:
LLR: 2.95 (-2.94,2.94) [0.00,5.00] sprt @ 5+0.1 th 21
Total: 7068 W: 1121 L: 975 D: 4972

LTC:
LLR: 2.96 (-2.94,2.94) [-3.00,1.00] sprt @ 12+0.12 th 21
Total: 26691 W: 3594 L: 3481 D: 19616

No functional change with a single thread

Resolves #574
2016-01-24 14:08:01 +00:00
Joona Kiiski
8c3a5bbc52 Do not probe syzygy bases when castling is possible
Almost no functional change. Bench is unchanged.

Resolves #230
Resolves #573
2016-01-20 15:24:21 +00:00
lucasart
28933a580e Retire RootNode template
There is no reason to compile 3 different copies of search(). PV nodes are on
the cold path, and PvNode is a template parameter, so there is no cost in
computing:

const bool RootNode = PvNode && (ss-1)->ply == 0;

And this simplifies code a tiny bit as well.

Speed impact is negligible on my machine (i7-3770k, linux 4.2, gcc 5.2):

            nps   +/-
test    2378605  3118
master  2383128  2793
diff      -4523  2746

Bench: 7751425

No functional change.

Resolves #568
2016-01-18 22:21:42 +00:00
Marco Costalba
356147d99a Rewrite time formula
Time management is really too complex, our aim is
to simplify it, but for time being at least rewrite
in an understandable way.

No functional change.
2016-01-18 17:12:18 +01:00
Lyudmil Antonov
89723339d9 Assorted English grammar changes
No functional change

Resolves #567
2016-01-16 21:34:29 +00:00
Stefano80
74e2fa97b7 Adjust reductions based on history and cmh tables
STC:
LLR: 4.06 (-2.94,2.94) [0.00,5.00]
Total: 149395 W: 28029 L: 27208 D: 94158

LTC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 9628 W: 1368 L: 1217 D: 7043

bench: 8076724

Resolves #565
2016-01-13 16:18:35 +00:00
Stefano80
dcd8ce7094 Update comments in LMR step
No functional change

Resolves #564
2016-01-13 16:03:53 +00:00
Leonid Pechenik
9eceb894ac Adjust time used for move based on previous score
Use less time if evaluation is not worse than for previous move and even less time if in addition no fail low encountered for current iteration.

STC: 10+0.1
ELO: 5.37 +-2.9 (95%) LOS: 100.0%
Total: 20000 W: 3832 L: 3523 D: 12645

STC: 10+0.1
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 17527 W: 3334 L: 3132 D: 11061

LTC: 60+0.6
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 28233 W: 3939 L: 3725 D: 20569

LTC: 60+0.6
ELO: 2.43 +-1.4 (95%) LOS: 100.0%
Total: 60000 W: 8266 L: 7847 D: 43887

LTC: 60+0.06
LLR: 2.95 (-2.94,2.94) [-1.00,3.00]
Total: 38932 W: 5408 L: 5207 D: 28317

Resolves #547
2016-01-03 14:01:15 +00:00
ppigazzini
d4af15f682 Update AUTHORS and copyright notice
No functional change

Resolves #555
2016-01-02 09:43:51 +00:00
Marco Costalba
9742fb10fd Update Copyright year
No functional change.

Resolves #554
2016-01-01 10:17:36 +00:00
Marco Costalba
1b5b900a29 Move some globals into main thread scope
Make it explicit that those variables are not globals, but
are used only by main thread. I think it is a sensible
clarification because easy move is already tricky enough
and current patch makes the involved actors explicit.

No functional change.

Resolves #537
2015-12-27 19:29:16 +00:00
DU-jdto
e3c85c314d Remove another unnecessary Search::Stack field
No functional change

Resolves #535
2015-12-22 17:16:15 +00:00
VoyagerOne
ed72a1e9ba Remove killer move conditions from LMR
STC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 8459 W: 1619 L: 1477 D: 5363

LTC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 32239 W: 4404 L: 4299 D: 23536

Bench: 7597031

Resolves #534
2015-12-20 20:41:17 +00:00
loco-loco
5bbd944099 Remove unused field SearchStack::ttMove
No functional change

Resolves #533
2015-12-20 20:37:18 +00:00
Guenther Demetz
38adb487ca Distinct iteration paths for Lazy SMP threads
STC 5+0.1, threads 7
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 6026 W: 1047 L: 901 D: 4078

LTC: 20+0.2, threads 7
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 19739 W: 2910 L: 2721 D: 14108

STC 5+0.1, threads 20
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 2493 W: 462 L: 331 D: 1700

LTC 30+0.3, threads 20
ELO: 8.86 +-3.7 (95%) LOS: 100.0%
Total: 8000 W: 1076 L: 872 D: 6052

Bench: 8012530

Resolves #525
2015-12-18 21:59:09 +00:00
mstembera
2c1797ab81 Fix easy move bug in SMP mode
Fix a bug where we could stop the search after only 10% of time used due to a matching easy move but later switch to a different move that was never pre-screened as easy due to SMP thread select.

STC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 27227 W: 4910 L: 4800 D: 17517

LTC:
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 40368 W: 5826 L: 5733 D: 28809

Resolves #521
2015-12-14 18:47:12 +00:00
Leonid Pechenik
69240a982d Simplify time management and fix 'ponder on' bug
Simplify time management code by removing hard stops for unchanging first root moves.
Search is now stopped earlier at the end iteration if it did not have fail-lows at root.

This simplification also fixes pondering bug. Ponder flag was true by default
and cutechess-cli doesn't change it to false even though no pondering is possible.
Fix the issue by setting the default value of 'Ponder' flag to false.

10+0.1:
ELO: 3.51 +-3.0 (95%) LOS: 99.0%
Total: 20000 W: 3898 L: 3696 D: 12406

40+0.4:
ELO: 1.39 +-2.7 (95%) LOS: 84.7%
Total: 20000 W: 3104 L: 3024 D: 13872

60+0.06:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 37231 W: 5333 L: 5236 D: 26662

Stopped run at 100+1:
LLR: 1.09 (-2.94,2.94) [-3.00,1.00]
Total: 37253 W: 4862 L: 4856 D: 27535

Resolves #523
Fixes #510
2015-12-14 18:00:52 +00:00
mstembera
7904a7d930 Fix MultiPv and Skill in SMP.
7 threads, 5+0.1:
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 55460 W: 9665 L: 9601 D: 36194

No functional change in normal playing mode
2015-12-12 10:32:28 +00:00
Marco Costalba
93195555ed Rewrite how threads are spawned
Instead of creating a running std::thread and
returning, wait in Thread c'tor that the native
thread of execution goes to sleep in idle_loop().

In this way we can simplify how search is started,
because when main thread is idle we are sure also
all other threads will be idle, in any case, even
at thread creation and startup.

After lazy smp went in, we can simpify and rewrite
a lot of logic that is now no more needed. This is
hopefully the final big cleanup.

Tested for no regression at 5+0.1 with 3 threads:
LLR: 2.95 (-2.94,2.94) [-5.00,0.00]
Total: 17411 W: 3248 L: 3198 D: 10965

No functional change.
2015-11-21 07:48:50 +01:00
VoyagerOne
07e0741dfb History Pruning: Don't prune the main killer move.
Also increased pruned depth to 4.

STC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 23380 W: 4581 L: 4350 D: 14449

LTC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 28934 W: 4329 L: 4105 D: 20500

Bench: 8369743

Resolves #498
2015-11-15 20:40:09 -08:00
Marco Costalba
76ed0ab501 Retire ThreadBase
Now that we don't have anymore TimerThread, there is
no need of this long class hierarchy.

Also assorted reformatting while there.

To verify no regression, passed at STC with 7 threads:
LLR: 2.97 (-2.94,2.94) [-5.00,0.00]
Total: 30990 W: 4945 L: 4942 D: 21103

No functional change.
2015-11-13 08:22:44 +01:00
Marco Costalba
ce84ab6e9d Fix broken UCI 'wait for stop'
When we reach the maximum depth, we can finish the
search without a raise of Signals.stop. However, if
we are pondering or in an infinite search, the UCI
protocol states that we shouldn't print the best move
before the GUI sends a "stop" or "ponderhit" command.

It was broken by lazy smp. Fix it by moving the stopping
of the threads after waiting for GUI.

No functional change.
2015-11-13 08:13:59 +01:00
lucasart
e6eeb17aa6 Ensure that rootDepth < DEPTH_MAX
Indeed, if we use a depth >= DEPTH_MAX, we start having negative depth in the
TT (due to int8_t cast).

No functional change in single thread mode

Resolves #490
2015-11-10 21:41:42 +00:00
Marco Costalba
9c9205860c Get rid of timer thread
Unfortunately std::condition_variable::wait_for()
is not accurate in general case and the timer thread
can wake up also after tens or even hundreds of
millisecs after time has elapsded. CPU load, process
priorities, number of concurrent threads, even from
other processes, will have effect upon it.

Even official documentation says: "This function may
block for longer than timeout_duration due to scheduling
or resource contention delays."

So retire timer and use a polling scheme based on a
local thread counter that counts search() calls and
a small trick to keep polling frequency constant,
independently from the number of threads.

Tested for no regression at very fast TC 2+0.05 th 7:
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 32969 W: 6720 L: 6620 D: 19629

TC 2+0.05 th 1:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 7765 W: 1917 L: 1765 D: 4083

And at STC TC, both single thread
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 15587 W: 3036 L: 2905 D: 9646

And with 7 threads
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 8149 W: 1367 L: 1227 D: 5555

bench: 8639247
2015-11-03 11:27:00 +01:00
mbootsector
27c5cb5912 Pick bestmove from the deepest thread.
STC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 26930 W: 4441 L: 4214 D: 18275

LTC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 7783 W: 1017 L: 876 D: 5890

No functional change in single thread mode

Resolves #485
2015-11-02 10:05:43 +00:00
Marco Costalba
86f04dbcc0 Assorted trivia in search.cpp
The only interesting change is the moving of
stack[MAX_PLY+4] back to its original position
in id_loop (now renamed Thread::search).

No functional change.
2015-10-31 19:26:35 +01:00
VoyagerOne
aa242d2f84 New History Bonus Formula
bonus = d^2 + d - 1

Bench: 8639247

Resolves #484
2015-10-31 18:17:00 +00:00
Ajith
8d858783e1 Reduce variation in rootDepth between different threads
Reduce the variation in Root Depth between different threads. This
prevents threads from searching at a depth much higher than Main Thread.

Performed well at STC 24 Threads:
ELO: 3.44 +-3.8 (95%) LOS: 96.1%
Total: 10000 W: 1627 L: 1528 D: 6845

And LTC 24 Threads
LLR: 1.43 (-2.94,2.94) [0.00,4.00]
Total: 3804 W: 500 L: 420 D: 2884
ELO : +7.31
p-value: 73.16%

Passed no regression at STC 3 Threads:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 40457 W: 7148 L: 7060 D: 26249

And LTC 3 Threads:
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 17704 W: 2489 L: 2364 D: 12851

Raising a pull request early as 24 Thread tests are very expensive and
this is clearly a positive gain at high thread counts and high time
controls. The change is a small parameter tweak with no additional
logic.

No functional change for single thread mode.

Resolves #481
2015-10-29 17:06:13 -07:00
Stéphane Nicolet
80d7556af7 Some code and comment cleanup
- Remove all references to split points
- Some grammar and spelling fixes

No Functional change

Resolves #478
2015-10-29 15:28:59 +00:00
lucasart
00d9e9fd28 Use atomics instead of volatile
Rely on well defined behaviour for message passing, instead of volatile. Three
versions have been tested, to make sure this wouldn't cause a slowdown on any
platform.

v1: Sequentially consistent atomics

No mesurable regression, despite the extra memory barriers on x86. Even with 15
threads and extreme time pressure, both acting as a magnifying glass:

threads=15, tc=2+0.02
ELO: 2.59 +-3.4 (95%) LOS: 93.3%
Total: 18132 W: 4113 L: 3978 D: 10041

threads=7, tc=2+0.02
ELO: -1.64 +-3.6 (95%) LOS: 18.8%
Total: 16914 W: 4053 L: 4133 D: 8728

v2: Acquire/Release semantics

This version generates no extra barriers for x86 (on the hot path). As expected,
no regression either, under the same conditions:

threads=15, tc=2+0.02
ELO: 2.85 +-3.3 (95%) LOS: 95.4%
Total: 19661 W: 4640 L: 4479 D: 10542

threads=7, tc=2+0.02
ELO: 0.23 +-3.5 (95%) LOS: 55.1%
Total: 18108 W: 4326 L: 4314 D: 9468

As suggested by Joona, another test at LTC:

threads=15, tc=20+0.05
ELO: 0.64 +-2.6 (95%) LOS: 68.3%
Total: 20000 W: 3053 L: 3016 D: 13931

v3: Final version: SeqCst/Relaxed

threads=15, tc=10+0.1
ELO: 0.87 +-3.9 (95%) LOS: 67.1%
Total: 9541 W: 1478 L: 1454 D: 6609

Resolves #474
2015-10-25 09:15:45 +00:00
Marco Costalba
307a5a4f63 Cleanup history stats
And other assorted trivia.

No functional change.
2015-10-24 17:29:12 +02:00
VoyagerOne
4eca981e55 History pruning
Prune moves with negative History
and CMH scores at low depth.

STC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 24182 W: 4672 L: 4439 D: 15071

LTC:
LLR: 2.97 (-2.94,2.94) [0.00,5.00]
Total: 12579 W: 1959 L: 1792 D: 8828

bench: 8907701
2015-10-24 09:30:31 +02:00
Stefano80
328d314f2f Almost passed tuning attempts
Collect and give a second try to some almost passed tuning attempts and
one-line tweaks from the last month.

Passed STC

LLR: 3.07 (-2.94,2.94) [0.00,4.00]
Total: 15124 W: 2974 L: 2756 D: 9394

And LTC

LLR: 2.95 (-2.94,2.94) [0.00,4.00]
Total: 21577 W: 3507 L: 3289 D: 14781

Bench: 8855226

Resolves #464
2015-10-20 19:49:01 -07:00
mbootsector
ecc5ff6693 Lazy SMP
Start all threads searching on root position and
use only the shared TT table as synching scheme.

It seems this scheme scales better than YBWC for
high number of threads.

Verified for nor regression at STC 3 threads
LLR: -2.95 (-2.94,2.94) [-3.00,1.00]
Total: 40232 W: 6908 L: 7130 D: 26194

Verified for nor regression at LTC 3 threads
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 28186 W: 3908 L: 3798 D: 20480

Verified for nor regression at STC 7 threads
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 3607 W: 674 L: 526 D: 2407

Verified for nor regression at LTC 7 threads
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 4235 W: 671 L: 528 D: 3036

Tested with fixed games at LTC with 20 threads
ELO: 44.75 +-7.6 (95%) LOS: 100.0%
Total: 2069 W: 407 L: 142 D: 1520

Tested with fixed games at XLTC (120secs) with 20 threads
ELO: 28.01 +-6.7 (95%) LOS: 100.0%
Total: 2275 W: 349 L: 166 D: 1760

Original patch of mbootsector, with additional work
from Ivan Ivec (log formula), Joerg Oster (id loop
simplification) and Marco Costalba (assorted formatting
and rework).

Bench: 8116244
2015-10-20 06:58:08 +02:00
VoyagerOne
8fd34d7763 Combination of two ideas:
Apply bonus for the prior CMH that caused a fail low.

Balance Stats: CMH and History bonuses are updated differently.
This eliminates the "fudge" factor weight when scoring moves. Also
eliminated discontinuity in the gravity history stat formula. (i.e. stat
scores will no longer inverse when depth exceeds 22)

STC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 21802 W: 4107 L: 3887 D: 13808

LTC:
LLR: 2.96 (-2.94,2.94) [0.00,5.00]
Total: 46036 W: 7046 L: 6756 D: 32234

Bench: 7677367
2015-10-12 14:00:54 -07:00
Marco Costalba
ca38358574 Run PVS-STUDIO analyzer
Fix issues after a run of PVS-STUDIO analyzer.
Mainly false positives but warnings are anyhow
useful to point out not very readable code.

Noteworthy is the memset() one, where PVS prefers ss-2
instead of stack. This is because memeset() could
be optimized away by the compiler when using 'stack',
due to stack being a local variable no more used after
memset. This should normally not happen, but when
it happens it leads to very sublte and difficult
to find bug, so better to be safe than sorry.

No functional change.
2015-10-05 09:13:33 +02:00
Marco Costalba
3c0fe1d9b2 Rework lock protecting
When changing 'search' and 'splitPointsSize' we have to
use thread locks, not split point ones, because can_join()
is called under the formers.

Verified succesfully with 24 hours toruture tests with 20
cores machine by Louis Zulli: it does not hangs.

Verifyed for no regressions with STC, 7 threads:
LLR: 2.94 (-2.94,2.94) [-3.00,1.00]
Total: 52804 W: 8159 L: 8087 D: 36558

No functional change.
2015-09-30 10:47:20 +02:00
Joona Kiiski
613dc66c12 Careful SMP locking - Fix very occasional hangs
Louis Zulli reported that Stockfish suffers from very occasional hangs with his 20 cores machine.

Careful SMP debugging revealed that this was caused by "a ghost split point slave", where thread
was marked as a split point slave, but wasn't actually working on it.

The only logical explanation for this was double booking, where due to SMP race, the same thread
is booked for two different split points simultaneously.

Due to very intermittent nature of the problem, we can't say exactly how this happens.

The current handling of Thread specific variables is risky though. Volatile variables are in some
cases changed without spinlock being hold. In this case standard doesn't give us any kind of
guarantees about how the updated values are propagated to other threads.

We resolve the situation by enforcing very strict locking rules:
- Values for key thread variables (splitPointsSize, activeSplitPoint, searching)
can only be changed when the thread specific spinlock is held.
- Structural changes for splitPoints[] are only allowed when the thread specific spinlock is held.
- Thread booking decisions (per split point) can only be done when the thread specific spinlock is held.

With these changes hangs didn't occur anymore during 2 days torture testing on Zulli's machine.

We probably have a slight performance penalty in SMP mode due to more locking.

STC (7 threads):
ELO: -1.00 +-2.2 (95%) LOS: 18.4%
Total: 30000 W: 4538 L: 4624 D: 20838

However stability is worth more than 1-2 ELO points in this case.

No functional change

Resolves #422
2015-09-10 19:15:43 +01:00
gguliash
84a641b8bb A small code simplification
No functional change

Resolves #411
2015-08-30 19:58:32 +01:00
lucasart
7ad85fca6d Prune castling moves
Align the behaviour with reductions. Initially castling moves had to be
treated differently, because the SEE did not handle them correctly. But now it
does.

STC:
LLR: 2.96 (-2.94,2.94) [-3.00,1.00]
Total: 83750 W: 15722 L: 15711 D: 52317

LTC:
LLR: 2.95 (-2.94,2.94) [-3.00,1.00]
Total: 97183 W: 15120 L: 15115 D: 66948

bench 7759837

Resolves #403
2015-08-28 20:33:12 +01:00
lucasart
c052e03426 Retire dangerous flag
Replace by its value where it is used. Code is more clear that
way.

No functional change.

Resolves #402
2015-08-20 20:18:23 +01:00
Marco Costalba
68d61b80c6 Simplify IID depth formula
Restore original formula messed up during
half-ply removal.

STC
LLR: 4.11 (-2.94,2.94) [-3.00,1.00]
Total: 21349 W: 4091 L: 3909 D: 13349

LTC
LLR: 5.42 (-2.94,2.94) [-3.00,1.00]
Total: 52819 W: 8321 L: 8122 D: 36376

bench: 8040572
2015-07-30 09:54:25 +02:00