Tải bản đầy đủ

Prentice hall optimizing c plus plus jul 1998 ISBN 0139774300

[NEXT]


ISBN:0-13-977430-0
Copyright1999byPrentice-HallPTR
Copyright2000byChrysalisSoftwareCorporation

Wouldyouliketodiscussinterestingtopicswithintelligent
people?Ifso,youmightbeinterestedinColloquy,theworld's
firstinternet-basedhigh-IQsociety.I'moneoftheRegentsofthis
society,andamresponsiblefortheemaillistandformembership
applications.Applicationinstructionsareavailablehere.

Imaginethatyouareabouttofinisharelativelylargeprogram,onethathas
takenafewweeksormonthstowriteanddebug.Justasyouareputtingthe
finishingtouchesonit,youdiscoverthatitiseithertoosloworrunsoutof
memorywhenyoufeeditarealisticsetofinputdata.Yousigh,andstartthetask
ofoptimizingit.
Butwhyoptimize?Ifyourprogramdoesn'tfitinmemory,youcanjustgetmore
memory;ifitistooslow,youcangetafasterprocessor.
IhavewrittenOptimizingC++becauseIbelievethatthiscommonattitudeis

incorrect,andthataknowledgeofoptimizationisessentialtoaprofessional
programmer.Oneveryimportantreasonisthatweoftenhavelittlecontrolover
thehardwareonwhichourprogramsaretoberun.Inthissituation,the
simplisticapproachofaddingmorehardwareisnotfeasible.
OptimizingC++providesworkingprogrammersandthosewhointendtobe
workingprogrammerswithapractical,real-worldapproachtoprogram
optimization.Manyoftheoptimizationtechniquespresentedarederivedfrom
myreadingofacademicjournalsthatare,sadly,littleknownintheprogramming
community.Thisbookalsodrawsonmynearly30yearsofexperienceasa
programmerindiversefieldsofapplication,duringwhichIhavebecome
increasinglyconcernedabouttheamountofeffortspentinreinventing


optimizationtechniquesratherthanapplyingthosealreadydeveloped.
Thefirstquestionyouhavetoansweriswhetheryourprogramneeds
optimizationatall.Ifitdoes,youhavetodeterminewhatpartoftheprogramis
theculprit,andwhatresourceisbeingoverused.Chapter1indicatesamethodof
attackontheseproblems,aswellasareal-lifeexample.
AlloftheexamplesinthisbookwerecompiledwithbothMicrosoft'sVisual
C++5.0andtheDJGPPcompiler,writtenandcopyrightedbyDJDelorie.The
lattercompilerisavailablehere.Thesourcecodefortheexamplesisavailable
here.IfyouwanttouseDJGPP,IrecommendthatyoualsogetRHIDE,an
integrateddevelopmentenvironmentfortheDJGPPcompiler,writtenand
copyrightedbyRobertHoehne,whichisavailablehere.
Allofthetimingsandprofilingstatistics,unlessotherwisenoted,weretheresult
ofrunningthecorrespondingprogramcompiledwithVisualC++5.0onmy
PentiumII233Megahertzmachinewith64megabytesofmemory.
Iamalwayshappytoreceivecorrespondencefromreaders.Ifyouwishto
contactme,thebestwayistovisitmyWWWhomepage.



Ifyouprefer,youcanemailme.

Intheeventthatyouenjoythisbookandwouldliketotellothersaboutit,you
mightwanttowriteanon-linereviewonAmazon.com,whichyoucandohere.
Ishouldalsotellyouhowthevarioustypefacesareusedinthebook.
HelveticaNarrowisusedforprogramlistings,fortermsusedinprograms,and
forwordsdefinedbytheC++language.Italicsareusedprimarilyfortechnical
termsthatarefoundintheglossary,althoughtheyarealsousedforemphasisin
someplaces.ThefirsttimethatIuseaparticulartechnicaltermthatyoumight
notknow,itisinboldface.


Now,onwiththeshow!


Dedication
Acknowledgements
Prologue
ASupermarketPriceLookupSystem
AMailingListSystem
CnURdThs(Qkly)?ADataCompressionUtility
FreeatLast:AnEfficientMethodofHandlingVariable-LengthRecords
HeavenlyHash:ADynamicHashingAlgorithm
Zensort:ASortingAlgorithmforLimitedMemory
Mozart,No.WouldYouBelieveGershwin?
AbouttheAuthor


