zoukankan      html  css  js  c++  java
  • mktime很慢就自己去实现一个吧

    mktime很慢就自己去实现一个吧

    标签(空格分隔): Linux C语言


    1. 前言

    • 最近遇到一个转换数据的程序,只是一些内存操作,但是程序表现的巨慢,导致上线之后要天天盯着是否正常。忍不了,就使用gprofiler分析了一波,发现的结果是一个时间转换上十分耗时(占比达到90%多)

    • mktime是用来把字符串时间(YYYYMMDD-HH:MM:SS)转换为unix时间戳的

    2. 慢的原因

    根据后面自己的测试和前辈说的总结下:

    • 根据我的测试发现,我自己写的函数都是在用户态下的耗时,而mktime的有一半时间是在内核态的耗时。
    • 前辈说:“这个函数有锁的。” 具体未知,有时间去探索下。

    3. 自己实现一个

    • 番外:转自漫画:程序员的日常:时间戳和时区的故事 
      1.时间戳:指的就是Unix时间戳(Unix timestamp)。它也被称为Unix时间(Unix time)、POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。因此,严格来说,不管你处在地球上的哪个地方,任意时间点的时间戳都是相同的。这点有利于线上和客户端分布式应用统一追踪时间信息。 
      2.时区:中国时区是东8区 
      时间戳.png-493.5kB

      时间戳相同的根本原因是因为时区,这么想,时间戳相同,那么我们可以转换自己本地时间的时候就需要一个偏移来,那就是时区的作用了。同样在实现本地时间字符串转换为时间戳的时候,也需要加入时区的偏移来还原时间戳。后面会在代码中说清楚。 
      UTC,GMT等时间参考:时间:UTC时间、GMT时间、本地时间、Unix时间戳

    • 实现 
      参考:“mktime” slow? use custom function. 
      主要实现是使用c语言的 struct tm结构体和时间戳时区关系来计算就好了。 
      代码是参考上面博主的,但是他的代码存在问题,比如时区的处理,还有闰年的处理上,自己实现之后使用脚本测试过一些日期和mktime对比是没有问题的。

    上代码如下: 
    代码下载:github——str_to_stamp.c

     1 #include <stdio.h>
     2 #include <time.h>
     3 
     4 /*字符串时间(YYYYMMDD-HH:MM:mm)转换为struct tm结构*/
     5 void str_to_tm(char *p_time, struct tm* m_tm)
     6 {
     7     if(p_time)
     8     {
     9         sscanf(p_time, "%4d%2d%2d-%d:%d:%d", &m_tm->tm_year,&m_tm->tm_mon,&m_tm->tm_mday,&m_tm->tm_hour,&m_tm->tm_min,&m_tm->tm_sec);
    10         m_tm->tm_mon -= 1;
    11         m_tm->tm_year -= 1900;
    12     printf("%4d%2d%2d-%d:%d:%d
    ", m_tm->tm_year,m_tm->tm_mon,m_tm->tm_mday,m_tm->tm_hour,m_tm->tm_min,m_tm->tm_sec);
    13     }
    14     else
    15     {
    16         printf("input time is null
    ");
    17         return ;
    18     }
    19 }
    20 
    21 /*时间结构转换为时间戳*/
    22 time_t time_to_stamp(const struct tm* ltm, int utc_diff)
    23 {
    24     const int mon_days[] = {31,28,31,30,31,30,31,31,30,31,30,31};
    25     long tyears,tdays,leap_years,utc_hrs;
    26     int is_leap;
    27     int i,ryear;
    28     
    29     //判断闰年
    30     ryear = ltm->tm_year + 1900;
    31     is_leap = ((ryear%100!=0 && ryear%4==0) || (ryear%400==0) ) ? 1 : 0;
    32     
    33     tyears = ltm->tm_year-70;  //时间戳从1970年开始算起
    34     if(ltm->tm_mon < 1 && is_leap==1 )
    35     {
    36         leap_years = (tyears + 2) / 4 - 1;  //1970年不是闰年,从1972年开始闰年
    37                                             //闰年的月份小于1,需要减去一天
    38     }
    39     else
    40     {
    41         leap_years = (tyears + 2) / 4 ;
    42     }
    43     
    44     tdays = 0;
    45     for(i=0; i<ltm->tm_mon; ++i)
    46     {
    47         tdays += mon_days[i];
    48     }
    49     tdays += ltm->tm_mday - 1;  //减去今天
    50     tdays += tyears * 365 + leap_years;
    51     utc_hrs = ltm->tm_hour - utc_diff;   //如上面解释所说,时间戳转换北京时间需要+8,那么这里反转需要-8
    52     
    53     return (tdays * 86400) + (utc_hrs * 3600) + (ltm->tm_min * 60) + ltm->tm_sec;
    54 }
    55 
    56 int main(int argc, char **argv)
    57 {
    58     char *ptime = argv[1];
    59     struct tm tt;
    60     int ltime = 0;
    61     int systime = 0;
    62     str_to_tm(ptime,&tt);
    63     ltime = time_to_stamp(&tt,8);
    64     printf("ltime=%d
    ",ltime);
    65     return 0;    
    66 }
  • 相关阅读:
    [HNOI2008]玩具装箱toy(dp+斜率优化)
    hdu 4597 Play Game(记忆化搜索)
    下载文件,ie文件名称乱码问题
    HDU 2138 How many prime numbers
    Codeforces Round #277 (Div. 2)---A. Calculating Function (规律)
    MapReduce-MulitipleOutputs实现自己定义输出到多个文件夹
    EFM8单片机与I2C外设通信
    linux杂谈(十一):LDAPserver的搭建
    Redis命令学习-string类型操作
    Java 实现单链表反序
  • 原文地址:https://www.cnblogs.com/panhao/p/6892037.html
Copyright © 2011-2022 走看看