ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclccllccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcccclllclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllcclclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllcllllllllllllllclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllclllllllllclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllcllllllllllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclccllllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcclllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllllllcccccccccc:cclccclcccllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllclllllllllllllllllllllllllllllllllllllllllllllllllcc::;:..,;;ccccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcllllllllllllllllllllllllllllllllllllllllllllllllllllllllc,..';::::,;''',,,,;:clllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcccclllllcclllllllllllllllllllllllllllllllllllllllllllllllllll::c:,,,;;;;':::;.':,;:;;,,,;:cllllllllllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcclcclcllllllllllllllllllllllllllllllllllllllllllllllllllllc:clllll::clc,;,,,,;'..:::::c;':;;::::clllllllllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccclllclllcllllllllllclllllllllllllllllllllllllllllllllllc:clllllllllc::,:;;,,,,.'....,:,,::;''.. .,:;:clllllllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcccclccclcccllclllllllllllllllllllllllllllllllllllllllllllllllccllllllllllllll;;clllll,lll;'.'..',;',,;.,.;,:;'..;::cllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllcccllllllllllllllllllllllllllllllllllllllllllclllllllllllllllllllc::lll;lllc:;,...,;;',' ....;,..',,:;;;;,;cllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcccclcccccccccccccccllllllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllc::c,:;;::::''. ';:,,.,,;...,''::,:cc,';,,;;;;:clllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclccccccccccccccclccclllllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllc',:lllll,cc;...cl.c;.,;.c:.,;;,,;,,ccc;;:.;:;;;,,,;cllllllcclllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllll::clll;l;''.'';.,;c;;:.;;lcccl;'.,;;;;,.,;:;;;:ccllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclccllllllllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllc::l';.::c.,, .;,::::.'lllc;;'.,','',:lllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllll; ..,,::...,.;:;,.. ',,,;::cllclllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllllllllll'',,,;,:' ':.'::'.'clllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcllllllllllllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllllllllllll;c.,;:c:,.;:c'.,;c:clllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclccccccclclclclllllllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllllllllllllll,c:..,,:l.cc,';.;c;:lllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcccclccllccclclllllllllllllllllllllllllllllllllllllllllclllllllllllllllllllllllllllllllllllllllllllllllllc:l,'..;;c.;,cc;:';c:lllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcccccllccccccccllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllc:'.':,.c: .cccllc'';lllllllllllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccccccccccccclcllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllll;.:cl:lc.;.:.;lllll.'lllllllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllccccccccccccccllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllllll:,':lcl:c' ;l,;llc,,;lllloolllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllllllll:l:.;::c:' ;:c;,;;:o;looolllllllllllllllllllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccccccccccccccclllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllllllllllllllll;cc,...,cl.cc:,,.,c:,looooooolllllllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccccccccccccclllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll;cc,'.';:o.:;,:,,',c;looooolooolooooollollllllllllllllllll
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccccccccccccccclllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooo;l,':c;;c, .cl:llc,;;looooooooooooooollollllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllclccllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllloooloooll.',;,',,.' .',;:::;' coooooooooooooooooooolloolooooolooool
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllclllllllllllllllllllllllllllllllllllllllllllllllllllllllolollllcc:. .,.,;lo;' ,',llllc' .:loooooooooooooooooooooooooooooooooo
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllclllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllllllllllllool:;,,,;::l''';';,,:. .c;.loo,.'colcclooooooooooooooooooooooooooooooo
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllllll:,',::,,,',,.;:::loo'l'.c';l;, ',;'.:,;l;:oooolcccoooooooooooooooooooooooooooo
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllc;,',',;, . ...',,,;',;,,;'c;..',.cl :l:c..'::'.;ccccc::..:lllllllllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllccccccllllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllll,.'',.'''. ......,,...'.....'..'....... ........'. .oooool;.,:c::ooooooooooooooooooolll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllccccllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllll;:lc:';;;'...,';;;,,;.',::;''.. ......c;, ,,cl:cc'',.'';cc,.;..,;;.,::cllllllllllllllllll
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllllccccllllllllllllllllllllllllllllllllllllllllccllllllllllllllllllllllllllllllllllllllllllllll,.';..looool'cc:;,;;'.,:llll:c;.,.';.. . ;:;oooc,''lc,...,;cloocccoolcclooooooooooooooo
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccllcllllllllllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllll;..,..clooool,cllooooocc:;''''...;;'...... . .,...'.. ,cc'':';:lococ:oddool::loddooodooooo
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllcclllllllllllllllllllllllllllllllllllllllllllllll:.....;looooool,coooooooooooooooc. ''''.;;.. . ''.,''. ,;,.',':c:',ll:ddolllo:lccloodddddoo
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcccccccclcclclcclllllllllllllllllllllllllllllllllllllllllllllclllllllllllllllllllllllllllllllllollllllllllllc:'.''..coooooooll;coooooooooooooooo,;.,;:c';;. '. ... . ,,..,'. .'....;cloooo:odlc:cloooooo
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcllcllllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllolllollllll,'.....:,looooolooo:;oooooooooooooooo,ol. ',l:., ';cc. ..,'. ..'.',.cc:c.:;..';;,.::,,,;;',,;;;
ccccccccccccccccccccccccccccccccccccccccccccccccccclccccccccccccccccccccccccccllllllllllllllllllllllllllllllllllllllllllllllllllllllllcllllllllllllllllllllllllllllllllllllloooooooooc:'. ..',cl,loolloooooc,oooooooooooooood'llc. ..,oo :d;..; .c:.;:'..;;;;::,;.::::',,::';:::::,lolcl
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccclcclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllloooooooooo:c;..;,;ccol,clloooooool,oooooooooooddodd'ol'...';;: .',o;,:'.;,,odccdddolcc;';:;;c:c,,';cccc:'...',
ccccccccccccccccccccccccccccccccccccccccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllloololoooooooooooooooolll::.,':ooool::oooooooooo;looooooooooodddo.:..:cc..o; :o;ldl'. :dd:cdddddddo:dddlccccc'......,;;,c:
cccccccccccccccccccccccccccccccccccccccccccccccccccccccclllccclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooloooooooooooooooooooooollllcl:;::loollol;oooooooooo;loooooodoooodddl 'lloldd;.. '..ooc..:: ,dd::dddddddl;dddddddddooo;'':oddood
ccccccccccccccccccccccccccccccccccccccccccccccccccclcclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllloooloooooooooooooooooooooooooooooooolllllollocolclooool,ooolllccc:';loooooddddddddl..cloldo;c. .c;.;:oo;..;ddc:dddddddo;dddddddddoccoo:ddooodd
cccccccccccccccccccccccccccccccccccclcllclcccclclccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllolloooooooooooooooooooooooooooooooooooooolllllollooolcocoooooo,;c:cllloooolllllododddddddc'o..clc:o:. .,cc.,:''cc,ddc:dddddddo;ddddddo:.,oddo;ooodddd
ccccccccccccccccccccccccccccccclllllllllcllllcllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllollollollloloooooooooooooooooooooooooooooooooooooooooooolllllolloooooolocoooolc;,cooooooooooooodollllodddd:,dd'..,;.,; 'l:c:..;odl'ddl:oooooooolododo:.;odoooo;odddddd
ccccccccccccccccccccccccclccccccllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllooooooooollooooooooooooooooooooooooooooooooooooooooooooooolllllolloooooooolocooolclcoooooooooooooooodddddollcc''cc,. .,:oc ,d:',,,.cdo.dooodddddddddddoocodddodddo;ddddddd
ccccccccccccccccccccclllclllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllloloooooooooooooooooollooooooooooooooooooooooooooooooooooooooooooooooolllllollooooooooooollooococooooooooooooooooodddddddddd,;o,..;.'l;; .,cd:c:c''o.oddddddddddddoldddodddddddd:ddddddo
ccccccccccccccccccclllllllllllllllllllllllllllllllllllllllllllllllolloooollllolllllooolollooooolooooooooooooooooooollooooooooooooooooooooooooooooooooooooooooooooooollllloloooooooooooooololococooooooooooooodddoddddddddddd,;.';l:l;.o: :o;odddc'..ddddddddddooldddddodddddddd;ooooood
llllllllllllllllllllllllllllllllllllllllllllllllllllllloolooloolooooooooolooooooooooolooooooooooooooooooooooooooollooooooooooooooooooooooooooooooooooooooooooooooollllloloooooooooooooooooll:llloooooddodddodddddddddddddddd..lololddl.. '..odddddd' oddddddoodddddddddoodddddoooddddddd
llllllllllllllllllllllllllllllllllllllllllllllllllllloooooooooooooooooooooooooooooooooooooooooooooooooooooooooollooooooooooooooooooooooooooooooooooooooooooooooololllolooooooooooooooooooooloooodddddddddddddddddddddddddddo..'oloodo:l. .l:.cdddl'..oddddooddddddddddddooddoodddddddddd
llllllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooollooooooooooooooooooooooooooooooooooooooooooooooololloolooooooooooooddoddoddddddddddddddddddddddddddddddddddood.o;.,loc:o;. .ldo.,o,.'o'ldooddddddddddddddddddddddddddddddd
lllllllllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooollooloooooooooooddddddddddddddddddddddddddddddddddddddddoodddd.ddc .'c;'cl ,l:lo. ':dd,cddddddxxdddddddddddddddddddddddddd
lllllllllllllllllllllllllllllllllllllllllllolloooolooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooollooooooodododddddddddddddddddddddddddddddddddddddddddddoodddddd.dxo;...'dxo ,xd,.,,.;dd;:xxxxxxxxxxdddddddddddddddddddddddd
lllllllllllllllllllllllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooolloooooooddddddddddddddddddddddddddddddddddddddddddddddoodddddxxxo.xd;..,.c::l ,;.co,;:..d::xxxxxxxxxxxxxddddddddddddddddddddd
lllllllllllllllllllllllllllllllllllllllllloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodooooooooooooooooooooolloooooooddddddddddddddddddddddddddddddddddddddddddddddoodddddxxxxxl'o..,cl:.:o, :dc:dxoc'.';xxxxxxxxxxxxdddddddddddddddddddddd
lllllllllllllllllllllllllllllllllllllllolooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddddddooooooodoooooloooooodddddddddddddddddddddddddddddddddddddddddddddddooddddddxxxxxxxc..cooldxd.', ..,lxxxxxo; .dxxxxxxxxxxxxddddddddddddddddddddd
llllllllllllllllllllllllllllllllllllooolooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddoddoodddddddddddddddddddooooloooooddddddddddddddddddddddddddddddddddddddddddddddddodddddddddxxxxxxx; :xoolxxxc'. .;.;xxxxxxc..dxxxxxxxxxdddddddddddddddddddddddd
llllllllllllllllllllllllllllllooloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddddddddddddddddddddddddddddddooollooooddddddddddddddddddddddddddddddddddddddddddddddddooddddddddddddxxxxxd;;,':olxo:ld' 'xx;'oxxl'.c.xxxxxxxxdddddddddddddddddddddddddd
lllllllllllllllllllllllollolloooloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodoooddoooddddddddddddddddddddddddddddddooolloooodddddddddddddddddddddddddddddddddddddddddddddddoooddddddddddddddxddxxx,cdc.'cc:o;., .;ldl.;,,;dd.dxxxxxxddxdddddddddddddddddddddddd
llllllllllllllllllllloollooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddoddddddddddddddddddddddddddddooolloooddddddddddddddddddddddddddddddddddddddddddddddddoodddddddddddddddxxxxxxxx':lo:...''ldl ,xo;;...,lll.dxxxxxxxxxxxdddddddddddddddddddddd
lllllllllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooododoooddddddddddddddddddddddddddoooloooodddddddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddxxxxxxxxxd.:oo:,. ,:dxl ,xo'',.'.;lc.oxxxxxxxxxxxxxxxdddddddddddddddddd
lllllllllllllllllloolooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddoddddddddddddddddddddddddoooloooodddddddddddddddddddddddddddddddddddddddddddddddoodddddddddddddddxxdxxxxxxdddd.cx:...,.:c,: .';ol:':c',d lxxxxxxxxxxxxxxxxxdddddxxxddddddxx
llllllllllllllllllooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddoooooooodddddodddddddddddddddddddoooolooodddddddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddddxxdxxxddddxxd c''cd,lo.,c. :l:cx,do:'. cxxxxxxxxxxxxxxxxxxxdxxxxxxxxdxxxx
lllllllllllllloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddooooooooddooddddddddddddddddddddddooccloooddddddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddddddxxxxxddddxxxxc .:l:c,:;;,.. ..,llc;ccc:. ,dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
llllllollllloolloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddddddddddddddddddddddooolccloddddddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddddddxxxxddddxxxolll' .c;''.;ll:;. .:.,locoool' .:loxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
llllllloollloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddddddddddddddddddddoooloooodddddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddddddxxxxddddxdlllloxxo:.;.cl::,o:ll. .;oc.oxxd:.';;xxdllldxxxxxxxxxxxxxxxxxxxxxxxxxx
llloooooooollloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddddddddddddddddddoooloooddddddddddddddddddddddddddddddddddddddddddddddodddddddddddddddddddddxxxddddolllc,:l:;c;;:'xd..;l:'l;,: .,,:;.;:,,cxc,xxxxxxolloxxxxxxxxxxxxxxxxxxxxxxx
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddddddddddddddddddooooooodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddxdocc,..':cc:,c:oxxlx;'oxx;..:;':xo ,xo:;....cooc'xxxxxxxxxdllldxxxxxxxxxxxxxxxxxxx
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddddddddddddddddoooloooodddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddolccc,:,',,;: .. ...',':,';..',;,...;llcl ,xx:,;,;..';;.oododc,clccc:..codddddddddddddddd
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddddddddddddddddddddddoooooooodddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddd;.;,;'' ...... ',,.';c,cc:,..;.... .... ....''..'. c .'::;.':lccl:l;dolccodddddddddddd
ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddddddddddddddddddddddoooooooddddddddddddddddddddddddddddddddddddddddddddoddddddddddddddddddddd::lc;.lddolc::,.',;:;;c,ccccc.'.,;..,:',' .. 'c:;odo;. ...:;.,,..'coo:ld;ddddoccccddddddddd
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodooddddddddddddddddddddoooooooodddddddddddddddddddddddddddddddddddddddddddooddddddddddddddddddddddo' .;.'dddxxxxxd::dddoc:,;,.',, .;lc,, .. .,,....',. ,:;'oc;,ll;oxx:xxxxdooccllldxxxxx
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooddoodddoddddddddddddddddddooooooooddddddddddddddddddddddddddddddddddddddddddoodddddddddddddddddddddddo,.....cddddxxxxxxl;dxxxxxxxxxxxd; ,,'.'.:;,'. ....,:',,,,. .,,:,,,...';lo:xdoodxxolxxxolloxx
oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooodddodddddoddddddddddddddddddlooodooddddddddddddddddddddddddddddddddddddddddddoodddddddddddddddddddddddcc. '. ,ddddxxxxxxxxo;dxxxxxxxxxxxxx...xxccc,o:.. c; ...;co;. .;:,. ... .:dxxxxdcxxxxdl;,o
Django performance optimization diagram Background# Building a POS system that handles inventory, sales, and real-time reporting presented multiple performance bottlenecks. With a PostgreSQL database and a Django backend, early performance issues arose due to inefficient query patterns, redundant updates, and excessive database hits.
Initial Problems# 1. Slow Bulk Updates # Updating multiple records individually in Django was inefficient. Consider this naïve approach:
for product in products:
product. stock -= 1
product. save()
This triggered a separate UPDATE query for each product, significantly slowing down batch operations.
2. Signal Overhead # Django signals were initially used to track stock changes, but they fired on every save, leading to unnecessary computations.
@receiver (post_save, sender= Sale)
def update_inventory (sender, instance, ** kwargs):
product = instance. product
product. stock -= instance. quantity
product. save()
With high transaction volumes, this became a major bottleneck.
3. Redundant Queries # Certain parts of the system, such as product conversion rates (e.g., unit-based conversions), recalculated values every time instead of caching them.
def get_conversion_rate (product):
return ConversionRate. objects. get(product= product). rate
Optimizations Implemented# 1. Using bulk_update for Efficiency # Instead of saving each instance separately, Django’s bulk_update was used to update multiple rows efficiently.
Product. objects. bulk_update(products, ['stock' ])
This reduced the number of queries from N to 1.
2. Replacing Signals with Direct Updates # Instead of relying on Django signals, updates were performed explicitly in views or services:
Sale. objects. create(product= product, quantity= 5 )
Product. objects. filter(id= product. id). update(stock= F('stock' ) - 5 )
By using F expressions, updates were performed in a single SQL statement, improving efficiency.
3. Caching Frequently Accessed Data # For product conversion rates, a caching mechanism using Django’s built-in cache framework was introduced:
from django.core.cache import cache
def get_conversion_rate (product):
cache_key = f 'conversion_rate_ { product. id} '
rate = cache. get(cache_key)
if rate is None :
rate = ConversionRate. objects. get(product= product). rate
cache. set(cache_key, rate, timeout= 3600 ) # Cache for 1 hour
return rate
This reduced redundant database hits and significantly improved response times.
Results# Bulk updates reduced update time from seconds to milliseconds. Eliminating unnecessary signals lowered database write load. Caching reduced redundant queries, leading to faster response times in product-related calculations. Final Thoughts# Performance tuning in Django requires a mix of bulk operations, query optimization, and caching. Understanding when to use Django’s ORM features efficiently can prevent unnecessary database load and keep the application responsive. This approach significantly improved the speed of a POS system handling thousands of transactions daily.