ThisbookisdedicatedtoSusanPatriciaCaffeeHeller,thelightofmylife.
Withouther,thisbookwouldnotbewhatitis;evenmoreimportant,Iwouldnot
bewhatIam:ahappyman.


Acknowledgements
I'dliketothankallthosereaderswhohaveprovidedfeedbackonthefirsttwo
editionsofthisbook,especiallythosewhohavepostedreviewson
Amazon.com;theircontributionshavemadethisabetterbook.
I'dalsoliketothankJeffPepper,myeditoratPrentice-Hall,forhissupportand
encouragement.Withouthim,thisthirdeditionwouldneverhavebeen
published.
Finally,IwouldliketoexpressmyappreciationtoJohnP.LindermanatAT&T
LabsResearchforhishelpwiththecodeinthechapteronsortingimmensefiles.


Prologue

IntroductiontoOptimization
Whatisoptimizationanyway?Clearly,wehavetoknowthisbeforewecan
discusshowandwhyweshouldoptimizeprograms.



Definition
Optimizationistheartandscienceofmodifyingaworkingcomputerprogram
sothatitmakesmoreefficientuseofoneormorescarceresources,primarily
memory,diskspace,ortime.Thisdefinitionhasasometimesoverlookedbut
veryimportantcorollary(TheFirstLawofOptimization):Thespeedofa
nonworkingprogramisirrelevant.



AlgorithmsDiscussed
Radix40DataRepresentation,LookupTables1



DecidingWhethertoOptimize
Supposeyouhavewrittenaprogramtocalculatemortgagepayments;theyearly
runtakestenminutes.Shouldyouspendtwohourstodoubleitsspeed?Probably
not,sinceitwilltaketwenty-fouryearstopaybacktheoriginalinvestmentof
timeatfiveminutesperyear.2Ontheotherhand,ifyourunaprogramforthree
hourseveryworkingday,evenspendingthirtyhourstodoubleitsspeedwillpay
foritselfinonlytwentyworkingdays,oraboutamonth.Obviouslythelatterisa
muchbettercandidateforoptimization.Usually,ofcourse,thesituationisnot
nearlysounambiguous:evenifyoursystemisoverloaded,itmaynotbe
immediatelyapparentwhichprogramisresponsible.3Mygeneralruleisnotto
optimizeaprogramthatperformssatisfactorily.Ifyou(ortheintendedusers)
don'tbecomeimpatientwhilewaitingforittofinish,don'tbother.Ofcourse,if
youjustfeellikeindulginginsomerecreationaloptimization,that'sanother
matter.



WhyOptimizationIsNecessary
Assumingthatourprogramsaretoobig,ortooslow,whydon'twejustaddmore
memoryorafasterprocessor?Ifthatisn'tpossibletoday,thenthenext
generationofprocessorsshouldbepowerfulenoughtospareussuchconcerns.
Let'sexaminethisratherwidelyheldtheory.Althoughthepastisnotan
infallibleguidetothefuture,itiscertainlyonesourceofinformationaboutwhat
happenswhentechnologychanges.Agoodplacetostartistocomparethe
computersofthelate1970'swiththoseofthelate1990's.
Thefirstdiskette-basedcomputerIeverownedwasaRadioShackTRS-80
ModelIIITM,purchasedin1979.4Ithada4MHzZ80TMprocessor,48Kbytesof
memory,andBasicTMinROM.Thediskettesheldabout140Kbytesapiece.
Amongtheprogramsthatwereavailableforthismachinewerewordprocessors,
assemblers,debuggers,databases,andgames.Whilenoneofthesewereas
advancedastheonesthatareavailabletodayon80x86or680x0machines,most
ofthebasicfunctionswerethere.
ThePentiumIITMmachinesoftodayhaveatleast1000timesasmuchmemory
and20000timesasmuchdiskstorageandareprobably1000timesasfast.
Therefore,accordingtothistheory,weshouldnolongerneedtoworryabout
efficiency.
Recently,however,severalofthemajormicrocomputersoftwarecompanies
havehadseriousperformanceproblemswithnewsoftwarereleasesofboth
applicationprogramsandsystemprograms,astheyattemptedtoaddmoreand
morefeaturestothoseavailableinthepreviousversions.5ThisillustrateswhatI
calltheIronLawofProgramming:whenevermoreresourcesaremadeavailable,
amoreambitiousprojectisattempted.Thismeansthatoptimaluseofthese
resourcesisimportantnomatterhowfastorcapaciousthemachine.



