Skip to content

Commit 17be156

Browse files
committed
Locking stats and lots of changes to make threads as fast as possible
1 parent a4c8431 commit 17be156

File tree

21 files changed

+586
-156
lines changed

21 files changed

+586
-156
lines changed

src/api.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
import json
88
import threading
99
import types
10+
import UserDict
1011

1112
import hlib.error
1213
import hlib.handlers
1314
import hlib.http.session
1415
import hlib.input
16+
import hlib.locks
1517
import hlib.log
1618

1719
# pylint: disable-msg=F0401
@@ -23,6 +25,26 @@
2325
lambda s: s.startswith('password')
2426
]
2527

28+
class APICookieStorage(UserDict.UserDict):
29+
def __init__(self):
30+
UserDict.UserDict.__init__(self)
31+
32+
self._lock = hlib.locks.RLock(name = 'API cookie storage')
33+
34+
def __getitem__(self, name):
35+
with self._lock:
36+
return UserDict.UserDict.__getitem__(self, name)
37+
38+
def __setitem__(self, name, value):
39+
with self._lock:
40+
UserDict.UserDict.__setitem__(self, name, value)
41+
42+
def __contains__(self, name):
43+
with self._lock:
44+
return UserDict.UserDict.__contains__(self, name)
45+
46+
_COOKIES = APICookieStorage()
47+
2648
class ApiIORegime(hlib.handlers.IORegime):
2749
@staticmethod
2850
def check_session():
@@ -252,7 +274,7 @@ def __init__(self, name, app):
252274
self.name = name
253275
self.app = app
254276

255-
self.lock = threading.Lock()
277+
self.lock = hlib.locks.Lock(name = 'API token cache')
256278
self.token_to_user = {}
257279

258280
def __getitem__(self, key):

src/cache.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import sys
88
import threading
99

10+
import hlib.locks
11+
1012
from hlib.stats import stats as STATS
1113

1214
class Cache(object):
@@ -16,7 +18,7 @@ def __init__(self, name, app):
1618
self.name = name
1719
self.app = app
1820

19-
self.lock = threading.RLock()
21+
self.lock = hlib.locks.RLock(name = 'Cache')
2022
self.objects = {}
2123

2224
self.stats_name = 'Cache (%s - %s)' % (self.app.name, self.name)

src/console.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import json
88
import os
99

10+
import hlib.locks
11+
1012
class HelpAction(argparse._HelpAction):
1113
def __init__(self, *args, **kwargs):
1214
super(HelpAction, self).__init__(*args, **kwargs)
@@ -42,6 +44,8 @@ def __init__(self, console, parser):
4244
self.parser.add_argument('--version', action = 'store_const', dest = 'action', const = 'version')
4345
self.parser.add_argument('--crash', action = 'store_const', dest = 'action', const = 'crash')
4446

47+
self.parser.add_argument('--locks', action = 'store_const', dest = 'action', const = 'locks')
48+
4549
def handler(self, args):
4650
if args.action == 'quit':
4751
self.console.stop()
@@ -51,6 +55,9 @@ def handler(self, args):
5155
if args.action == 'crash':
5256
os._exit(0)
5357

58+
if args.action == 'locks':
59+
hlib.locks.save_stats('lock_debug.dat')
60+
5461
class Command_Help(Command):
5562
def __init__(self, console, parser):
5663
super(Command_Help, self).__init__(console, parser)

src/database.py

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import hlib.console
1717
import hlib.error
18+
import hlib.locks
1819
import hlib.log
1920
from hlib.stats import stats as STATS
2021

@@ -30,7 +31,7 @@ def __init__(self, console, parser):
3031
self.parser.add_argument('--enable-lt', action = 'store_const', dest = 'action', const = 'enable-lt')
3132
self.parser.add_argument('--disable-lt', action = 'store_const', dest = 'action', const = 'disable-lt')
3233
self.parser.add_argument('--pack', action = 'store_const', dest = 'action', const = 'pack')
33-
self.parser.add_argument('--minimize-cache', action = 'store_const', dest = 'action', const = 'minimize-cache')
34+
self.parser.add_argument('--gc', action = 'store_const', dest = 'action', const = 'gc')
3435

