Posts in category performance

Benchmarking the WMI2 HTTPS

I wanted to know if the WMI2 can handle some correct traffic. It's a management interface, so I don't expect it to undergo real pressure, but we need a minimum.

Testing was performed on my development Virtual Machine, running on my MacbookAir? (late 2010):

cat /proc/cpuinfo

processor	: 1
model name	: Intel(R) Core(TM)2 Duo CPU     L9400  @ 1.86GHz
cpu MHz		: 1860.000
cpu cores	: 2

free

             total       used       free     shared    buffers     cached
Mem:       1536928    1453196      83732          0       8500     101312
-/+ buffers/cache:    1343384     193544
Swap:      1570812     648604     922208

I first tried  Apache Benchmark, but it showed a lot of SSL read failed - closing connection without any reason: all seems OK on the server side. Anyway, the results:

ab -n 1000 -c 50 -r https://localhost:3356/login/

[...]
SSL read failed - closing connection
SSL read failed - closing connection
[ more SSL errors ]
Completed 1000 requests
Finished 1000 requests

Server Software:        
Server Hostname:        localhost
Server Port:            3356
SSL/TLS Protocol:       TLSv1/SSLv3,AES256-SHA,2048,256

Document Path:          /login/
Document Length:        0 bytes

Concurrency Level:      50
Time taken for tests:   35.158 seconds
Complete requests:      1000
Failed requests:        1000
   (Connect: 0, Receive: 0, Length: 1000, Exceptions: 0)
Write errors:           0
Total transferred:      4601000 bytes
HTML transferred:       4075000 bytes
Requests per second:    28.44 [#/sec] (mean)
Time per request:       1757.888 [ms] (mean)
Time per request:       35.158 [ms] (mean, across all concurrent requests)
Transfer rate:          127.80 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      129 1332 275.7   1381    1896
Processing:    14  387 278.8    373    1171
Waiting:       14  387 278.8    372    1171
Total:        373 1719 302.8   1740    2464

Percentage of the requests served within a certain time (ms)
  50%   1740
  66%   1821
  75%   1908
  80%   1945
  90%   2073
  95%   2172
  98%   2283
  99%   2431
 100%   2464 (longest request)

Reading  this, I decided to switch to  HTTPerf, and it worked a lot better:

httperf --max-connections 50 --max-piped-calls 10 --num-conns 1000 --ssl \
    --server localhost --port 3356

httperf --client=0/1 --server=localhost --port=3356 --uri=/ \
    --max-connections=50 --max-piped-calls=10 --send-buffer=4096 \
    --recv-buffer=16384 --ssl --num-conns=1000 --num-calls=1
httperf: warning: open file limit > FD_SETSIZE; limiting max. # of open files to FD_SETSIZE
Maximum connect burst length: 1

Total: connections 1000 requests 1000 replies 1000 test-duration 62.415 s

Connection rate: 16.0 conn/s (62.4 ms/conn, <=1 concurrent connections)
Connection time [ms]: min 39.5 avg 62.4 max 155.0 median 59.5 stddev 12.3
Connection time [ms]: connect 15.8
Connection length [replies/conn]: 1.000

Request rate: 16.0 req/s (62.4 ms/req)
Request size [B]: 62.0

Reply rate [replies/s]: min 13.8 avg 15.9 max 17.2 stddev 1.2 (12 samples)
Reply time [ms]: response 7.3 transfer 39.4
Reply size [B]: header 226.0 content 0.0 footer 2.0 (total 228.0)
Reply status: 1xx=0 2xx=0 3xx=1000 4xx=0 5xx=0

CPU time [s]: user 12.99 system 39.78 (user 20.8% system 63.7% total 84.5%)
Net I/O: 4.5 KB/s (0.0*10^6 bps)

Errors: total 0 client-timo 0 socket-timo 0 connrefused 0 connreset 0
Errors: fd-unavail 0 addrunavail 0 ftab-full 0 other 0

So, these are just bare numbers for a no-real-at-all test, but at least the server responded successfully without crashing, which is fine for a quick test in a development branch. I can continue coding!

New inotifier (v4) finished, and a bunch of (small but cool) new features

I'm proud to announce the new inotifier rewrite (and its bunch of small enhancements), internally and lovely named "hopefully-this-one-will-work-as-expected" (private joke to me). It's shorter than previous version in terms of codelines, albeit more complex when dealing with special cases (large directories, multiple concurrent accesses to same files, re-born just-deleted files or dirs, etc). The new version is many times faster than all previous ones (including the external C-implemented gamin one). When you untar an archive, you can expect more or less the time of the untar process, after it finished, for complete ACLs application. Previously, it could take minutes to do the same (specifically when untarring the linux kernel in a shared dir). licornd is also very smart when talking about resources-consumption: it takes the CPU for ACLs intensive tasks (but only ONE CPU), and doesn't take it long. For what it has to do, I find it well balanced from the functionnality/resource point of view.

The new inotifier and related core.classes additions allow users homes to be watched now, and offer dedicated functionnalities to handle configuration files, and report *real* changes to them (not 'all access', generating a lot of false positives).

dnsmasq backend, privileges directly benefit from this new functionnalities. shadow configuration files watch is more robust and verifies everything when they reload (one could create inconsistencies, editing the files manually; this is taken in account).

There are still some rough edges and evil sub-sonic bugs (perhaps they are all the same, I can't hunt it down for now), but only on very-very heavily loaded systems, where users and groups pop in an out very fast. I will fix them in the next coding cycle.

Hopefully, you won't need the chk group command anymore. If you do, please provide a full trace:

export LTRACE=std
licornd -rvD

<whatever command in your other terminal>

In the new-but-small-but-cool features category, you'll find the command fuzzy matching:

get u
get us
get usr
get users

(and so one, with identical counterparts for add/mod/del/chk)

Will bring you the list of users. In the same kind:

get g     -> groups
get pro   -> profiles
get pri   -> privileges
get kw    -> keywords

And so on. Everything is computed when you type it, there are no so-called "fixed values".

In the not-so-small-but-very-cool category, you will find that every part of Licorn® is now fully multi-lingual, on-the-fly: the daemon starts in the system lang, but every thread inside of it can switch to another language, and the client languages are pulled in from the web headers or the calling CLI environment. This makes everything dynamic, at will.

Documentation has been updated for permissions parts.

French tranlation is progressing notably: WMI part is finished, CLI is 90% done, and the rest is more or less 70% done (it doesn't matter anyway, as no user really sees it in real life).

I voluntarily don't mention the core object rewrite. It's very technical and doesn't bring new end-users functionalities, but guarantees that everything is cleaner and easier to extend inside licornd, regarding the users/groups/profiles/privileges/machines point of view.

I probably forgot many things here, but if I had written a book, you won't have read it anyway. Code and *use* the code is better. Many bugs have been fixed, and the code is generally more pythonic and lighter tht before: there are more generators, less hard-coded things, and abstractions (when necessary) got in the right places. At least, this how I wanted to implement them.

Enjoy,