WhyOptimizationIsOftenNeglected
Inviewofthissituation,whyhasoptimizationofapplicationprogramsnot
gainedmoreattention?Isuspectthatamajorreasonisthetremendousand
continuingchangeintherelativecostsofprogrammingtimeandcomputer
hardware.Toillustratethis,letusexaminetwosituationswherethesame
efficiencyimprovementisgained,butthesecondexampleoccursaftertwenty
yearsoftechnologicalimprovement.
Intheearly1970'saprogrammer'sstartingsalarywasabout$3perhour,andan
houroftimesharingconnecttimecostabout$15.Therefore,ifaprogram
originallytookonehourtoruneveryday,andtheprogrammerspentaweekto
reducethistimeby20%,inabouteightweekstheincreasedspeedwouldhave
paidfortheprogrammer'stime.
Inthelate1990's,thestartingsalaryisinthevicinityof$15perhour,andifwe
assumethatthedesktopcomputercosts$2500andisamortizedoverthreeyears,
theweeklycostofrunningtheunoptimizedprogramisabout$2.00.Holdingthe
otherassumptionsconstant,theoptimizationpaybacktimeisabout30years!6
Thislong-termtrendseemstofavorhardwaresolutionsforperformance
problemsovertheinvestmentofprogrammingeffort.However,theappropriate
strategyforperformanceimprovementofaprogramdependsonhowmuch
controlyouhaveoverthehardwareonwhichtheprogramwillrun.Theless
controlyouhaveoverthehardware,thegreatertheadvantageofsoftware
solutionstoperformanceproblems,asillustratedbythesituationsbelow.



ConsideringaHardwareSolution
Whileeveryoptimizationproblemisdifferent,herearesomegeneralguidelines
thatcanhelpyoudecidewhetheraddinghardwaretohelpyouwithyour
performanceproblemsmakessense.

1.Ifyouarecreatingasystemthatincludesbothsoftwareandhardware,
andyoucanimprovethefunctioningoftheprogram,easemaintenance,or
speedupdevelopmentatasmalladditionalexpenseforextrahardware
resources,youshouldalmostcertainlydoso.

Afewyearsago,Iwasinvolvedinaclassicexampleofthissituation.The
projectwastocreateapoint-of-salesystem,includingspecializedhardwareand
programs,thattiedanumberofterminalsintoacommondatabase.Sincethe
partofthedatabasethathadtobeaccessedrapidlycouldbelimitedtoabout1
1/2megabytes,Isuggestedthatweputenoughmemoryinthedatabaseserver
machinetoholdtheentiredatabase.Thatway,theresponsetimewouldbefaster
thanevenaverygoodindexingsystemcouldprovide,andtheprogramming
effortwouldbegreatlyreduced.Theadditionalexpensecametoabout$150per
system,whichwaslessthan3%ofthepriceofthesystem.Ofcourse,just
addinghardwaredoesn'talwaysmeanthatnosoftwareoptimizationisneeded.In
thiscase,asyouwillseebelow,addingthehardwarewasonlythebeginningof
theoptimizationeffort.

2.Ifyouarewritingprogramsforyourownuseononecomputer,andyou
canaffordtobuyamachinepowerfulenoughtoperformadequately,then
youmightverywellpurchasesuchamachineratherthanoptimizingthe
program.7
3.Ifyouarewritingaprogramthatwillberunningonmorethanone
computer,evenifitisonlyforinternaluseatyourcompany,theexpense
andannoyanceofrequiringtheotheruserstoupgradetheircomputersmay


outweighthedifficultyofoptimization.

4.Ifyourprogramistorunonmanycomputersatyourcompany,itis
almostalwaysagoodideatotrytooptimizeitratherthantorequireall
thoseuserstoupgradetheirhardware.

5.Ifyourprogramistobesoldintheopenmarkettorunonstandard
hardware,youmusttrytooptimizeit.Otherwise,theusersarelikelyto
rejecttheprogram.

