C语言,要求输入C语言一个12小时制时间,然后转化为24小时制时间,大一新学,请大神帮忙看看问题在哪里

  • 海鸟的种类约350种其中大洋性海鳥约150种。比较著名的海鸟有信天翁、海燕、海鸥、鹈鹕、鸬鹚、鲣鸟...

  • 无锡至少有两所正规大学: 1、江南大学 2、南京农业大学无锡渔业学院由于它不直接在无锡召本科生,所...

  • 目前我们的生活水平必竟非同以往.吃得好休息得好能量消耗慢,食欲比较旺盛活动又少,不知鈈觉脂肪堆积...

  • 关于三国武将的排名在玩家中颇有争论其实真正熟读三国的人应该知道关于三国武将的排名早有定论,头十位依...

  • 在主驾驶看看驾驶员左脚休息踏板那一块,方向杆下面那一块,再就是副驾驶脚那一块,休息踏板那。 汽车...

  • 您好!一般来说车辆年审时,车主必须要提供当年有效的交强险保单也就是说年审时间在交强险保单的有效期...

  • 公积金的那个银行卡是反映你从公积金的账户把资金转入后才可以看见的,你没有办理提取公积金的转入是暂时...

  • 根据《企业会计准则--固定资产》第8条规定:外购的固定资产的成本包括买价、增值税、进ロ关税等相关税费...

  • 银行啊! 个人无抵押贷款其实就是个人信用贷款!一般情况下个人信用贷款银行都是提供的,你的资质满足个人...

  • 在 快三Φ奖的号码中跨度3的号码最为均匀。当我们发现跨度3的号码遗漏达20期以上可以稳步加入。跨...

  • 各种彩票的玩法都有一定的规律。但规律是有阶段性的!在某一个阶段里会出现一点规律,不过这个规律有可...

  • 盲目跟从毫无主见,必输一直依赖计划也不是长久的法子,必须要自己一点一点去摸索出来这才是正确的生...

  • 一分快三开奖豹子号当期开奖号码:第3位×3+3牞结果除以10取余数,余数即为“下期”很可能出的号码!...

  • 一分快三开奖豹子号该技巧并不是时时都灵验的,作者总结了快3开售以来的历史数据该现象会阶段性出现,烸...

点击上方“朱小厮的博客”选擇“

做积极的人,而不是积极废人

一、Redis封装架构讲解

实际上NewLife.Redis是一个完整的Redis协议功能的实现但是Redis的核心功能并没有在这里面,而是在NewLife.Core里媔

Redis的核心功能就是有这两个类实现,RedisClient代表着Redis客户端对服务器的一个连接Redis真正使用的时候有一个Redis连接池,里面存放着很多个RedisClient对象

二、Test實例讲解Redis的基本使用

这里XTrace.UseConsole();是向控制台输出日志,方便调试使用查看结果

接下来看第一个例子Test1,具体的我都在代码中进行了注释大家可鉯看下:

Set的时候,如果是字符串或者字符数据的话Redis会直接保存起来(字符串内部机制也是保存二进制),如果是其他类型会默认进行json序列化然后再保存起来。

Get的时候如果是字符串或者字符数据会直接获取,如果是其他类型会进行json反序列化

Set第三个参数过期时间单位是秒。

vs调试小技巧按F5或者直接工具栏“启动”会编译整个解决方案会很慢(VS默认),可以选中项目然后右键菜单选择调试->启动新实例会呮编译将会用到的项目,这样对调试来说会快很多

大家运行调试后可以看到控制台输出的内容:向右的箭头=》是ic.Log=XTrace.Log输出的日志。

字典的使鼡:对象的话需要把json全部取出来,然后转换成对象而字典的话,就可以直接取某个字段

队列是List结构实现的,上游数据太多下游处悝不过来的时候,就可以使用这个队列上游的数据发到队列,然后下游慢慢的消费另一个应用,跨语言的协同工作比方说其他语言實现的程序往队列里面塞数据,然后另一种语言来进行消费处理这种方式类似MQ的概念,虽然有点low但是也很好用。

集合用的比较多的昰用在一个需要精确判断的去重功能。像我们每天有三千万订单这三千万订单可以有重复。这时候我想统计下一共有订单这时候直接數据库group by是不大可能的,因为数据库中分了十几张表这里分享个实战经验:

比方说揽收,商家发货了网点要把件收回来,但是收回来之湔网点不知道自己有多少货这时候我们做了一个功能,也就是订单会发送到我们公司来我们会建一个time_site的key的集合,而且集合本身有去重嘚功能而且我们可以很方便的通过set.Count功能来统计数量,当件被揽收以后我们后台把这个件从集合中Remove掉。然后这个Set中存在的就是网点还没囿揽收的件这时候通过Count就会知道这个网点今天还有多少件没有揽收。实际使用中这个数量比较大因为有几万个网点。

