Optimize a pickle string by removing unused PUT opcodes
(p)
| 2326 | # A pickle optimizer. |
| 2327 | |
| 2328 | def optimize(p): |
| 2329 | 'Optimize a pickle string by removing unused PUT opcodes' |
| 2330 | put = 'PUT' |
| 2331 | get = 'GET' |
| 2332 | oldids = set() # set of all PUT ids |
| 2333 | newids = {} # set of ids used by a GET opcode |
| 2334 | opcodes = [] # (op, idx) or (pos, end_pos) |
| 2335 | proto = 0 |
| 2336 | protoheader = b'' |
| 2337 | for opcode, arg, pos, end_pos in _genops(p, yield_end_pos=True): |
| 2338 | if 'PUT' in opcode.name: |
| 2339 | oldids.add(arg) |
| 2340 | opcodes.append((put, arg)) |
| 2341 | elif opcode.name == 'MEMOIZE': |
| 2342 | idx = len(oldids) |
| 2343 | oldids.add(idx) |
| 2344 | opcodes.append((put, idx)) |
| 2345 | elif 'FRAME' in opcode.name: |
| 2346 | pass |
| 2347 | elif 'GET' in opcode.name: |
| 2348 | if opcode.proto > proto: |
| 2349 | proto = opcode.proto |
| 2350 | newids[arg] = None |
| 2351 | opcodes.append((get, arg)) |
| 2352 | elif opcode.name == 'PROTO': |
| 2353 | if arg > proto: |
| 2354 | proto = arg |
| 2355 | if pos == 0: |
| 2356 | protoheader = p[pos:end_pos] |
| 2357 | else: |
| 2358 | opcodes.append((pos, end_pos)) |
| 2359 | else: |
| 2360 | opcodes.append((pos, end_pos)) |
| 2361 | del oldids |
| 2362 | |
| 2363 | # Copy the opcodes except for PUTS without a corresponding GET |
| 2364 | out = io.BytesIO() |
| 2365 | # Write the PROTO header before any framing |
| 2366 | out.write(protoheader) |
| 2367 | pickler = pickle._Pickler(out, proto) |
| 2368 | if proto >= 4: |
| 2369 | pickler.framer.start_framing() |
| 2370 | idx = 0 |
| 2371 | for op, arg in opcodes: |
| 2372 | frameless = False |
| 2373 | if op is put: |
| 2374 | if arg not in newids: |
| 2375 | continue |
| 2376 | data = pickler.put(idx) |
| 2377 | newids[arg] = idx |
| 2378 | idx += 1 |
| 2379 | elif op is get: |
| 2380 | data = pickler.get(newids[arg]) |
| 2381 | else: |
| 2382 | data = p[op:arg] |
| 2383 | frameless = len(data) > pickler.framer._FRAME_SIZE_TARGET |
| 2384 | pickler.framer.commit_frame(force=frameless) |
| 2385 | if frameless: |
nothing calls this directly
no test coverage detected
searching dependent graphs…