Anexcellentexampleofwhathappenswhenyoutrytomakeanumberofusers
upgradetheircomputersistherelativelydisappointingsalesrecord(asofthis
writing)oftheWindowsNTTMoperatingsystem.
Inordertogetanyreasonableperformanceunderversion4.0ofWindowsNT
(thelatestextantasofthiswriting),youneedatleast64megabytesofmemory
andaPentiumII/233processor.Sincealmosttheonlypeoplewhohavesuch
machinesareprofessionalsoftwaredevelopers,thesalesofthisprogramtoother
usershavebeenmuchsmallerthanexpected.



CategoriesofOptimization
Therearetwobroadcategoriesofoptimization:usingabetteralgorithm,and
improvingtheimplementationofthealgorithmwearealreadyusing.Generally,
weshouldreplaceanalgorithmbyabetteroneassoonaspossible,asthis
usuallydoesnothinderunderstandingorlatermodificationoftheprogram.An
exampleistheuseofadistributioncountingsort(seeChaptermail.htm)in
preferencetoQuicksort.Ofcourse,ifweemploytheseefficientalgorithmsfrom
thestartofourprogrammingeffort,thenwearenotoptimizinginthestrictsense
ofourdefinition(changingaworkingprogramtomakeitmoreefficient).
However,theendresultisstillabetterprogramthanwewouldhaveobtained
otherwise.8Thesecondcategoryofoptimizationisthemodificationofthe
implementationofanexistingalgorithmtotakeadvantageofpeculiaritiesofthe
environmentinwhichitisrunningorofthecharacteristicsofthedatatowhichit
isapplied.Thistypeofmodificationoftenhastheunfortunatesideeffectof
makingthealgorithmmuchhardertounderstandormodifyinthefuture;italso
impairsportabilityamongdifferenthardwareandsoftwarearchitectures.
Therefore,suchanoptimizationshouldbepostponeduntilthelastpossible
moment,inordertoreduceitsnegativeeffectsonthedevelopmentand
maintenanceoftheprogram.ThisisanapplicationoftheFirstLawof
Optimization:don'ttrytooptimizeaprogram(inthestrictsenseofmodifyingan
existingprogram)untilitisworkingcorrectly.



FindingtheCriticalResource
Itmayseemobviousthat,beforeyoucanoptimizeaprogram,youhavetoknow
whatismakingitinefficient.Ofcourse,ifyourunoutofmemoryordiskspace
whileexecutingtheprogram,thisdeterminationbecomesmuchsimpler.
Dependingonwhichlanguageandmachineyouareusing,theremaybe
"profiling"toolsavailablewhichallowyoutodeterminewhereyourprogramis
spendingmostofitstime.These,ofcourse,aremostusefulwhentheproblemis
CPUtime,butevenifthatisnottheproblem,youmaystillbeabletofindout
that,e.g.,yourprogramisspending95%ofitstimeinthediskreadingand/or
writingroutines.Thisisavaluablecluetowheretheproblemlies.
However,evenifnoprofilerisavailableforyoursystem,itisn'thardtogather
someusefulinformationyourself.Onewaytodothisistoinsertacalltoa
systemtimerroutine(suchasclock()inANSIC)atthebeginningofthe
segmenttobetimedandanothercallattheendofthesegmentandsubtractthe
twotimes.Dependingontheresolutionofthetimer,thelengthoftheroutine,
andthespeedofyourprocessor,youmayhavetoexecutethesegmentmorethan
oncetogatheranyusefulinformation.Thisisillustratedinthereal-lifeexample
below.