Redis中布隆过滤器詓重的,面试的时候问的比较多

数据库中不合法的时间处理:判断时间中的年份是否大于2000年,如果小于2000就认为不合法;习惯大于小于号鈈习惯用等于号这样可以处理很多意外的数据;

Set的时候最好指定过期时间,防止有些需要删除的数据我们忘记删了;

Redis异步尽量不用因為Redis延迟本身很小,大概在100us-200us再一个就是Redis本身是单线程的,异步任务切换的耗时比网络耗时还要大;

List用法:物联网中数据上传量比较大时,我们可以把这些数据先放在Redis的List中比如说一秒钟1万条,然后再批量取出来然后批量插入数据库中这时候要设置好key,可以前缀+时间对巳处理的List可以进行remove移除。

接下来看第四个例子我们直接做压力测试,代码如下:

运行的结果如下图所示:

测试就是进行get,set remove,累加等的操作夶家可以看到在我本机上轻轻松松的到了六十万,多线程的时候甚至到了一百多万

为什么会达到这么高的Ops呢?下面给大家说一下:

Bench会分根据线程数分多组进行添删改压力测试;

batch批大小分批执行读写操作,借助GetAll/SetAll进行优化

3、Redis中NB的函数来提升性能

上面的操作如果大家都掌握叻就基本算Redis入门了,接下来进行进阶如果能全然吃透,差不多就会比别人更胜一筹了

GetAll:比方说我要取十个key,这个时候可以用getall这时候Redis僦执行了一次命令。比方说我要取10个key那么用get的话要取10次如果用getall的话要用1次。1次getall时间大概是get的一点几倍但是10次get的话就是10倍的时间,这个賬你应该会算吧强烈推荐大家用getall。

setall与getall性能很恐怖官方公布的Ops也就10万左右,为什么我们的测试轻轻松松到五十万甚至上百万因为我们僦用了setall,getall。如果get,set两次以上建议用getall,setall。

比如执行10次命令会打包成一个包集体发过去执行这里实现的方式是StartPipeline()开始,StopPipeline()结束中间的代码就会以管道嘚形式执行

这里推荐使用更强的武器,AutoPipeline自动管道属性管道操作到一定数量时,自动提交默认0。使用了AutoPipeline就不需要StartPipeline,StopPipeline指定管道的开始結束了

Add:Redis中没有这个Key就添加,有了就不要添加返回false;

Replace:有则替换,还会返回原来的值没有则不进行操作。

三、Redis使用技巧经验分享

茬项目的Readme中,这里摘录下:

在ZTO大数据实时计算广泛应用200多个Redis实例稳定工作一年多,每天处理近1亿包裹数据日均调用量80亿次;

低延迟,Get/Set操作平均耗时200~600us(含往返网络通信);

大吞吐自带连接池,最大支持1000并发;

高性能支持二进制序列化(默认用的json,json很低效转成二进制性能会提升很多)。

在Linux上多实例部署实例个数等于处理器个数,各实例最大内存直接为本机物理内存避免单个实例内存撑爆(比方说8核心处理器,那么就部署8个实例)

把海量数据(10亿+)根据key哈希(Crc16/Crc32)存放在多个实例上,读写性能成倍增长

采用二进制序列化,而非常見的Json序列化

合理设计每一对Key的Value大小,包括但不限于使用批量获取原则是让每次网络包控制在1.4k字节附近,减少通信次数(实际经验几十k几百k也是没问题的)。

Redis客户端的Get/Set操作平均耗时200~600us(含往返网络通信)以此为参考评估网络环境和Redis客户端组件(达不到就看一下网络,序列化方式等等)

使用管道Pipeline合并一批命令。

Redis的主要性能瓶颈是序列化、网络带宽和内存大小滥用时处理器也会达到瓶颈。

在此我向大家嶊荐一个架构学习交流圈: 帮助突破J瓶颈 提升思维能力

以上经验源自于300多个实例4T以上空间一年多稳定工作的经验,并按照重要程度排了先后顺序可根据场景需要酌情采用。

3、缓存Redis的兄弟姐妹

Redis实现ICache接口它的孪生兄弟MemoryCache,内存缓存千万级吞吐率。

各应用强烈建议使用ICache接口編码设计小数据时使用MemoryCache实现;数据增大(10万)以后,改用Redis实现不需要修改业务代码。

四、关于一些疑问的回复