3536
self.parser.add_argument('--name', action = 'store', dest = 'name')
3637

@@ -57,8 +58,8 @@ def handler(self, args):
5758
if args.action == 'pack':
5859
return self.__get_db_by_name(args.name).pack()
5960

60-
if args.action == 'minimize-cache':
61-
return self.__get_db_by_name(args.name).minimize_cache()
61+
if args.action == 'gc':
62+
return self.__get_db_by_name(args.name).globalGC()
6263

6364
if args.action == 'update-stats':
6465
return self.__get_db_by_name(args.name).update_stats()
@@ -134,8 +135,8 @@ def __init__(self, name, address, **kwargs):
134135
self.db = None
135136
self.root = None
136137

137-
self.log_transaction_handler = self.__log_transaction
138-
self.log_transaction_lock = threading.RLock()
138+
self.log_transaction_handler = self.__nolog_transaction
139+
self.log_transaction_lock = hlib.locks.RLock(name = 'Transaction logging setup')
139140

140141
self.kwargs = kwargs
141142

@@ -167,7 +168,7 @@ def on_request_finished(self, _):
167168
def is_opened(self):
168169
return self.db != None
169170

170-
def set_transaction_logging(self, enabled = True):
171+
def set_transaction_logging(self, enabled = False):
171172
with self.log_transaction_lock:
172173
if enabled:
173174
self.log_transaction_handler = self.__log_transaction
@@ -191,6 +192,9 @@ def connect(self):
191192
return (connection, self.root)
192193

193194
def log_transaction(self, *args, **kwargs):
195+
# Transaction logging is broken - because of locking - lock is required even for NOP action :(
196+
return
197+
194198
with self.log_transaction_lock:
195199
self.log_transaction_handler(*args, **kwargs)
196200

@@ -259,6 +263,24 @@ def pack(self):
259263
def minimize_cache(self):
260264
self.db.minimizeCache()
261265

266+
def localGC(self):
267+
hruntime.dbconn.cacheGC()
268+
hruntime.dbconn.cacheMinimize()
269+
270+
def poolGC(self):
271+
self.db._a()
272+
self.db.pool.availableGC()
273+
self.db.historical_pool.availableGC()
274+
self.db._r()
275+
276+
def globalGC(self):
277+
self.pack()
278+
279+
self.db._a()
280+
self.db.pool.availableGC()
281+
self.db.historical_pool.availableGC()
282+
self.db._r()
283+
262284
def update_stats(self):
263285
data = self.db.getActivityMonitor().getActivityAnalysis(divisions = 1)[0]
264286
connections = {}
@@ -271,18 +293,19 @@ def update_stats(self):
271293
'Info': data['info'],
272294
'Before': data['before']
273295
}
296+
i += 1
274297

275298
for data in self.db.cacheDetailSize():
276299
caches[data['connection']] = {
300+
'Connection': data['connection'],
277301
'Non-ghost size': data['ngsize'],
278302
'Size': data['size']
279303
}
280304

281-
with STATS:
282-
STATS.set(self.stats_name, 'Load', data['loads'] if 'loads' in data else 0)
283-
STATS.set(self.stats_name, 'Stores', data['stores'] if 'stores' in data else 0)
284-
STATS.set(self.stats_name, 'Connections', connections)
285-
STATS.set(self.stats_name, 'Caches', caches)
305+
STATS.set(self.stats_name, 'Load', data['loads'] if 'loads' in data else 0)
306+
STATS.set(self.stats_name, 'Stores', data['stores'] if 'stores' in data else 0)
307+
STATS.set(self.stats_name, 'Connections', connections)
308+
STATS.set(self.stats_name, 'Caches', caches)
286309

287310
class DBObject(persistent.Persistent):
288311
def __init__(self, *args, **kwargs):

0 commit comments

Comments
 (0)