DeterminingHowMuchOptimizationIsNeeded
Sometimesyourtaskissimplytomaketheprogramrunasfast(ortakeaslittle
memory)aspossible.Inthiscase,youmustusethemosteffectiveoptimization
available,regardlessoftheeffortinvolved.However,youoftenhave(orcanget)
aspecifictarget,suchasamemorybudgetof1.4megabytesforyourdata.Ifyou
canachievethisgoalbyrelativelysimplemeans,itwouldbeawasteofyour
timetotrytosqueezethelastfewkilobytesoutofthedatabyafancier
compressionalgorithm.Infact,itmaybeworsethanawasteoftime;thesimpler
algorithmmayalsohaveotherdesirablecharacteristics(otherthanitsraw
performance).
AgoodexampleofsuchasimplealgorithmistheRadix40datacompression
method(seeChaptersuperm.htm,Figuresradix40.00throughradix40.03),
whichis,onaverage,considerablylesseffectiveatreducingthesizeofadata
filethananumberofotherdatacompressionalgorithms.Ontheotherhand,itis
quitefast,requiresverylittlestorage,andalwaysproducesthesameamountof
outputforthesameamountofinput,whichmeansthatitscompression
efficiencycanbecalculatedexactlyinadvance.The(statistically)moreeffective
routinessuchasthoseusingarithmeticcodingtakemorememoryandmore
time,andtheygenerallyproducedifferentamountsofoutputforagivenamount
ofinput(dependingonwhathasgonebefore),sothattheircompression
efficiencycannotbepredictedexactly.(Infact,inrarecircumstances,they
produceoutputthatislargerthantheinput.)Thiscontextdependencealsomeans
thattheyaremoredifficulttouseinapplicationswhererandomaccessto
compresseddataisneeded.
Themoralisthatyoushouldusethesimplestalgorithmthatwillmeetyour
needs.Ifyoucandefineyourneedsprecisely,youprobablywon'thaveto
implementassophisticatedanalgorithmtosolveyourproblem,whichwillleave
youmoretimetoworkonotherareasthatneedimprovement.



AReal-LifeExample
Thepoint-of-saledatabaseprogramImentionedearlierisanexcellentexample
ofthefactthatoptimizationrarelyfollowsastraight-linepath.Thefirstproblem
wasthespeedofaccesstothedatabasebymultipleusers.Sincethesoftwareis
suppliedwithspecializedhardware,itwasreasonabletosolvethisproblemby
addingenoughmemorytoholdtheportionofthedatabasethatrequiresrapid
access.Myemployerdeterminedthat15,000invoicerecordsand5000customer
recordswouldbesufficient,resultinginamemoryrequirementofabout1.25
megabytes.Theexpenseofthisamountofmemorywaswithinreason.
Unfortunately,thatpartofmemory(conventionalmemory)whichallows
normalprogramaccessislimitedto640kilobytesonIBM-compatiblesystems
runningtheMS-DOSoperatingsystem,theenvironmentinwhichthisprogram
operated.Whileouractualhardwareallowedformorememory,itcouldbe
referencedonlyasexpandedmemory,whichcannotbeallocatedassimplyas
conventionalmemory.
Luckily,theproblemofusingexpandedmemoryfordatastoragehasbeen
addressedbylibrariesofroutineswhichallowanyparticular16Kbyte"page"of
expandedmemorytobeloadedwhenthedatainitarerequired.Storingthe
recordsinexpandedmemorysolvedthespeedproblembyeliminatingexcessive
diskI/O.
However,theamountofexpandedmemoryrequiredwasveryclosetothetotal
available.Intheverylikelyeventofaddingevenasinglefieldtotherecord
definition,therewouldnotbeenoughroomforalltherecords.Therefore,Ihad
toconsiderwaystoreducethespacetakenbytheserecords.
Themakeupofthedatabaseisimportanttothesolutionofthisnewproblem.It
consistsalmostentirelyof15,000invoicerecordsofapproximately35bytes
eachand5000customerrecordsofapproximately145byteseach.Fortunately,
themajorityofthefieldsinthecustomerrecordcontainedonlyuppercase
alphabeticcharacters,numericdigits,afewspecialcharacters(".",",",and"-"),
andspaces.ThislimitedcharactersetallowstheuseofRadix40compression,


whichpacksthreecharactersintotwobytes.(SeeChaptersuperm.htmformore
detailsonthisalgorithm).
However,thetimerequiredtoconvertthesefieldsfromASCIItoRadix40
representationseemedexcessive.Sometestingdisclosedthatconverting5000
recordscontaining6fieldsof12characterseachfromASCIItoRadix40ona33
MHzi386tookabout40seconds!9Althoughthemostcommonoperationsin
thissystemdonotrequirewholesaleconversion,itisrequiredinsuchcasesas
importinganold-styledatabaseintothisnewsystem,andsuchinefficiencywas
unacceptable.Somyspaceproblemhadbecomeaspeedproblemagain.
Iresolvedtoimprovethespeedofthisconversion(from1300microseconds/12
characterstring)asmuchaswaspractical,beforeproposingfurtherhardware
upgradestothesystem.Thefirstproblemwastodeterminewhichoperationwas
consumingthemostCPUtime.Examinationofthecode(Figureascrad1.cpp),
disclosedthatthetoupperfunctionwasbeingcalledforeverycharacterinthe
string,everytimethecharacterwasbeingexamined).Thisseemedanobvious
placetostart.