这一Part我们会来聊聊大数據中Redis使用的经验:

Q1:一条数据多个key怎么设置比较合理

A1:如果对性能要求不是很高直接用json序列化实体就好,没必要使用字典进行存储

Q2:隊列跟List有什么区别?左进右出的话用List还是用队列比较好

A2:队列其实就是用List实现的,也是基于List封装的左进右出的话直接队列就好。Redis的List结構比较有意思既可以左进右出,也能右进左出所以它既可以实现列表结构,也能队列还能实现栈。

Q3:存放多个字段的类性能一样吗

A3:大部分场景都不会有偏差,可能对于大公司数据量比较大的场景会有些偏差

Q4:大数据写入到数据库之后,比如数据到亿以上的时候统计分析、查询这块,能不能分享些经验

A4:分表分库,拆分到一千万以内

Q5:CPU为何暴涨?

A5:程序员终极理念——CPU达到百分百然后性能达到最优,尽量不要浪费最痛恨的是——如果CPU不到百分百,性能没法提升了说明代码有问题。

虽然Redis大家会用但是我们可能平时不會有像这样的大数据使用场景。希望本文能够给大家一些值得借鉴的经验

想知道更多?描下面的二维码关注我


喜欢就点个"在看"呗^_^

本文将首先解释内存访问粒度概念以便可以了解处理器如何访问内存。然后将进一步了解数据对齐的概念,并研究一些示例结构的内存布局在之前关于嵌入式C中结構的文章中,了解到重新排列结构中成员的顺序可以改变存储结构所需的内存量还将看到编译器在为结构成员分配内存时具有某些约束。这些约束被称为数据对齐要求允许处理器以可能出现在存储器布局中的一些浪费空间(称为“填充”)为代价来更有效地访问变量。計算机的内存系统可能比这里介绍的要复杂得多本文的目标是讨论在编写嵌入式系统时可能有用的一些基本概念。APn电子头条

内存访问粒喥APn电子头条

我们通常将内存设想为单字节存储位置的集合如图1所示。每个位置都有一个唯一的地址允许我们访问该地址的数据。APn电子頭条

但是处理器通常以大于一个字节的块形式访问内存。例如处理器可以以四字节块的形式访问内存。在这种情况下我们可以设想圖1中的12个连续字节,如下面的图2所示APn电子头条

你可能想知道这两种处理内存的方式之间有什么区别。使用图1处理器一次读取一个字节並向内存写入。请注意在读取内存位置或写入内存之前,我们需要访问该内存单元并且每次内存访问都需要一些时间。假设我们想要讀取图1中存储器的前八个字节对于每个字节,处理器需要访问内存并读取它因此,为了读取前八个字节的内容处理器将必须访问内存八次。APn电子头条

在图2中处理器一次读取4个字节并将其写入内存。因此为了读取前四个字节,处理器访问存储器的地址0并读取四个连續的存储位置(地址0到3)同样,要读取下一个四字节块处理器需要再次访问内存。它转到地址4并同时从地址4到7读取存储位置对于字節大小的块,需要8次内存访问来读取连续8个字节的内存但是,使用图2只需要两次内存访问。如上所述每次内存访问都需要一些时间。由于图2中所示的存储器配置减少了访问次数因此可以提高处理效率。处理器在访问内存时使用的数据大小称为内存访问粒度图2描绘叻具有四字节存储器访问粒度的系统。APn电子头条

内存访问边界APn电子头条

硬件设计人员经常采用另一种重要技术来提高处理系统的效率:它們限制处理器使其只能在某些边界访问内存。例如处理器可能仅能够在四字节边界上访问图2的内存,如图3中的红色箭头所示APn电子头條

这种边界限制会使系统显着提高效率吗?仔细看看假设我们需要读取地址为3和4的内存位置的内容(由图3中的绿色和蓝色矩形表示)。洳果处理器可以从任意地址开始读取一个四字节的块那么我们可以访问地址3并通过单个内存访问读取两个所需的内存位置。但是如上所述,处理器不能直接访问任意地址;相反它只在某些边界访问内存。那么如果处理器只能访问四字节边界它将如何读取地址3和4的内嫆?APn电子头条

由于内存访问边界限制处理器必须访问地址为0的内存位置并读取连续的四个字节(地址0到3)。接下来它必须使用移位操莋将地址3的内容与其他三个字节(地址0到2)分开。类似地处理器可以访问地址4并从地址4到7读取另一个四字节块。最后可以使用移位操莋将所需字节(蓝色矩形)与其他三个字节分开。APn电子头条

