`
cloudeagle
  • 浏览: 104264 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类
最新评论

Friday Q&A 2013-10-11: Why Registers Are Fast and RAM Is Slow

 
阅读更多

http://www.mikeash.com/pyblog/friday-qa-2013-10-11-why-registers-are-fast-and-ram-is-slow.html


In the previous article on ARM64, I mentioned that one advantage of the new architecture is the fact that it has twice as many registers, allowing code load data from RAM less often, which is much slower. Reader Daniel Hooper asks the natural question: just why is RAM so much slower than registers?

Distance
Let's start with distance. It's not necessarily a big factor, but it's the most fun to analyze. RAM is farther away from the CPU than registers are, which can make it take longer to fetch data from it.

Take a 3GHz processor as an extreme example. The speed of light is roughly one foot per nanosecond, or about 30cm per nanosecond for you metric folk. Light can only travel about four inches in time of a single clock cycle of this processor. That means a roundtrip signal can only get to a component that's two inches away or less, and that assumes that the hardware is perfect and able to transmit information at the speed of light in vacuum. For a desktop PC, that's pretty significant. However, it's much less important for an iPhone, where the clock speed is much lower (the 5S runs at 1.3GHz) and the RAM is right next to the CPU.

Cost
Much as we might wish it wasn't, cost is always a factor. In software, when trying to make a program run fast, we don't go through the entire program and give it equal attention. Instead, we identify the hotspots that are most critical to performance, and give them the most attention. This makes the best use of our limited resources. Hardware is similar. Faster hardware is more expensive, and that expense is best spent where it'll make the most difference.

Registers get used extremely frequently, and there aren't a lot of them. There are only about 6,000 bits of register data in an A7 (32 64-bit general-purpose registers plus 32 128-bit floating-point registers, and some miscellaneous ones). There are about 8 billion bits (1GB) of RAM in an iPhone 5S. It's worthwhile to spend a bunch of money making each register bit faster. There are literally a million times more RAM bits, and those eight billion bits pretty much have to be as cheap as possible if you want a $650 phone instead of a $6,500 phone.

Registers use an expensive design that can be read quickly. Reading a register bit is a matter of activating the right transistor and then waiting a short time for the register hardware to push the read line to the appropriate state.

Reading a RAM bit, on the other hand, is more involved. A bit in the DRAM found in any smartphone or PC consists of a single capacitor and a single transistor. The capacitors are extremely small, as you'd expect given that you can fit eight billion of them in your pocket. This means they carry a very small amount of charge, which makes it hard to measure. We like to think of digital circuits as dealing in ones and zeroes, but the analog world comes into play here. The read line is pre-charged to a level that's halfway between a one and a zero. Then the capacitor is connected to it, which either adds or drains a tiny amount of charge. An amplifier is used to push the charge towards zero or one. Once the charge in the line is sufficiently amplified, the result can be returned.

The fact that a RAM bit is only one transistor and one tiny capacitor makes it extremely cheap to manufacture. Register bits contain more parts and thereby cost much more.

There's also a lot more complexity involved just in figuring out what hardware to talk to with RAM because there's so much more of it. Reading from a register looks like:

  1. Extract the relevant bits from the instruction.
  2. Put those bits onto the register file's read lines.
  3. Read the result.

Reading from RAM looks like:

  1. Get the pointer to the data being loaded. (Said pointer is probably in a register. This already encompasses all of the work done above!)
  2. Send that pointer off to the MMU.
  3. The MMU translates the virtual address in the pointer to a physical address.
  4. Send the physical address to the memory controller.
  5. Memory controller figures out what bank of RAM the data is in and asks the RAM.
  6. The RAM figures out particular chunk the data is in, and asks that chunk.
  7. Step 6 may repeat a couple of more times before narrowing it down to a single array of cells.
  8. Load the data from the array.
  9. Send it back to the memory controller.
  10. Send it back to the CPU.
  11. Use it!

Whew.

Dealing With Slow RAM
That sums up why RAM is so much slower. But how does the CPU deal with such slowness? A RAM load is a single CPU instruction, but it can take potentially hundreds of CPU cycles to complete. How does the CPU deal with this?

First, just how long does a CPU take to execute a single instruction? It can be tempting to just assume that a single instruction executes in a single cycle, but reality is, of course, much more complicated.

Back in the good old days, when men wore their sheep proudly and the nation was undefeated in war, this was not a difficult question to answer. It wasn't one-instruction-one-cycle, but there was at least some clear correspondence. The Intel 4004, for example, took either 8 or 16 clock cycles to execute one instruction, depending on what that instruction was. Nice and understandable. Things gradually got more complex, with a wide variety of timings for different instructions. Older CPU manuals will give a list of how long each instruction takes to execute.

Now? Not so simple.

Along with increasing clock rates, there's also been a long drive to increase the number of instructions that can be executed per clock cycle. Back in the day, that number was something like 0.1 of an instruction per clock cycle. These days, it's up around 3-4 on a good day. How does it perform this wizardry? When you have a billion or more transistors per chip, you can add in a lot of smarts. Although the CPU might be executing 3-4 instructions per clock cycle, that doesn't mean each instruction takes 1/4th of a clock cycle to execute. They still take at least one cycle, often more. What happens is that the CPU is able to maintain multiple instructions in flight at any given time. Each instruction can be broken up into pieces: load the instruction, decode it to see what it means, gather the input data, perform the computation, store the output data. Those can all happen on separate cycles.

On any given CPU cycle, the CPU is doing a bunch of stuff simultaneously:

  1. Fetching potentially several instructions at once.
  2. Decoding potentially a completely different set of instructions.
  3. Fetching the data for potentially yet another different set of instructions.
  4. Performing computations for yet more instructions.
  5. Storing data for yet more instructions.

But, you say, how could this possibly work? For example:

    add x1, x1, x2
    add x1, x1, x3

These can't possibly execute in parallel like that! You need to be finished with the first instruction before you start the second!

It's true, that can't possibly work. That's where the smarts come in. The CPU is able to analyze the instruction stream and figure out which instructions depend on other instructions and shuffle things around. For example, if an instruction after those two adds doesn't depend on them, the CPU could end up executing that instruction before the second add, even though it comes later in the instruction stream. The ideal of 3-4 instructions per clock cycle can only be achieved in code that has a lot of independent instructions.

What happens when you hit a memory load instruction? First of all, it is definitely going to take forever, relatively speaking. If you're really lucky and the value is in L1 cache, it'll only take a few cycles. If you're unlucky and it has to go all the way out to main RAM to find the data, it could take literally hundreds of cycles. There may be a lot of thumb-twiddling to be done.

The CPU will try not to twiddle its thumbs, because that's inefficient. First, it will try to anticipate. It may be able to spot that load instruction in advance, figure out what it's going to load, and initiate the load before it really starts executing the instruction. Second, it will keep executing other instructions while it waits, as long as it can. If there are instructions after the load instruction that don't depend on the data being loaded, they can still be executed. Finally, once it's executed everything it can and it absolutely cannot proceed any further without that data it's waiting on, it has little choice but to stall and wait for the data to come back from RAM..

Conclusion

  1. RAM is slow because there's a ton of it.
  2. That means you have to use designs that are cheaper, and cheaper means slower.
  3. Modern CPUs do crazy things internally and will happily execute your instruction stream in an order that's wildly different from how it appears in the code.
  4. That means that the first thing a CPU does while waiting for a RAM load is run other code.
  5. If all else fails, it'll just stop and wait, and wait, and wait, and wait.

That wraps things up for today. As always, Friday Q&A is driven by reader suggestions, so if you have a topic you'd like to see covered or a question you'd like to see answered, send it in!

Did you enjoy this article? I'm selling a whole book full of them. It's available for iBooks and Kindle, plus a direct download in PDF and ePub format. It's also available in paper for the old-fashioned. Click here for more information.

Comments:

One other wrinkle is that, in the event RAM is full, the OS starts paging, placing RAM pages on disk (and having to go to disk to read that memory again).

The iPhone doesn't have paging (last I checked, at least), and will terminate applications that go above their memory quota (and send a low-memory warning to them before doing so). General purpose computers don't have this flexibility and have to deal with applications requesting more memory than is available in RAM.

Anyway, paging isn't necessarily germane to an article about the iPhone's memory layout, but it has a pretty big effect on workstation performance.

RAM is farther away from the CPU than registers are, which can make it take longer to fetch data from it.

Indeed, registers are right inside the CPU so their effective distance is very small.
More properly, each processor core usually has its own register file, which usually is at least double than the actual visible register count to accomodate out-of-order instruction execution - so you can double your estimate of 6000 bits.
The stack pointer and program counter are also implemented as registers, so a CPU core profits a lot from having very fast registers.

It's worth noting that on a hyper-threading enabled CPU two threads can share the same execution resources. So you get two streams of likely non-dependent instructions coming from the decoder, and the CPU is free to interleave the instructions according to its rules. In software with a lot of memory read stalls (e.g. in-memory databases) that gives close to the theoretical maximum x2 speedup.

You missed explaining the most important detail, and the real culprit: it's not about distance or the speed of light/electricity, it's about THE DELAYS IN SIGNAL PROCESSING that occurs in the memory controller etc.

Even until the early 80s, many small computers used SRAM as main memory, in order not to have to deal with refresh (unlike modern memory modules, refresh circuity was not built into the memory or the controller, and had to be handled by either roll your own circuitry, or by the cpu itself). The lack of intermediate interface circuitry between the cpu and the main memory itself is also a cause for a lot of the latency between requests to main memory and when the data actually arrives (even discounting cpu cache). Even reading a single byte from main memory requires a multi stage process of sending an address to the right memory module (to allow for faster bus speeds and limit power consumption, even in the case of parallel busses 1) the address and data lines are multiplexed, and 2) the bus width is not big enough to send the entire memory address at one time. So even sending the request to the control circuitry on the main memory chip takes potentially hundreds of CPU clock cycles. This is orthogonal to the physical distance between the cpu and the memory. This is just step #4 in your list of accessing data from main memory.

Another few nits:
1) There are more registers than you give the cpu credit for. Even within a single core, and even discounting an architecture like SPARC which has a large windowing register file, all modern cpus have shadow registers which get mapped to the logical registers the code actually sees due to register renaming. This automatically increases the number of actual registers by several times

2) The power usage of CMOS SRAM is not actually that high. Like all other static CMOS circuitry, the actual power dissipation during steady state (when there are no transitions), is very low. In addition, up to multiple tens of MB of on chip cache in modern processors is of the same design. In fact, when considering the subthreshold leakage of deep submicron processes, the power consumption of DRAM, may be similar or higher to SRAM, particularly if the memory contents are not being changed (as DRAM must of course be constantly refreshed). In addition, in modern designs, aggressive clock gating of logic and cache blocks, as well as dynamic voltage and frequency scaling, means that one cannot categorically say that per unit storage, DRAM uses more power than SRAM (registers included). Your statement "The entire circuit sits idle most of the time, only requiring power when being read, or for occasional refreshes needed to recharge the capacitors.," is actually more true of SRAM than DRAM, as even "idle / unused DRAM must still be refreshed," even when the cpu's clock is not running (a la sleep mode).

The article is true as far as it goes, but unfortunately it ignores caching. All modern CPUs depend on caches to hide DRAM latency. Most modern CPUs have at least L1 and L2 caches and possibly a large L3 cache as well. These caches are often able to hide the large latencies to DRAM.

The effective DRAM access time is complex function of L1/L2/L3 cache hit/miss/snoop latencies combined with DRAM bank and page access patterns. The effective DRAM latency is much less than the worst case DRAM miss time.

A trick often used on the register starved Intel X86 (32 bit) architecture is to allocated a 64 byte cache line sized and aligned chuck of memory and use it for often used variables. A high rate of accesses will assure it will be in L1 most of the time. L1 access time is ~ 4 cycles which is pretty good and certainly much much better than the three to four decimal orders of magnitude worst case DRAM cache miss time.

from here:
http://www.mikeash.com/pyblog/friday-qa-2013-10-11-why-registers-are-fast-and-ram-is-slow.html

Core i7 Xeon 5500 Series Data Source Latency (approximate)
L1 CACHE hit, ~4 cycles
L2 CACHE hit, ~10 cycles
L3 CACHE hit, line unshared ~40 cycles
L3 CACHE hit, shared line in another core ~65 cycles
L3 CACHE hit, modified in another core ~75 cycles remote
remote L3 CACHE ~100-300 cycles
Local Dram ~60 ns
Remote Dram ~100 ns

You forgot about the number of specifiers per instruction. An instruction typically specifies two, three, four, or even five registers. A memory reference instruction can specify typically one memory location. This is possible because registers are implemented in a redundant, multi ported structure right inside the pipeline, usually in a dedicated pipe stage. The L1 cache can also be thought of as occupying its own pipe stage, but a memory reference instruction can specify only one location in that cache (modulo things like misaligned access, string operations, etc.)

It's not just the distance (compare register file to L1 cache), it's the size and design.

Another reason that having more registers is important is because they can be easily specified in an instruction. Specifying a particular register typically takes three to five bits (eight to thirty two registers), so an instruction can specify multiple registers, allowing for r1 += r2, r1 = r2 + r3, or perhaps even r1 = r2 * r3 + r4. Doing the same thing with memory locations would be more challenging because the interesting addressing modes require specifying a lot more than three to five bits.

But yes, fundamentally registers are fast because it is their job to be fast and because it is impossible to have everything be that fast.

Also a good question to ask on the same topic is why do most, in particular the establishment (I.E. CS education) ignore this fact and stick to the same old models from 1977?
The C++ OOP object model that focuses on code over data for example.

At least performance wise IMHO we should be thinking "data orientation".

That big white data elephant in the room gets ignored all too often.
Where the excuse is usually: "Your hardware should handle it, not my problem", "You mean you want to actually run something else at the same time?", or "That's too much work!".

I'll take low resource usage + quick and snappy style, over the big + bloated + slow (to load and, or, run).

Actually, the reading from the RAM part is much longer, you'll have to use the registers frequently in that step.

This is the first time I read one your posts, Mike, and it's really comforting that there is still one person out there who actually cares about software performance, down to the Assembly level.

My opinion is that many applications right now would run very well on a machine with just 64 MB of RAM, but the messiness level in the code as well as complete oblivion to optimization has lead us to the point that we're at right now.

By the way, I had no idea that the signal travels at the speed of light - does that mean we have reached the limits when it comes to processing power?

分享到:
评论

相关推荐

    大学生创新创业训练计划经验分享.zip

    大学生创新创业训练计划(以下简称为“大创计划”)是一项旨在提升大学生创新能力和创业精神的实践活动。通过这项计划,学生可以在导师的指导下,自主开展研究性学习和创业实践。下面我将分享一些关于大创计划的经验和建议。

    node-v12.22.3-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    毕业设计-The coding solutions of Leetcode and 剑指Offer using .zip

    这里为你收集整理了关于毕业设计、课程设计可参考借鉴的资料一份,质量非常高,如果你投入时间去研究几天相信肯定对你有很大的帮助。到时候你会回来感谢我的。 本资源是经过本地编译测试、可打开、可运行的项目、文件或源码,可以用于毕业设计、课程设计的应用、参考和学习需求,请放心下载。 祝愿你在这个毕业设计项目中取得巨大进步,顺利毕业! 但还需强调一下,这些项目源码仅供学习和研究之用。在使用这些资源时,请务必遵守学术诚信原则和相关法律法规,不得将其用于任何商业目的或侵犯他人权益的行为。对于任何因使用本资源而导致的问题,包括但不限于数据丢失、系统崩溃或安全漏洞,风险自担哦!

    【微信小程序毕业设计】宠物店商城系统开发项目(源码+演示视频+说明).rar

    【微信小程序毕业设计】宠物店商城系统开发项目(源码+演示视频+说明).rar 【项目技术】 微信小程序开发工具+java后端+mysql 【演示视频-编号:282】 https://pan.quark.cn/s/cb634e7c02b5 【实现功能】 本系统实现的是和宠物相关的信息管理和发布,加入了商品销售的功能。操作角色为管理员和用户、商家,管理员的功能为用户管理、商家管理、宠物分类管理、宠物信息管理、商品分类管理、宠物用品管理、项目类型管理、服务项目管理、宠物日志管理、订单管理等;用户的功能为购买宠物、商品、预约服务发表日志管理订单等。商家功能为提供宠物、宠物用品、宠物服务,管理订单和服务预约等。

    雷迪森的工具包(95分以上课程大作业).zip

    Java SSM项目是一种使用Java语言和SSM框架(Spring + Spring MVC + MyBatis)开发的Web应用程序。SSM是一种常用的Java开发框架组合,它结合了Spring框架、Spring MVC框架和MyBatis框架的优点,能够快速构建可靠、高效的企业级应用。 1. Spring框架:Spring是一个轻量级的Java开发框架,提供了丰富的功能和模块,用于开发企业级应用。它包括IoC(Inverse of Control,控制反转)容器、AOP(Aspect-Oriented Programming,面向切面编程)等特性,可以简化开发过程、提高代码的可维护性和可测试性。 2. Spring MVC框架:Spring MVC是基于Spring框架的Web框架,用于开发Web应用程序。它采用MVC(Model-View-Controller,模型-视图-控制器)的架构模式,将应用程序分为模型层、视图层和控制器层,提供了处理请求、渲染视图和管理流程的功能。 3. MyBatis框架:MyBatis是一个持久层框架,用于与数据库进行交互。它提供了一种将数据库操作与Java对象映射起来的方式,避免了手动编写繁琐的SQL语句,并提供了事务管理和缓存等功能,简化了数据库访问的过程

    node-v9.10.1.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于B2C的网上拍卖系统_秒杀与竞价.zip

    基于B2C的网上拍卖系统主要用于帮助人们应用互联网方便快捷买到自己所中意的商品,并参与到秒杀与竞拍当中。 主要功能包括: 1.前台模块 (1)普通用户登录/注册。 (2)分类查看商品(普通商品与促销商品) (3)查看商品详细信息 (4)查看秒杀商品 (5)查看竞拍商品 (6)将商品加入购物车 (7)购买,结算功能 (8)留言 2.后台模块 (1)修改密码 (2)商品管理: -- 编辑/删除 -- 设置/取消促销 (3)秒杀商品:设置/取消秒杀 (4)竞拍商品:设置/取消竞拍 (5)订单管理:查看订单 (5)留言管理:查看/删除留言 项目访问路径: 前台:http://localhost:8080/sale 后台:http://localhost:8080/sale/user/adminlogin

    【前端素材】大数据-政务大数据共享交换平台.zip

    大数据技术指的是用于处理和分析大规模数据集的技术和工具。以下是一些常见的大数据技术和工具: Hadoop:Apache Hadoop是一个用于分布式存储和处理大规模数据的开源框架。它包括Hadoop Distributed File System(HDFS)用于数据存储和MapReduce用于数据处理。 Spark:Apache Spark是一个快速、通用的集群计算系统,提供了比MapReduce更快的数据处理能力。它支持内存计算和更多复杂的数据处理流程。 NoSQL数据库:NoSQL数据库(如MongoDB、Cassandra等)则更适用于处理这类数据。 数据仓库:数据仓库是一个用于集成和分析大规模数据的存储系统,一些知名的数据仓库包括Snowflake、Amazon Redshift等。 数据湖:数据湖是一个存储结构化和非结构化数据的存储池,用于支持数据分析和机器学习应用。 机器学习:大数据技术也广泛应用于机器学习领域,支持大规模数据的模型训练和预测分析。 流式处理:针对实时数据处理需求,流式处理技术(如Apache Kafka、Apache Flink)可以实时。

    【前端素材】大数据-气象预报大数据平台.zip

    大数据技术指的是用于处理和分析大规模数据集的技术和工具。以下是一些常见的大数据技术和工具: Hadoop:Apache Hadoop是一个用于分布式存储和处理大规模数据的开源框架。它包括Hadoop Distributed File System(HDFS)用于数据存储和MapReduce用于数据处理。 Spark:Apache Spark是一个快速、通用的集群计算系统,提供了比MapReduce更快的数据处理能力。它支持内存计算和更多复杂的数据处理流程。 NoSQL数据库:NoSQL数据库(如MongoDB、Cassandra等)则更适用于处理这类数据。 数据仓库:数据仓库是一个用于集成和分析大规模数据的存储系统,一些知名的数据仓库包括Snowflake、Amazon Redshift等。 数据湖:数据湖是一个存储结构化和非结构化数据的存储池,用于支持数据分析和机器学习应用。 机器学习:大数据技术也广泛应用于机器学习领域,支持大规模数据的模型训练和预测分析。 流式处理:针对实时数据处理需求,流式处理技术(如Apache Kafka、Apache Flink)可以实时。

    数学模型算法多目标决策分析方法.pptx

    数学模型算法

    ############ 光电传感器的描述

    光电传感器

    node-v12.17.0-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    Web开发工具和方法课程的学术项目Java、Spring、Hibernate、Angular

    Java SSM项目是一种使用Java语言和SSM框架(Spring + Spring MVC + MyBatis)开发的Web应用程序。SSM是一种常用的Java开发框架组合,它结合了Spring框架、Spring MVC框架和MyBatis框架的优点,能够快速构建可靠、高效的企业级应用。 1. Spring框架:Spring是一个轻量级的Java开发框架,提供了丰富的功能和模块,用于开发企业级应用。它包括IoC(Inverse of Control,控制反转)容器、AOP(Aspect-Oriented Programming,面向切面编程)等特性,可以简化开发过程、提高代码的可维护性和可测试性。 2. Spring MVC框架:Spring MVC是基于Spring框架的Web框架,用于开发Web应用程序。它采用MVC(Model-View-Controller,模型-视图-控制器)的架构模式,将应用程序分为模型层、视图层和控制器层,提供了处理请求、渲染视图和管理流程的功能。 3. MyBatis框架:MyBatis是一个持久层框架,用于与数据库进行交互。它提供了一种将数据库操作与Java对象映射起来的方式,避免了手动编写繁琐的SQL语句,并提供了事务管理和缓存等功能,简化了数据库访问的过程

    云计算基础课件—云安全dr.pptx

    云计算基础课件—云安全dr.pptx

    jizu3.cod

    jizu3.cod

    线性规划模型及应用中的整数规划讲义.pptx

    数学模型算法

    JAVA毕业设计之医疗挂号管理系统(springboot+mysql)完整源码.zip

    医疗挂号管理系统是一款基于Spring Boot和MySQL的Java毕业设计项目,旨在为医院提供一个高效、便捷的挂号管理解决方案。该系统采用了当下流行的微服务架构,通过Spring Boot框架实现快速开发和部署,同时使用MySQL数据库进行数据存储和管理。 在技术方面,本项目主要使用了以下技术: Spring Boot:一个基于Spring框架的快速开发工具,可以简化项目的搭建、配置和部署过程,提高开发效率。 MySQL:一款开源的关系型数据库管理系统,用于存储和管理医疗挂号管理系统中的数据。 MyBatis:一款优秀的持久层框架,用于实现Java对象与数据库之间的映射关系,简化数据库操作。 Redis:一款高性能的键值对缓存数据库,用于缓存系统中的热点数据,提高系统性能。 Bootstrap:一款前端UI框架,用于构建响应式的用户界面,提高用户体验。 jQuery:一款轻量级的JavaScript库,用于简化前端开发,实现动态效果和Ajax交互。 在功能方面,医疗挂号管理系统主要包括以下模块: 用户注册与登录:用户可以注册并登录系统,创建个人账户。 医生信息管理:管理员可以添加、修改和删除医生信息,包括姓名、职称、科室等。 挂号管理:用户可以选择医生和就诊时间进行挂号,支持在线支付挂号费用。 挂号记录查询:用户可以查看自己的挂号记录,包括挂号时间、医生信息等。 取消挂号:用户可以在规定时间内取消挂号,系统将退还挂号费用。 预约提醒:系统会在预约就诊前通过短信或邮件提醒用户。 统计报表:管理员可以查看系统的挂号统计数据,包括每日挂号人数、各科室挂号人数等。 通过这些功能,医疗挂号管理系统为医院提供了一个便捷、高效的挂号管理解决方案,有助于提高医疗服务质量和患者满意度。

    基于C++ QT的航空订票系统 .zip

    基于QT的系统

    线性规划模型及应用中的单纯形方法讲义.pptx

    数学模型算法

    小程序-43-基于小程序的企业产品推广系统-源码.zip

    提供的源码资源涵盖了小程序应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

Global site tag (gtag.js) - Google Analytics