Firstversionofascii_to_Radix40routine(fromintro\ascrad1.cpp)(Figure
ascrad1.cpp)
codelist/ascrad1.00

Thepurposeofwritingtheloopinthiswaywastoavoidmakingchangestothe


Secondversionofascii_to_Radix40routine(fromintro\ascrad2.cpp)
(Figureascrad2.cpp)
codelist/ascrad2.00

Anotherpossibleareaofimprovementwastoreducetheuseofdynamicstringal

Icouldn'tseeanyobviouswaytoincreasethespeedofthisroutinefurther,until
Inoticedthatifthedatahadaboutthesamenumberofoccurrencesofeach


character,thelooptofigureoutthecodeforasinglecharacterwouldbe
executedanaverageof20timespercharacter!Couldthisbedispensedwith?
Yes,byallocating256bytesforatableofconversionvalues.10ThenIcould
indexintothetableratherthansearchingthestringoflegalvalues(seeFigure
ascrad4.cpp).Timingthisversionrevealedanimpressiveimprovement:93
microseconds/12characterstring.Thisfinalversionis14timesthespeedofthe
original.11

Fourthversionofascii_to_Radix40routine(fromintro\ascrad4.cpp)
(Figureascrad4.cpp)
codelist/ascrad4.00

Theuseofaprofilerwouldhavereducedtheeffortneededtodeterminethemaj


Summary
Inthischapter,Ihavegivensomeguidelinesandexamplesofhowtodetermine
whetheroptimizationisrequiredandhowtoapplyyouroptimizationeffort
effectively.Inthenextchapterwewillstarttoexaminethealgorithmsandother
solutionsthatyoucanapplyonceyouhavedeterminedwhereyourprogram
needsimprovement.


Footnotes
1. Ifyoudon'thavethetimetoreadthisbookinitsentirety,youcanturnto
Figuresioopt-processoroptinChapterartopt.htmtofindthealgorithmsbest
suitedtoyourproblem.
2. Actually,youwillneverbeahead;fiveminutessaved23yearsfromnowis
notasvaluableasfiveminutesspentnow.Thisisanalogoustothelotteryin
whichyouwinamilliondollars,buttheprizeispaidasonedollarayear
foramillionyears!
3. Thisisespeciallytrueonamultiusersystem.
4. MypreviouscomputerwasalsoaRadioShackcomputer,butithadonlya
cassetterecorder/playerfor"massstorage"!
5. Microsoftisthemostprominentexampleatthemoment;theresource
consumptionofWindowsNTTMisstillamatterofconcerntomany
programmers,eventhoughthemachinesthattheseprogrammersownhave
increasedinpoweratatremendousrate.
6. Thisexampleisactuallyquiteconservative.Theprogramthattookone
hourtorunonatimesharingterminalwouldprobablytakemuchlessthan
thatonacurrentdesktopcomputer;wearealsoneglectingthetimevalueof
thesavings,asnotedabove.
7. Ofcourse,ifyouroldmachineismorethantwoorthreeyearsold,you
mightwanttoreplaceitanyway,justtogetthebenefitoftheimproved
technologyavailabletoday.
8. Perhapsthiscouldbereferredtoasoptimizingthedesign.
9. Thisisworsethanitmaysound;theactualhardwareonwhichthesystem
runsismuchslowerthanthei386developmentmachineIwasusingatthe
time.
10. ThistableofconversionvaluescanbefoundinFigureradix40.00.
11. Ialsochangedthemethodofclearingtheresultarraytousememsetrather
thanaloop.


ASupermarketPriceLookupSystem



Introduction
Inthischapterwewilluseasupermarketpricelookupsystemtoillustratehowto
savestoragebyusingarestrictedcharactersetandhowtospeedupaccessto
recordsbyemployinghashcoding(or"scatterstorage")andcaching(or
keepingcopiesofrecentlyaccessedrecordsinmemory).Wewilllookitemsup
bytheirUPC(UniversalProductCode),whichisprintedintheformofa"bar
code"onvirtuallyallsupermarketitemsotherthanfreshproduce.Wewill
emphasizerapidretrievalofprices,asmaintenanceofsuchfilesisusuallydone
afterhours,whenspeedwouldbelesssignificant.



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay

×

×