如果没有内存访问边界限制可以用一个内存访问读取地址3和地址4。但是边堺限制迫使处理器两次访问存储器。那么如果数据操作变得更加困难,为什么需要限制对某些边界的内存访问呢内存访问边界存在限淛,因为对地址进行某些假设可以简化硬件设计例如,假设一个内存块中的所有字节都需要32位来寻址如果将地址限制为四字节边界,那么32位地址中的两个最低有效位将始终为零(因为地址始终可以被4整除)因此,我们可以使用30位来寻址一个232字节的内存APn电子头条

数据對齐APn电子头条

既然已经知道基本处理器如何访问内存,那么下面就可以可以讨论数据对齐要求通常,任何K字节C数据类型必须具有K的倍数嘚地址例如,四字节数据类型只能存储在地址04,8...中; 它不能存储在地址1,23,5 ...... 这些限制简化了处理器和内存系统之间的接口硬件的设計APn电子头条

例如,考虑一个具有四字节内存访问粒度的处理器它只能以四字节边界访问内存。假设一个四字节变量存储在地址1如图4所示(四个字节对应四种不同的颜色)。在这种情况下我们需要两次内存访问和一些额外的工作来读取未对齐的四字节数据(“未对齐”指它被分成两个四字节块)。该过程如图所示APn电子头条

但是,如果将一个四字节变量存储在4的倍数的任何地址只需要一个内存访问來修改数据或读取数据。所以将K字节数据类型存储在K的倍数的地址可以提高系统的效率因此,C语言“char” 变量(只需要一个字节)可以存儲在任何字节地址但是一个双字节变量必须存储在偶数地址中。四字节类型必须从可被4整除的地址开始并且八字节数据类型必须存储茬可被8整除的地址。例如假设在特定机器上,“short”变量需要两个字节“int ”和“float” 类型占用四个字节,“long ”、“double”指针占用八个字节這些数据类型中的每一种通常应具有K的倍数的地址,其中K由下表给出APn电子头条

请注意,不同数据类型的大小可能因编译器和计算机体系結构的不同而不同sizeof()运算符是查找数据类型实际大小的最佳方法。APn电子头条

结构的内存布局APn电子头条

让我们检查一下结构的内存布局为32位计算机编译以下结构:APn电子头条

我们知道将分配四个内存位置来存储结构中的成员,并且内存位置的顺序将与声明成员的顺序相匹配第一个成员是一个单字节变量,可以存储在任何地址因此,第一个可用存储位置将分配给此变量假设,如图5所示编译器为此变量分配地址0。下一个成员是一个四字节数据类型只能存储在4的倍数地址。第一个可用的存储位置是地址4但是,这需要不使用地址1、2和3如你所见,数据对齐要求会导致内存布局中出现一些浪费空间(或填充)APn电子头条

下一个成员是e,它是一个单字节变量第一个可用嘚存储位置(图5中的地址8)分配给此变量。接下来我们到达f,这是一个双字节变量它可以存储在可被2整除的地址。第一个可用空间是哋址10如你所见,为了满足数据对齐要求将出现更多的填充。 APn电子头条

我们期望该结构占用8个字节但实际上它需要12个字节。有趣的是如果了解数据对齐要求,我们可能能够重新排列结构中成员的顺序使内存使用效率更高。例如让我们重写上面的结构,如下所示其中成员是从最大的到最小的。APn电子头条

在32位机器上上述结构的内存布局可能看起来像图6中所示的布局。APn电子头条

第一种结构需要12个字節而新排列只需要8个字节。这是一个显著的改进特别是在内存受限的嵌入式处理器环境中。另外请注意结构的最后一个成员后面可能有一些填充字节。结构的总大小必须能够被其最大成员的大小整除考虑以下结构:APn电子头条

在这种情况下,内存布局将如图7所示如伱所见,在内存布局的末尾添加了三个填充字节以将结构的大小增加到8个字节。这将使结构大小可以被结构中较大成员的大小整除(c成員这是一个四字节变量)。APn电子头条

处理器通常以大于一个字节的块形式访问内存这可以提高系统效率;处理器访问内存时使用的数據大小是处理器的内存访问粒度;处理器可能仅限于在某些边界(例如,在四字节边界)访问内存;存在这种内存访问限制因为对地址莋出某些假设可以简化硬件设计;通常,任何K字节C数据类型必须具有K的倍数的地址这些限制简化了处理器和内存系统之间的接口硬件的設计;数据对齐要求导致内存布局中出现一些浪费空间(或填充);结构的最后一个成员后面可以有一些填充字节,结构的总大小必须能被其最大成员的大小整除APn电子头条

*版权所有,转载请注明出处

我要回帖

更多关于 输入C语言 的文章

 

随机推荐